Przejdź do treści
Tło

Blog

Architektura porty i adaptery w języku Java

Porty i adaptery Java to architektura, która zwiększa elastyczność aplikacji. Sprawdź, jak separować warstwy i projektować systemy odporne na zmiany, grafilka przedstawia klawiaturę oraz programistę który koduje.
Ikona

Architektura trójwarstwowa w Javie – standard, który warto znać.

Porty i adaptery Java

Od wielu lat w świecie Javy przyjętym standardem jest podział backendu aplikacji webowych na trzy główne warstwy zobaczmy porty i adaptery Java.

  1. Kontrolery – przyjmujące żądania od interfejsu użytkownika (tzw. endpointy),

  2. Logika biznesowa – składająca się z encji i serwisów operujących na tych encjach,

  3. Warstwa persystencji – odpowiadająca za odczyt i zapis danych do bazy lub komunikację z zewnętrznymi usługami.

Zależności między warstwami

Encje, czyli obiekty domenowe, reprezentują rzeczowniki zebrane na etapie analizy wymagań. Posiadają one pola, gettery i settery, a ich struktura często odwzorowuje tabele w bazie danych (tzw. anemiczny model domenowy).

Warstwa kontrolerów korzysta z logiki biznesowej, natomiast logika opiera się na warstwie persystencji. Innymi słowy: każda warstwa wyższa jest zależna od niższej i działa w ramach jej możliwości.

Problemy klasycznego podejścia

Choć podejście trójwarstwowe dobrze sprawdza się w przypadku prostych operacji CRUD (Create, Read, Update, Delete), to przy bardziej złożonych regułach biznesowych pojawiają się wyzwania:

1. Trudniejsza testowalność

W serwisach logiki biznesowej mnożą się instrukcje warunkowe (if), co zwiększa ryzyko pominięcia ważnego warunku. Dodatkowo, testowanie wymaga często podpięcia bazy danych, co wydłuża proces i komplikuje automatyzację.

2. Wysoka zależność od persystencji

Prace nad aplikacją zwykle zaczynają się od konfiguracji bazy danych. To narzuca konkretne decyzje projektowe już na samym początku, ponieważ sposób działania logiki biznesowej zależy od tego, jakie metody oferuje warstwa niższa.

3. Przecieki szczegółów technicznych

Gdy aplikacja korzysta z zewnętrznych usług (np. kolejek wiadomości, usług autoryzacyjnych lub bibliotek), ich szczegóły „przeciekają” do warstwy logiki. W rezultacie, każda zmiana w niższych warstwach może wymagać modyfikacji logiki biznesowej. To łamie zasadę pojedynczej odpowiedzialności (SRP), która mówi, że każda klasa powinna mieć tylko jeden powód do zmiany.

Ratunek

Rozwiązaniem powyższych problemów byłoby odwrócenie zależności – to nie warstwa logika biznesowa powinna zależeć od warstw niższych, ale to warstwa niższa powinna dostarczać to co potrzebuje logika biznesowa.

Porty i adaptery

Architektura portów i adapterów (heksagonalna) – jak działa?

Architektura, która odwraca tradycyjną zależność między warstwami, nosi nazwę portów i adapterów. Nazywana jest też architekturą heksagonalną, co wynika z jej schematycznego przedstawienia.

Czym jest jądro aplikacji?

Centralnym elementem tej architektury jest jądro aplikacji, które zawiera całą logikę biznesową. Jądro nie zna szczegółów technicznych implementacji. Dzięki temu pozostaje niezależne od infrastruktury oraz technologii zewnętrznych.

Porty – interfejsy komunikacyjne

Jądro udostępnia tzw. porty, czyli interfejsy. Te dzielą się na dwa typy:

  • Porty wejściowe (primary ports) – umożliwiają światu zewnętrznemu wywoływanie logiki aplikacji. Z ich pomocą można np. utworzyć nowy zasób czy pobrać dane.

  • Porty wyjściowe (secondary ports) – służą logice biznesowej do komunikacji ze światem zewnętrznym. Dzięki nim możliwa jest integracja z bazą danych, API czy innymi modułami.

 Adaptery – Porty i adaptery Java

Adaptery to warstwa implementująca wspomniane porty:

  • Adaptery wejściowe obsługują porty wejściowe. Przykład? Endpointy REST, które odbierają żądania i przekazują je dalej do logiki.

  • Adaptery wyjściowe implementują interfejsy zdefiniowane w portach wyjściowych. Mogą odpowiadać za zapis do bazy danych albo wysyłkę wiadomości do zewnętrznego systemu.

Gdzie tkwi magia architektury heksagonalnej?

Największą zaletą tego podejścia jest izolacja logiki biznesowej od zewnętrznych zależności. Dzięki temu:

  • Można rozwijać system, nie decydując od razu o wyborze np. bazy danych,

  • Testy jednostkowe logiki nie wymagają konfiguracji środowiska (np. połączenia z bazą),

  • Migracje technologiczne (np. zmiana dostawcy usługi) są łatwiejsze, bo zależą tylko od adaptera.

Inna struktura pakietów

Powyższy przykład jest jedną z wielu opcji struktury pakietów. W przypadku małych domen taka liczba pakietów może być przerostem formy nad treścią. Wtedy można ograniczyć się na przykład do pakietów “api”, “domain”, “infrastructure”. Z kolej przy rozbudowanych modelach możemy chcieć pogrupować porty w podpakietach “primary” i “secondary”. Można zacząć od wersji prostszej i, gdy uznamy, że kod się znacząco rozrósł, przeprowadzić refaktoryzację do większej liczby podpakietów. Najważniejsze jest ustalić w ramach całej organizacji, zespołu lub projektu wspólny standard.

 

Więcej o języku jawa znajdziecie tutaj: Zapytania w języku Java – znaczenie i zastosowanie