Czy „Law of Demeter” ma zastosowanie do podpisów metod publicznych / API?

10

Biorąc pod uwagę, że zmiany w sygnaturze API / metody publicznej powinny być minimalne, aby zapobiec łamaniu kodów klientów korzystających z tych metod, zastanawiałem się, czy prawo Demetera w mniejszym stopniu się do nich stosuje.

Prosty przykład:

class Account() {
   double balance;
   public void debit(Transaction t) {
      balance -= t.getAmount();
   }
}

Zauważ, że metoda debetowa przekazuje obiekt Transakcji zamiast podwójnej kwoty („Prawo Demetera”, jak rozumiem, powiedziałoby, aby przekazać wymagane informacje, w tym przypadku tylko kwotę, a nie obiekt Transakcji ... ). Powodem tego jest to, że metoda w przyszłości może wymagać innych właściwości Transakcji oprócz kwoty. Z tego, co rozumiem, zapobiegnie to złamaniu podpisu metody przez dodanie nowego parametru w przyszłości.

Czy to sprawia, że ​​jest to rozsądny wybór? A może coś mi brakuje?

Carlos Jaime C. De Leon
źródło

Odpowiedzi:

3

Ale to nie łamie prawa Demeter.

Bardziej formalnie, prawo Demetera dla funkcji wymaga, aby metoda M obiektu O mogła wywoływać tylko metody następujących rodzajów obiektów:

  • O sama
  • Parametry M.
  • wszelkie obiekty utworzone / utworzone w M
  • Bezpośrednie obiekty składowe O.
  • zmienna globalna, dostępna dla O, w zakresie M

Wikipedia: Law of Demeter

Transakcja jest argumentem dla metody debetowej, więc wywołanie t.getAmount () jest w porządku.

Edycja: Źle to zrozumiałeś, mówisz, że LoD wymaga, abyś przekazał kwotę transakcji, a nie obiekt Transakcji. Jeśli tak, to tak, myślę, że jest to dobre miejsce, aby to przerwać, wiedząc, że będziesz potrzebować więcej od obiektu Transakcji w przyszłości. Również enkapsulowanie prymitywów w obiektach na poziomie domeny to kolejna dobra praktyka programowania.

Edycja 2: Po przeczytaniu może potrzebować więcej w przyszłości, można również uznać to za niepotrzebne złocenie. Wystarczy podać metodę, która teraz przyjmuje podwójną wartość (lub lepiej klasę Money). Jeśli później potrzebujesz argumentu Transakcja, nie jest katastrofalne dostarczenie drugiego podpisu zawierającego Transakcję, ale nadal obsługuje oryginalny podpis. To nie tak, że zastosowałbyś dwie metody, jedna nazwałaby drugą.

Sean
źródło
Dzięki za wkład. Zgadzam się na temat enkapsulacji operacji podstawowych w obiektach domeny. Jednak tylko w Edycji 2 mówisz, że dodanie nowego drugiego podpisu nie jest katastrofalne, ale oznaczałoby to zmianę kodu na kod klienta, który powinien teraz przekazać 2 parametry zamiast jednego. W tym drugim punkcie waham się, czy zgodzić się na ...
Carlos Jaime C. De Leon
Zgadzam się, edycja 2 jest subiektywna.
Sean
0

Jeśli planujesz poszerzyć Accountklasę w przyszłości, powiedziałbym, że jest to sytuacja, w której uczynienie Transactionobiektu bardziej ogólnym celem byłoby dobrym zgięciem przepisów Prawa.

Na przykład:

public class Amount {

    public void process( Transaction t ) {
        ....
    }
}

public abstract class Transaction {

    public String getType();

}

Myślę, że trochę zbaczam z pierwotnego pytania, ale mam na myśli to, że chociaż możesz się martwić, że zbłądzisz z Prawa Demetera, zalety takiego postępowania przeważają nad negatywnymi.

chooban
źródło