CodeGym/Kursy Java/Moduł 3/Jak poluzować sprzężenie między modułami oprogramowania

Jak poluzować sprzężenie między modułami oprogramowania

Dostępny

8.1 Dekompozycja jest wszystkim

Dla jasności zdjęcie z dobrego artykułu „Decoupling of Object-Oriented Systems”, ilustrujące główne punkty, które zostaną omówione.

Rozkład

Czy nadal uważasz, że projektowanie architektury aplikacji jest łatwe?

8.2 Interfejsy, ukrywanie implementacji

Głównymi zasadami zmniejszania sprzężenia systemu są zasady OOP i stojąca za nimi zasada enkapsulacji + abstrakcji + polimorfizmu.

Dlatego:

  • Moduły powinny być dla siebie „czarnymi skrzynkami” (enkapsulacja) . Oznacza to, że jeden moduł nie powinien „wspinać się” do innego modułu i wiedzieć nic o jego wewnętrznej strukturze. Obiekty w jednym podsystemie nie powinny mieć bezpośredniego dostępu do obiektów w innym podsystemie.
  • Moduły/podsystemy powinny oddziaływać na siebie tylko poprzez interfejsy (czyli abstrakcje , które nie zależą od szczegółów implementacji). Odpowiednio, każdy moduł musi mieć dobrze zdefiniowany interfejs lub interfejsy do interakcji z innymi modułami.

Zasada „czarnej skrzynki” (enkapsulacji) pozwala nam rozpatrywać strukturę każdego podsystemu niezależnie od innych podsystemów. Moduł, który jest „czarną skrzynką”, można w miarę dowolnie zmieniać. Problemy mogą pojawić się tylko na styku różnych modułów (lub modułu i środowiska).

I ta interakcja musi być opisana w najbardziej ogólnej (abstrakcyjnej) formie, czyli w postaci interfejsu. W takim przypadku kod będzie działał tak samo z każdą implementacją zgodną z kontraktem interfejsu. To właśnie ta umiejętność pracy z różnymi implementacjami (modułami lub obiektami) poprzez ujednolicony interfejs nazywa się polimorfizmem.

Dlatego Servlet jest interfejsem : kontener WWW nie wie nic o serwletach, ponieważ są to obiekty, które implementują interfejs Servletu i to wszystko. Serwlety również wiedzą trochę o strukturze kontenera. Interfejs Servletu to kontrakt, ten standard, ta minimalna interakcja, która jest potrzebna, aby aplikacje internetowe Java zawładnęły światem.

Polimorfizm to wcale nie nadrzędność metod, jak się czasem błędnie uważa, ale przede wszystkim zamienność modułów/obiektów z tym samym interfejsem lub „jeden interfejs, wiele implementacji”. Aby zaimplementować polimorfizm, mechanizm dziedziczenia w ogóle nie jest potrzebny. Jest to ważne, aby zrozumieć, ponieważ generalnie należy unikać dziedziczenia, gdy tylko jest to możliwe .

Dzięki interfejsom i polimorfizmowi uzyskuje się właśnie możliwość modyfikowania i rozszerzania kodu bez zmiany tego, co już jest napisane (zasada Open-Closed).

Dopóki interakcja modułów jest opisana wyłącznie w postaci interfejsów i nie jest powiązana z konkretnymi implementacjami, masz możliwość absolutnie „bezbolesnej” dla systemu wymiany jednego modułu na inny, który implementuje ten sam interfejs, a także dodać nowy i tym samym rozszerzyć funkcjonalność.

To jak w konstruktorze LEGO - interfejs standaryzuje interakcję i pełni rolę swoistego łącznika, do którego można podłączyć dowolny moduł z odpowiednim złączem.

Elastyczność projektanta zapewnia fakt, że możemy po prostu wymienić jeden moduł lub część na inny z tymi samymi złączami (z tym samym interfejsem), jak również dodać dowolną liczbę nowych części (jednocześnie istniejące części nie są zmieniane ani modyfikowane w żaden sposób).

Interfejsy pozwalają zbudować prostszy system, biorąc pod uwagę każdy podsystem jako całość i ignorując jego wewnętrzną strukturę. Pozwalają modułom na interakcję i jednocześnie nic nie wiedzą o swojej wewnętrznej strukturze, tym samym w pełni realizując zasadę minimalnej wiedzy, która jest podstawą luźnego powiązania.

Im bardziej ogólne/abstrakcyjne są zdefiniowane interfejsy i im mniej nakładają ograniczeń na interakcję, tym bardziej elastyczny jest system. Stąd wynika jeszcze jedna z zasad SOLID - zasada segregacji interfejsów , która sprzeciwia się „grubym interfejsom”.

Mówi, że duże, nieporęczne interfejsy należy podzielić na mniejsze, bardziej szczegółowe, aby klienci małych interfejsów (zależnych od modułów) wiedzieli tylko o metodach, z którymi muszą pracować.

Zasada ta jest sformułowana w następujący sposób: „Klienci nie powinni polegać na metodach (uważaj na metody), których nie używają” lub „Wiele specjalistycznych interfejsów jest lepszych niż jeden uniwersalny”.

Okazuje się, że słaba łączność jest zapewniona tylko wtedy, gdy interakcja i zależności modułów są opisane tylko za pomocą interfejsów, czyli abstrakcji, bez użycia wiedzy o ich wewnętrznej strukturze i strukturze. Dodatkowo mamy możliwość rozbudowy/zmiany zachowania systemu poprzez dodawanie i używanie różnych implementacji, czyli dzięki polimorfizmowi. Tak, znowu trafiliśmy na OOP - Enkapsulacja, Abstrakcja, Polimorfizm.

8.3 Fasada: interfejs modułu

Tutaj doświadczony programista zapyta: jeśli projekt nie jest na poziomie obiektów, które same implementują odpowiednie interfejsy, ale na poziomie modułów, to czym jest implementacja interfejsu modułu?

Odpowiedź: mówiąc językiem wzorców projektowych, to za realizację interfejsu modułu może odpowiadać specjalny obiekt – Fasada . Jeśli wywołujesz metody na obiekcie, który zawiera sufiks Gateway (na przykład MobileApiGateway), najprawdopodobniej jest to fasada.

Fasada jest obiektem interfejsu , który gromadzi zestaw operacji wysokiego poziomu do pracy z określonym podsystemem, ukrywając za nim swoją wewnętrzną strukturę i prawdziwą złożoność . Zapewnia ochronę przed zmianami w implementacji podsystemu. Służy jako pojedynczy punkt wejścia - „kopniesz fasadę, a on wie, kogo należy kopnąć w tym podsystemie, aby uzyskać to, czego potrzebuje”.

Właśnie zapoznałeś się z jednym z najważniejszych wzorców projektowych, który pozwala wykorzystać koncepcję interfejsów podczas projektowania modułów, a tym samym je rozdzielić - „Fasada”.

Ponadto „Fasada” umożliwia pracę z modułami w taki sam sposób, jak ze zwykłymi obiektami i zastosowanie wszystkich przydatnych zasad i technik, które są stosowane w projektowaniu klas podczas projektowania modułów.

Fasada: interfejs modułu

Uwaga : Chociaż większość programistów rozumie znaczenie interfejsów podczas projektowania klas (obiektów), wydaje się, że wielu odkrywa pomysł wykorzystania interfejsów również na poziomie modułu.

Komentarze
  • Popularne
  • Najnowsze
  • Najstarsze
Musisz się zalogować, aby dodać komentarz
Ta strona nie ma jeszcze żadnych komentarzy