Prawo Demeter stwierdza co następuje:
- Każda jednostka powinna mieć ograniczoną wiedzę na temat innych jednostek: tylko jednostki „ściśle” związane z bieżącą jednostką.
- Każda jednostka powinna rozmawiać tylko z przyjaciółmi; nie rozmawiaj z nieznajomymi.
- Rozmawiaj tylko z najbliższymi przyjaciółmi.
W C # 6.0 wprowadzono nowy operator o nazwie operator null-warunkowy . IMHO ułatwia kodowanie i poprawia czytelność. Ale ułatwia także pisanie bardziej sprzężonego kodu, ponieważ łatwiej jest poruszać się po polach klas, sprawdzając już pod kątem nieważności (coś podobnego var x = A?.B?.C?.D?.E?.F?
).
Czy słusznie jest stwierdzić, że ten nowy operator jest niezgodny z prawem Demetera?
c#
design-patterns
object-oriented-design
Arthur Rizzo
źródło
źródło
A?.B?.C?.D?.E?.F?
by go naruszyło - LoD nie polega na tym, ile kropek i jeśli metoda wywołująca zawiera takie informacje o strukturze, która nie narusza jej punktów, takie wywołanie byłoby całkowicie akceptowalne. Że taki kod mogłoby naruszać LoD nie wystarczy powiedzieć, że wszystkie zastosowania nim zrobić naruszać LOD.X.Y.Z.W.U
naruszenie „prawa”. Ale z mojego doświadczenia związanego z kodem, 90% czasu jest po prostu brzydko sprzężonym kodem..?
Nie więcej niż jest niezgodny LoD+
czy-
nie.Odpowiedzi:
Nie *
* Operator warunkowy null jest narzędziem w języku i frameworku .NET. Każde narzędzie może być nadużywane i wykorzystywane w sposób, który mógłby zaszkodzić łatwości konserwacji danej aplikacji.
Ale fakt, że narzędzie może być nadużywane, niekoniecznie oznacza, że musi być nadużywane, ani że narzędzie narusza jakąkolwiek konkretną zasadę (zasady), która może być utrzymana.
Prawo Demeter i inne są wytycznymi, jak pisać kod. Jest skierowany do ludzi, a nie do narzędzi. Zatem fakt, że język C # 6.0 zawiera nowe narzędzie, niekoniecznie wpływa na sposób pisania i strukturyzacji kodu.
Z każdym nowym narzędziem, trzeba ocenić go jako ... jeśli facet, który kończy się utrzymując swój kod będzie gwałtowna psychopata ... . Jeszcze raz zauważ, że jest to wskazówka dla osoby piszącej kod, a nie na temat używanych narzędzi.
źródło
foo = new FiveDMatrix(); foo.get(0).get(0).get(0).get(0).set(0,1);
byłoby dobrze (i nie gorzej niżfoo[0][0][0][0][0] = 1
) ... i wiele innych sytuacji, w których nie narusza to LoD.Dom file = prase("some.xml"); file.get(tag1).getChild().get(tag2).getChild() ...
problem przetwarzania struktury jakiegoś głupiego kodu. To nie jest nieznajomy ... jest po prostu głupi..?
Się bardzo użyteczne w takich konstrukcjach.Raczej.
Jeśli wykonujesz tylko jeden dostęp (
a?.Foo
), jest to równoważne z:co większość ludzi zgodziłaby się, nie stanowi naruszenia Prawa Demeter. W tym momencie jest to cukier syntaktyczny, który poprawia czytelność.
Coś więcej i prawdopodobnie naruszałoby to prawo Demetera, a ta funkcja ma tendencję do promowania tego rodzaju użycia. Powiedziałbym nawet, że powyższe „dobre” użycie nie wystarcza, aby uzasadnić tego rodzaju zmianę języka, więc spodziewam się, że zostało stworzone, by wspierać mniej wyraźnie dobre użycie.
To powiedziawszy, warto pamiętać, że Prawo Demeter nie jest prawem jako takim, ale raczej wytyczną. Dużo kodu narusza go i działa dobrze. Czasami prostota projektu lub kodu jest warta więcej niż ryzyko związane z naruszeniem Prawa Demetera.
źródło
a?.Func1(x)?.Func2(y)
Operator koalescencji zerowej jest czymś innym.Nie. Rozważmy zarówno samego operatora, jak i mocno powiązane z nim wykorzystanie.
Samo
.?A
zależy od takiej samej wiedzy o klasie, jaką jest lewostronna wartość i rodzaju zwracanego przez metodę, jak.A != null
to jest, mianowicie. Musi wiedzieć, żeA
właściwość istnieje i zwraca wartość, którą można porównaćnull
.Możemy jedynie argumentować, że narusza to prawo Demeter, jeśli robią to właściwości pisane. Nie jesteśmy nawet zmuszeni do posiadania
A
jako konkretnego typu (jego wartość może być typu pochodnego). Sprzężenie tutaj jest minimalne.Teraz zastanówmy się
var x = A?.B?.C?.D?.E?.F
.Co oznacza, że
A
musi być typu, który może mieć wartość NULL lub może miećB
właściwość, która musi być typu, który może być NULL lub miećC
właściwość, i tak dalej, dopóki typE
właściwości nie będzie miał wartości NULL lub może miećF
właściwość.Innymi słowy, musimy to robić za pomocą języka o typie statycznym lub nałożyć ograniczenia na typy, które mogą zostać zwrócone, jeśli pisanie jest luźne. C # w większości przypadków używa pisania statycznego, więc nic nie zmieniliśmy.
Gdybyśmy mieli, następujący kod naruszałby również prawo:
Co jest dokładnie takie samo . Ten kod, który wykorzystuje sprzężenie różnych elementów, musi „wiedzieć” o pełnym łańcuchu sprzężenia, ale używa kodu, który nie narusza Prawa Demetera, aby to zrobić, ponieważ każda jednostka ma dobrze zdefiniowane sprzężenie z Następny.
źródło
var x = A?.B?.C?.D?.E?.F
niż wszystkie inne, nawet jeśli w końcu są tacy sami.A?.B?.C?.D?.E?.F
ponieważ jest mniej rzeczy, które mogą być złe; albo powinniśmy próbować przedostać sięF
tą ścieżką, albo nie powinniśmy, podczas gdy dłuższa forma może zawierać w sobie błędy, a także błąd, który jest niewłaściwy.A.B.C.D
. O wiele łatwiej jest mieć jedną rzecz, na którą należy zwrócić uwagę (dostęp do powiązanej nieruchomości), niż dwie różne rzeczy, które zależą od dość nieistotnego szczegółu (sprawdzanie wartości zerowej)Obiekt może być tworzony w celu kapsułkowania zachowań lub przechowywania danych, a obiekty mogą być tworzone w celu udostępniania ich zewnętrznemu kodowi lub przechowywania ich prywatnie przez ich twórcę.
Do obiektów tworzonych w celu enkapsulacji zachowania (współdzielonej lub nie) lub w celu współdzielenia z kodem zewnętrznym (niezależnie od tego, czy enkapsulują zachowanie lub dane) należy ogólnie uzyskiwać dostęp poprzez interfejs powierzchniowy. Gdy obiekty przechowujące dane są tworzone do użytku wyłącznie przez ich twórcę, nie mają jednak zastosowania normalne powody Demetera dotyczące unikania „głębokiego” dostępu. Jeśli część klasy, która przechowuje lub manipuluje danymi w obiekcie, zostanie zmieniona w sposób, który wymagałby dostosowania innego kodu, możliwe będzie zagwarantowanie, że cały taki kod zostanie zaktualizowany, ponieważ - jak wspomniano powyżej - obiekt został stworzony dla wyłączne wykorzystanie jednej klasy.
Chociaż myślę, że? operator mógł być może lepiej zaprojektowany, istnieje wystarczająco dużo sytuacji, w których obiekty wykorzystują zagnieżdżone struktury danych, że operator ma wiele przypadków użycia, które nie naruszałyby zasad wyrażonych przez Prawo Demetera. Fakt, że można go wykorzystać do naruszenia LoD, nie powinien być traktowany jako argument przeciwko operatorowi, ponieważ nie jest gorszy niż „.” operator w tym zakresie.
źródło