Zasada najmniejszej wiedzy lub Prawo Demetera jest ostrzeżeniem przed zaplątaniem się w twoją klasę szczegółami innych klas, które przemierzają warstwę po warstwie. Mówi ci, że lepiej rozmawiać tylko z „przyjaciółmi”, a nie z „przyjaciółmi znajomych”.
Wyobraź sobie, że zostałeś poproszony o przyspawanie tarczy do posągu rycerza w lśniącej zbroi płytowej. Ostrożnie ustawiasz tarczę na lewym ramieniu, aby wyglądała naturalnie. Zauważasz, że są trzy małe miejsca na przedramieniu, łokciu i ramieniu, gdzie tarcza dotyka zbroi. Spawaj wszystkie trzy miejsca, ponieważ chcesz mieć pewność, że połączenie jest silne. Teraz wyobraź sobie, że twój szef jest szalony, ponieważ nie może poruszyć łokciem swojej zbroi. Zakładałeś, że zbroja nigdy się nie poruszy, a zatem stworzyłeś nieruchome połączenie między przedramieniem a ramieniem. Tarcza powinna łączyć się tylko z przyjacielem, przedramieniem. Nie do przyjaciół przedramion. Nawet jeśli musisz dodać kawałek metalu, aby ich dotknąć.
Metafory są fajne, ale co właściwie rozumiemy przez przyjaciela? Każda rzecz, którą obiekt potrafi stworzyć lub znaleźć, jest przyjacielem. Alternatywnie, obiekt może po prostu poprosić o przekazanie innych obiektów , z których zna tylko interfejs. Nie liczą się oni jako przyjaciele, ponieważ nie jest narzucone oczekiwanie, jak je zdobyć. Jeśli obiekt nie wie, skąd się wziął, ponieważ coś przeszło / wstrzyknęło, to nie jest przyjacielem przyjaciela, to nawet nie jest przyjacielem. Jest to coś, co obiekt umie tylko używać. To dobra rzecz.
Próbując zastosować takie zasady, ważne jest, aby zrozumieć, że nigdy nie zabraniają ci osiągnięcia czegoś. Są ostrzeżeniem, że możesz zaniedbywać więcej pracy, aby osiągnąć lepszy projekt, który osiąga to samo.
Nikt nie chce pracować bez powodu, dlatego ważne jest, aby zrozumieć, co z tego wynika. W takim przypadku kod jest elastyczny. Możesz wprowadzać zmiany i mieć mniej innych klas, na które mogą się martwić. To brzmi dobrze, ale nie pomaga ci zdecydować, co robić, chyba że potraktujesz to jako doktrynę religijną.
Zamiast ślepo przestrzegać tej zasady, weź prostą wersję tego problemu. Napisz rozwiązanie, które nie będzie zgodne z zasadą i takie, które spełnia. Teraz, gdy masz dwa rozwiązania, możesz porównać ich wrażliwość na zmiany, próbując wprowadzić je w oba.
Jeśli NIE MOŻESZ rozwiązać problemu zgodnie z tą zasadą, prawdopodobnie brakuje Ci innej umiejętności.
Jednym z rozwiązań Twojego konkretnego problemu jest wstrzyknięcie frame
czegoś (klasy lub metody), która wie, jak rozmawiać z ramkami, abyś nie musiał rozpowszechniać wszystkich szczegółów rozmowy w ramce w swojej klasie, które teraz wiedzą tylko, jak i kiedy dostać ramkę.
To faktycznie jest zgodne z inną zasadą: Oddziel użycie od konstrukcji.
frame = encoder->WaitEncoderFrame()
Korzystając z tego kodu, bierzesz odpowiedzialność za jakoś uzyskanie Frame
. Nie wziąłeś jeszcze żadnej odpowiedzialności za rozmowę z Frame
.
frame->DoOrGetSomething();
Teraz musisz wiedzieć, jak rozmawiać Frame
, ale zastąp to:
new FrameHandler(frame)->DoOrGetSomething();
A teraz musisz tylko wiedzieć, jak rozmawiać z przyjacielem, FrameHandler.
Jest wiele sposobów na osiągnięcie tego i być może nie jest to najlepszy, ale pokazuje, że przestrzeganie zasady nie czyni problemu nierozwiązywalnym. To po prostu wymaga od ciebie więcej pracy.
Każda dobra reguła ma wyjątek. Najlepsze przykłady, jakie znam, to wewnętrzne języki specyficzne dla domeny . A DSL s łańcuch Sposóbzdaje się nadużywać Prawa Demeter przez cały czas, ponieważ ciągle wywołujesz metody zwracające różne typy i używasz ich bezpośrednio. Dlaczego to jest w porządku? Ponieważ w DSL wszystko, co jest zwracane, to starannie zaprojektowany przyjaciel, z którym masz rozmawiać bezpośrednio. Z założenia masz prawo oczekiwać, że łańcuch metod DSL się nie zmieni. Nie masz tego prawa, jeśli po prostu losowo zagłębisz się w bazę kodu, łącząc razem wszystko, co znajdziesz. Najlepsze DSL to bardzo cienkie reprezentacje lub interfejsy z innymi obiektami, do których prawdopodobnie nie powinieneś zagłębiać się. Wspominam o tym tylko dlatego, że odkryłem, że lepiej rozumiałem prawo demeter, kiedy dowiedziałem się, dlaczego DSL są dobrym projektem. Niektórzy posunęli się nawet do stwierdzenia, że DSL nawet nie naruszają prawdziwego prawa demeter.
Innym rozwiązaniem jest pozwolenie, aby coś innego wstrzyknęło frame
ci. Jeśli frame
przyszedł od setera lub najlepiej konstruktora, nie bierzesz żadnej odpowiedzialności za konstruowanie lub nabywanie ramki. Oznacza to, że twoja rola tutaj będzie o wiele bardziej podobna FrameHandlers
. Zamiast tego teraz jesteś tym, który rozmawia Frame
i robi coś innego, aby dowiedzieć się, jak uzyskać. Frame
W pewien sposób jest to to samo rozwiązanie z prostą zmianą perspektywy.
Zasady SOLID są tymi największymi, których staram się przestrzegać. Dwa z nich są przestrzegane tutaj: zasady pojedynczej odpowiedzialności i zasady inwersji zależności. Naprawdę trudno jest uszanować tych dwóch i nadal naruszać Prawo Demetera.
Mentalność, która narusza Demeter, jest jak jedzenie w restauracji bufetowej, w której po prostu łapiesz, co chcesz. Przy odrobinie pracy z góry możesz zapewnić sobie menu i serwer, który przyniesie ci wszystko, co chcesz. Usiądź wygodnie, zrelaksuj się i napiwek.