2008-10-02 15 views
60

Urządzenie Law of Demeter wskazuje, że należy mówić tylko do obiektów, o których wiesz bezpośrednio. Oznacza to, że nie należy wykonywać połączeń łańcuchowych, aby rozmawiać z innymi obiektami. Gdy to zrobisz, tworzysz niewłaściwe powiązania z obiektami pośredniczącymi, nieprawidłowo coupling Twój kod na inny kod.Sprzężenie, spójność i prawo Demeter

To jest złe.

Rozwiązanie byłoby dla klasy, o której wiesz, że w zasadzie eksponuje proste opakowania, które delegują odpowiedzialność na obiekt, z którym ma związek.

To dobrze.

Ale wydaje się, że klasa ma niską wartość cohesion. Nie jest już po prostu odpowiedzialna za dokładnie to, co robi, ale ma również delegatów, którzy w pewnym sensie powodują, że kod staje się mniej spójny poprzez duplikowanie fragmentów interfejsu związanego z nim obiektu.

To jest złe.

Czy to naprawdę prowadzi do obniżenia spójności? Czy to mniejsze zło?

Czy jest to jeden z tych szarej strefy rozwoju, gdzie można debatować, gdzie jest linia, lub czy istnieją mocne, pryncypialne sposoby podejmowania decyzji, gdzie narysować linię i jakie kryteria można użyć do podjęcia tej decyzji ?

+0

Podczas krótkiego tematu zdecydowanie polecam Ted Faisons "Programowanie oparte na zdarzeniach: podejmowanie wydarzeń do granic możliwości" [link] (http://books.google.co.uk/books?id=9CL446IzhuAC&pg=PA38&lpg= PA38 i dq = zdarzenia + rozdział + jeden + sprzężenie & źródło = bl & ots = qmJTOuCz90 & sig = EZKvZBjF8QmGohatC97HsmAqG0c & hl = en & ei = wj6tTqe5LcTX8gON_YyiCw & sa = X & oi = wynik_kolekcji & ct = wynik & resnum = 6 & ved = 0CEMQ6AEwBQ # v = onepage & q = events% 20chapter% 20one% 20coupling & f = false). Daje dobry podział na typowe problemy z połączeniem i daje dobry system dawania pomiaru ilości sprzężenia w danym systemie. –

+0

W przypadku naruszenia LoD, to czy dodatkowe połączenia są ** "niewłaściwe" zależy od natury połączone klasy **: Jeśli są one bardzo widoczne (myślę Row, Column, Cell w implementacji Excela), sprzężenie z nimi jest bezproblemowe, a LoD jest nadmiernie restrykcyjna. Podobnie, jeśli omawiane klasy są celowo zwykłymi klasami danych z zasadniczo żadnym zachowaniem. –

Odpowiedz

43

Grady Booch w "Object Oriented Analysis and Design":

„Idea spójności pochodzi również od uporządkowanego projektowania Krótko mówiąc, spójności mierzy stopień łączności między elementami jednego modułu (i . w przypadku projektowania obiektowego, pojedynczej klasy lub obiektu) Najmniej pożądaną postacią spójności jest przypadkowa spójność, w której całkowicie niezwiązane abstrakcje są wrzucane do tej samej klasy lub modułu, na przykład rozważmy klasę obejmującą psy i statki kosmiczne, których zachowania są zupełnie niezwiązane. jest spójnością funkcjonalną, w której elementy lub wszystkie moduły współpracują ze sobą, aby zapewnić pewne dobrze ograniczone zachowanie. Zatem Dog klasa jest funkcjonalnie spójna, jeśli jego semantyka objąć zachowanie psa, cały psa, i tylko pies.”

Subsitute Pies z Klientem w wyżej i może być nieco jaśniejsze. Tak więc celem jest po prostu dążenie do spójności funkcjonalnej i odejście od przypadkowej spójności w jak największym stopniu.Zależnie od twoich abstrakcji, może to być proste lub może wymagać pewnego refaktoryzacji

Uwaga spójność dotyczy w równym stopniu "moduł" niż do pojedynczej klasy, czyli grupy klas pracujących razem, więc w tym przypadku klasy Klient i Zamówienie zachowują przyzwoitą spójność, ponieważ mają tak silną relację, klienci tworzą zamówienia, zamówienia należą do cus tomers.

Martin Fowler mówi, że byłby bardziej komfortowo nazywając go „Sugestia Demeter” (patrz artykuł Mocks aren't stubs):

„Mockist testerów mów więcej o unikanie«wraki pociągów»- łańcuchy metoda stylu getThis(). getThat(). getTheOther() Unikanie łańcuchów metod jest również znane jako przestrzeganie prawa Demeter, podczas gdy łańcuchy metod są zapachem, przeciwny problem średnich obiektów wypełnianych metodami przekazywania jest również zapachem. Zawsze czułem, że będę lepiej czuć się z Prawem Demeter, jeśli nazywa się to Propozycją Demeter.) "

Ta suma ładnie, skąd pochodzę: jest całkowicie do przyjęcia i często konieczne jest mieć niższy poziom spójności niż ścisłe przestrzeganie "prawa" może wymagać. Należy unikać przypadkowej spójności i dążyć do spójności funkcjonalnej, ale nie należy odkładać słuchawek w miejscach, gdzie są one potrzebne, aby w bardziej naturalny sposób pasować do abstrakcji projektu.

+1

Podoba mi się ta odpowiedź, zdaje się sugerować, że jest to szara rzecz. Więc, jeśli mogę sparafrazować, czy argumentowałbyś, że tak długo, jak długo będziesz utrzymywał wysoką spójność w przedmiotach, dopuszcza się pogwałcenie Prawa Demeter? –

+0

Absolutnie, to dobry sposób na umieszczenie go. BTW, czy widziałeś JQuery, łańcuchy wywołań metod 3+ poziomy są wspólne. Chociaż może być w innym kontekście (bardziej proceduralnym), ktoś pochodzący z JQuery mówi, że Java/C#/C++ będzie miał wiele złych nawyków, aby "oduczyć się"! – Ash

+1

Jeśli mogę zasugerować, aby dodać ten punkt do swojego posta (o tym, że dobrze jest naruszać prawo Demeter) ... teraz jest to najlepsza odpowiedź jaką widziałem. –

0

W sytuacjach, w których wydaje się, że istnieje związek pomiędzy sprzężeniem a spójnością, prawdopodobnie zadałbym sobie pytanie "czy ktoś już napisał tę logikę, a ja szukałem w niej błędu, gdzie powinienem najpierw zajrzeć ? "i napisać kod w ten sposób.

20

Jeżeli naruszenie Prawo Demeter poprzez

int price = customer.getOrder().getPrice(); 

rozwiązanie nie jest stworzyć getOrderPrice() i przekształcenia kodeksu

int price = customer.getOrderPrice(); 

ale zamiast zwrócić uwagę, że jest to a code smell i dokonać odpowiednich zmian, które, mam nadzieję, zwiększą zarówno spójność, jak i niższe sprzężenie. Niestety nie ma tutaj prostego refaktoryzacji, która zawsze ma zastosowanie, ale prawdopodobnie powinieneś zastosować tell don't ask

+4

Link do "powiedz, nie pytaj" jest wart przeczytania. Dziękuję Ci! –

+0

"Powiedz, nie pytaj" również przybliża Cię do abstrakcji w domenie problemu (wymagania użytkownika), w przeciwieństwie do szczegółów implementacji (wymagania projektowe lub pochodne). – Fuhrmanator

1

Nie wiem, czy to faktycznie obniża spójność.

Agregacja/kompozycja dotyczy klasy wykorzystującej inne klasy w celu realizacji kontraktu, który eksponuje publicznymi metodami. Klasa nie musi duplikować interfejsu powiązanych obiektów. W rzeczywistości ukrywa wszelkie wiadomości o tych zagregowanych klasach od metody wywołującej.

Aby przestrzegać prawa Demeter w przypadku wielu poziomów zależności klas, wystarczy zastosować agregację/kompozycję i dobre enkapsulacje na każdym poziomie.

Innymi słowy, każda klasa ma jedną lub więcej zależności na innych klasach, ale są to zawsze tylko zależności od klasy, do której się odwołuje, a nie od jakichkolwiek obiektów zwróconych przez metody/metody.

+0

Aby użyć innego przykładu plakatów, jeśli obiekt klienta musi teraz wiedzieć nie tylko o zamówieniu klienta, ale o cenie zamówienia klienta, to zmusza to do kontaktu z klientem w sposób, który wydaje się obniżać spójność . –

+0

Chodzi również o poziom/typ używanej abstrakcji. Klient z definicji musi ściśle współpracować z zamówieniem/zamówieniami. Dlatego spójność klienta nie jest zmniejszana przez customer.getOrderPrice(); refaktoryzacja. np .: Klient może użyć prostego dziesiętnego jako zamówieniaCeny. – Ash

+0

W jaki sposób nie zmniejsza to spoistości? Nie ma związku z klientem, jest związany z zamówieniem. Po prostu ujawniasz go na poziomie klienta. Kiedy zaczyna zmniejszać spójność? Czy customer.getOrderAddressStreet() powoduje zmniejszenie spójności? Może to wszystko szare ... –

6

Myślę, że źle zrozumiałeś, co oznacza spójność.Klasa zaimplementowana pod kątem kilku innych klas niekoniecznie ma niską spójność, o ile stanowi wyraźną koncepcję i ma wyraźny cel. Na przykład możesz mieć class Person, który jest zaimplementowany pod względem klas Date (dla daty urodzenia), Address i Education (lista szkół, do których dana osoba poszła). Możesz dostarczyć opakowania w numerach Person, aby uzyskać rok urodzenia, ostatnią szkołę, do której poszła osoba lub stan, w którym mieszka, aby uniknąć ujawnienia faktu, że Person jest zaimplementowane w odniesieniu do tych innych klas. To zmniejszyłoby sprzężenie, ale spowodowałoby, że Person nie byłby mniej spójny.

3

To szara strefa. Te zasady mają na celu pomóc Ci w pracy, jeśli okażesz, że pracujesz dla nich (np. Wchodzą na drogę i/lub uważasz, że to komplikuje twój kod), wtedy jesteś zbyt twardy i trzeba się wycofać.

Spraw, żeby to działało, nie pracuj dla niego.

+0

to jest dobry opis Prawa Demeter "Spraw, żeby to działało dla ciebie, nie pracuj dla niego". – erhun