Skip to content

Funkcje – ZK #3

Nadmiar argumentów

Docelowo funkcja powinna zawierać jak najmniej argumentów wejściowych (parametrów). Idealną sytuacją jest moment, gdy mamy ich.. 0 (słownie: zero). Powinniśmy starać się pisać metody, które nie zawierają więcej niż 3 parametry. Ich większa liczba jest potencjalnym źródłem błędów, a także po prostu źle wygląda. Jeżeli funkcja wymaga więcej niż dwóch czy też trzech argumentów oznacza to, iż najprawdopodobniej powinniśmy je wyodrębnić do osobnej klasy.

Argumenty wyjściowe

Argumenty wyjściowe są z reguły mało intuicyjne. Użytkownik zakłada raczej, że argumenty będą wejściem, a nie wyjściem. Jeżeli funkcja coś zmienia, to powinien być to stan jej własnego obiektu. W językach obiektowych na szczęście zazwyczaj możliwym jest uniknięcie stosowania tego typu argumentów. Zamiast pisać funkcje typu x, która wisi w kodzie i przyjmuje argumenty niewiadomego typu, co wymusza na nasz konieczność dodatkowego sprawdzenia deklaracji funkcji, powinniśmy rozważyć odpowiednie zastosowanie obiektowej struktury kodu z wykorzystaniem dziedziczenia.

Więc zamiast:

.
.
foo(arg); // wtf is that?
.
.

Powinniśmy napisać:

.
.
object.foo();
.
.

Argumenty znacznikowe

Wykorzystywanie argumentów znacznikowych (czyli parametrów typu boolean) w wielu przypadkach jest brzydkie i niepraktyczne. Wynika to m.in. z faktu, iż argument taki na wstępie podkreśla, że funkcja wykonuje więcej niż jedną operację (osobne operacje dla wartości true lub false). Jeżeli więc mamy możliwość rozbicia takiej funkcji na dwie osobne – zróbmy to!

Martwe funkcje

Martwe funkcje to takie, które nie się nigdy wykorzystywane. Nie powinniśmy ich przetrzymywać w kodzie. Niepotrzebnie sztucznie pompują jego objętość oraz odwracają uwagę programisty. Nie bójmy się ich usuwać, w końcu będą one zapamiętane przez VCS. Jednym z pryncypiów XP (programowania ekstremalnego) jest zasada YAGNI.  Brzmi ona You aren’t gonna need it. Martin Fowler na swojej stronie opisuje ją tak (zachęcam do zapoznania się z całością):

Yagni originally is an acronym that stands for „You Aren’t Gonna Need It”. It is a mantra from ExtremeProgramming that’s often used generally in agile software teams. It’s a statement that some capability we presume our software needs in the future should not be built now because „you aren’t gonna need it”.

Oznacza to, że nie powinniśmy implementować rzeczy, których nie potrzebujemy w tym momencie. Dlaczego o tym wspominam? Ponieważ nawet nowa, świeżo napisana funkcja, której nie wykorzystujemy jest martwa!

1 funkcja = 1 operacja

Każda z pisanych przez nas funkcji powinna wykonywać tylko jedną operację. Podejście takie prowadzi do większej modularyzacji kodu co sprawia, że jest on bardziej elastyczny i łatwiejszy w zrozumieniu. Prostszym jest rozszyfrowanie dużej ilości niewielkich i czytelnych funkcji (dodatkowo opatrzonych precyzyjnymi nazwami opisowymi), niż jedną dużą funkcję wykonującą kilka operacji.

Poniższy fragment kodu wykonuje 3 operacje: przeglądanie listy listy obiektów klasy Recipient, sprawdzenie zmiennej served, a następnie utworzenie obiektu klasy Transfer i rozpoczęcie transferu na rzecz obiektu klasy Recipient:

public void start() {
  for (Recipient r : recipients) {
    if (r.isNotServed()) {
      Transfer transfer = r.calculateTransfer();
      r.start(transfer);
    }
  }
}

Powinno się rozbić go na trzy pomniejsze bloki:

public void start() {
  for (Recipient r : recipients) {
    startTransferIfNecessary(r);
  }
}

private void startTransferIfNecessary(Recipient r) {
  if (r.isNotServed()) {
    calculateAndStartTransfer(r);
  }
}

private void calculateAndStartTransfer(Recipient r) {
  Transfer transfer = r.calculateTransfer();
  r.start(transfer);
}

Informacje na temat cyklu i źródeł:

Facebooktwitterredditlinkedinmail
Published inProgramowanie