<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kamil Kozak</title>
    <description>The latest articles on DEV Community by Kamil Kozak (@kamilkozak).</description>
    <link>https://dev.to/kamilkozak</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F912736%2Fb6beefbd-f81a-4b13-8469-4ee2b783fd32.jpg</url>
      <title>DEV Community: Kamil Kozak</title>
      <link>https://dev.to/kamilkozak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kamilkozak"/>
    <language>en</language>
    <item>
      <title>Modularny monolit</title>
      <dc:creator>Kamil Kozak</dc:creator>
      <pubDate>Wed, 26 Oct 2022 20:41:35 +0000</pubDate>
      <link>https://dev.to/kamilkozak/modularny-monolit-w-laravelu-51f9</link>
      <guid>https://dev.to/kamilkozak/modularny-monolit-w-laravelu-51f9</guid>
      <description>&lt;p&gt;Można spotkać się z opinią, że Architektura Monolityczna jest równoznaczna z trudnym do utrzymania, niechlujnym kodem. Choć monolit wcale nie wyklucza przejrzystej architektury nie trudno doprowadzić do stanu gdy kod przypomina wielką kule błota (big ball of mud). Winę za taki stan rzeczy ponoszą między innymi tutoriale i dokumentacje frameworków, które skupiają się na szczegółach technicznych z pominięciem architektury. Nie trudno o przykłady kodu gdzie kontrolery są umieszczanie z kontrolerami, a modele z modelami. W dużej aplikacji doprowadzi to prędzej czy później do problemów z architekturą.&lt;/p&gt;

&lt;p&gt;Śledząc konferencje programistyczne w ostatnich latach można zauważyć, że Mikroserwisy zyskały na popularności. Jest to spowodowane prawdopodobnie tym, że zaczęło ich używać wiele firm pokroju Netflixa. Firmy te mają specjalne wymagania, których Architektura Monolityczna nie jest w stanie spełnić. Mikroserwisy zaczęły być reklamowane jako Silver Bullet, który rozwiązuje wszystkie problemy rozwoju oprogramowania.&lt;/p&gt;

&lt;p&gt;Architektura Mikroserwisowa to właściwy wybór w wielu przypadkach użycia, ale jak każda inna Architektura Oprogramowania, ma również słabe punkty. Architektura Monolityczna również ma miejsce w nowoczesnym tworzeniu oprogramowania. Każda architektura oprogramowania ma swój własny zestaw zalet i wad, a inne rozwiązanie będzie miało sens dla aplikacji zależnie od fazy jej rozwoju.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modularyzacja
&lt;/h2&gt;

&lt;p&gt;Wikipedia o &lt;a href="https://pl.wikipedia.org/wiki/Aplikacja_monolityczna"&gt;Aplikacji Monolitycznej&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Inżynieria oprogramowania opisuje aplikację monolityczną jako zaprojektowaną bez modułowości (podziału na moduły). Ogólnie rzecz biorąc, modułowość jest pożądana, ponieważ umożliwia ponowne wykorzystanie części logiki aplikacji, a także ułatwia konserwację, umożliwiając naprawę lub wymianę części aplikacji bez konieczności wymiany hurtowej.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dalej&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Modułowość jest osiągana w różnym stopniu przez różne podejścia do modularyzacji.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Można spotkać się też z definicją:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Monolit to system, który ma dokładnie jedną jednostkę wdrożeniową.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Zła reputacja Monolitów wynika z tego, że nie poddaje się ich odpowiedniej modularyzacji. Granice między różnymi domenami nie są przestrzegane co z czasem doprowadzi do wysokiego couplingu, który zastopuje rozwój i utrudni utrzymanie. Modularyzacja pozwoli uzyskać zalety zarówno monolitów, jak i mikroserwisów bez zwiększania liczby jednostek wdrożeniowych.&lt;/p&gt;

&lt;p&gt;Aby osiągnąć modularność, a co za tym idzie architekturę modułową ​​trzeba podzielić system na mniejsze kawałki czyli moduły, które są niezależne i wymienne, a każdy moduł musi mieć zdefiniowany interfejs i zaimplementować wszystko, co jest niezbędne do zapewnienia funkcjonalności biznesowej, którą opisuje interfejs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Niezależność
&lt;/h3&gt;

&lt;p&gt;Moduł nigdy nie jest całkowicie niezależny, zawsze zależy od czegoś innego. Jednak zależności powinny być ograniczone do minimum zgodnie z zasadami: Low Coupling, High Cohesion. Aby określić, jak niezależny i wymienny jest moduł, musimy przyjrzeć się trzem czynnikom: liczbie zależności, sile tych zależności oraz stabilności modułów, od których zależy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Funkcjonalność biznesowa
&lt;/h3&gt;

&lt;p&gt;W systemie typu "big ball of mud" spotkamy się z grupowaniem kodu na moduły techniczne - moduł dostępu do bazy danych, moduł systemu kolejek itd czyli plastry poziome (horizontal slices). Zmiana techniczna spowoduje zmianę w jednym module, ale zmiana biznesowa dotknie ich wszystkich. Jednak zmiany w systemie częściej dotyczą biznesu i z tego powodu moduły powinny być biznesowe - plastry pionowe (vertical slices). W ten sposób częste zmiany dotyczą tylko jednego modułu – staje się on bardziej samodzielny, autonomiczny i sam jest w stanie zapewnić funkcjonalność.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interfejs
&lt;/h3&gt;

&lt;p&gt;Moduł powinien mieć dobrze zdefiniowany interfejs – kontrakt, który definiuje, co moduł może zrobić i ukrywa lub hermetyzuje, jak to się robi. Hermetyzacja jest nieodłącznym elementem modułowości. Interfejs służy do komunikacji z innymi modułami. Wszystko, co udostępniamy na zewnątrz, staje się publicznym API modułu. Jeżeli komunikujemy moduły przez zdarzenia to ono również jest kontraktem. Zmiana pola w klasie zdarzenia jest zmianą kontraktu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bounded Context
&lt;/h2&gt;

&lt;p&gt;Znakomitą techniką do wyznaczenia modułów jest Bounded Context (Kontekst Ograniczony) czyli centralny wzorzec z Domain Driven Design. W DDD domenę (dziedzinę) oprogramowania odzwierciedlamy w kodzie jako model domeny. Model ten umieszczamy w Kontekście Ograniczonym. Model, aby był skuteczny, musi być zunifikowany – to znaczy być wewnętrznie spójny, aby nie było w nim sprzeczności.&lt;/p&gt;

&lt;p&gt;Gdy próbujesz modelować większą domenę, coraz trudniej jest zbudować jeden zunifikowany model. "Klient" w aplikacji do rezerwacji pokoju hotelowego w zależności od kontekstu może oznaczać płatnika, rezerwującego, odbiorcę faktury, gościa pokoju. Tworzenie jednej tabeli i jednego zunifikowanego modelu na wszystkie te konteksty jest przykładem Big Ball of Mud. Zamiast 4 modeli i 4 kontekstów mamy 1 model do 4 kontekstów. Ponieważ każda z tych definicji „Klienta” jest jasna wyłącznie we własnym kontekście, to każda powinna zostać ujęta w osobnym Kontekście Ograniczonym. W każdym kontekście "Klient" będzie opisany innym Językiem Wszechobecnym (Ubiquitous Language). Język Wszechobecny to język wypracowany wokół modelu domeny i używany przez wszyskich członków zespołu.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Kontekst ograniczony nie jest modułem. Zapewnia ramę, w której model ewoluuje. Moduły służą do organizowania elementów modelu, więc Bounded Context obejmuje moduł.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Aby osiągnąć modułowość w najprostszej formie można zacząć od przeniesienia klas z folderów technicznych do folderów nazwanych biznesowo. Wchodzimy w moduł Rezerwacji, a nie moduł kontrolerów czy serwisów. Pierwsze spotkanie z repozytorium kodu mówi nam jakie są funkcjonalności systemu. Kiedy mamy monolit typu spaghetti code to funkcji biznesowych nie widać. Jeżeli mamy wyznaczone moduły zmieniając funkcjonalność wchodzimy w jedno miejsce, zamiast przeszukiwać katalogi z kontrolerami, modelami itd. Rzeczy, które się zmieniają są blisko siebie. Osiągamy High Cohesion i Low Coupling na poziome nie klas, a modułów. Przeciwdziałamy antywzorcowi "Shotgun Surgery" wprowadzając zmiany w module, który tego wymaga, a nie w wielu miejscach jednocześnie w całym systemie.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drivery Architektoniczne
&lt;/h2&gt;

&lt;p&gt;Lepsze są mikroserwisy czy monolit? Nie da się jednoznacznie odpowiedzieć na pytanie. Przed podjęciem decyzji należy kierować się kontekstem. W pewnych przypadkach nawet Big Ball Of Mud będzie dobrą architekturą gdy system ma powstać szybko i szybko zakończy żywot. Decyzję o wyborze właściwej architektury należy podjąć w oparciu o Drivery Architektoniczne (Architectural Drivers).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drivery dla Monolitu:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Architektura monolityczna jest łatwa do zbudowania i pozwala wcześniej zaprezentować produkt klientom. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Architektura monolityczna jest bardziej popularna. W związku z tym jest większa ilość dostępnych programistów, którzy są z nią zaznajomieni.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jeden zestaw infrastruktury. W monolicie wystarczy jeden serwer z bazą danych. Dodatkowa infrastruktura zwiększa również liczbę możliwych punktów awarii, zmniejszając odporność i bezpieczeństwo aplikacji&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Architektura monolitu jest mniej złożona niż system rozproszony. Wymaga mniej narzędzi, bibliotek, komponentów itd.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wdrożenie monolitu jest łatwiejsze.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monolit ma lepszą wydajność niż Mikroserwisy do momentu pojawienia się potrzeby skalowania.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jedno repozytorium kodu. Możliwość łatwego wyszukiwania i znajdowania wszystkich funkcji w jednym folderze.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wszystkie dane mogą znajdować się w jednej bazie danych. Łatwiejsze pobieranie danych z różnych tabel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Możliwość bezpośredniego wywoływania innych komponentów, zamiast konieczności komunikowania się za pośrednictwem REST API. Nie trzeba się martwić o zarządzanie wersjami API i kompatybilność wsteczną.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ze względu na mniejszą ilość komponentów niż w mikroserwisach (wiele serwerów, baz danych, połączeń sieciowych, kontenerów, maszyn wirtualnych) kompletna aplikacja jest łatwiejsza do zabezpieczenia .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Łatwiejsze transakcje bazodanowe.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ze względu na brak połączeń zewnętrznych, całkowite opóźnienie całej aplikacji jest mniejsze.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drivery dla Mikroserwisów:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Wdrażanie autonomiczne. Mikroserwisy można wdrażać niezależnie.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wydajniejsze wykorzystanie zasobów przy skalowaniu.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mniejszy wpływ awarii jednego modułu na resztę systemu niż w Monolicie.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Każdy moduł może być napisany w innym języku programowania w zależności od potrzeb.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mniejsza ilość wiedzy jaką musi przyswoić programista przed przystąpieniem do pracy. Rozmiar mikroserwisów jest niewielki. Mniej obciąża zdolności poznawcze, a programiści są bardziej produktywni.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Łatwiejszy podział prac między wieloma zespołami oraz zrównoleglenie prac.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Skalowanie granularne czyli skalowanie części aplikacji.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Możliwość użycia bazy danych lepiej dopasowanej do mikroserwisu.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tak długo, jak zachowany jest zewnętrzny kontrakt, mikroserwis można szybko zastąpić, jak klocki Lego.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Integracja Modułów
&lt;/h2&gt;

&lt;p&gt;Aby dostarczyć system spełniający swoje zadanie potrzebne są sposoby, aby pocięte kawałki systemu mogły się ze sobą komunikować.&lt;/p&gt;

&lt;h3&gt;
  
  
  Synchroniczna komunikacja
&lt;/h3&gt;

&lt;p&gt;Bezpośrednie wywołanie (Direct Call). Wywołujemy moduł synchronicznie i musimy czekać na odpowiedź. Moduł ma zdefiniowane API czyli kontrakt (interfejs) lub strukturę danych, których możemy używać. Udostępnia tylko to, co jest potrzebne i w ten sposób stan naszego modułu nie jest nadmiernie eksponowany na zewnątrz. Stan systemu jest podzielony na stan modułów. Jeżeli to możliwe powinno się unikać zapisywania w jednej transakcji stanu wielu modułów.&lt;/p&gt;

&lt;p&gt;Odpowiednikiem w mikroserwisach jest API RESTowe, na które można stosunkowo łatwo przejść jeżeli Modularny Monolit jest etapem przejściowym w drodze do mikroserwisów.&lt;/p&gt;

&lt;p&gt;Coupling jest niższy niż w przypadku Współdzielonej Bazy Danych, ale nadal istnieje. &lt;/p&gt;

&lt;h3&gt;
  
  
  Asynchroniczna komunikacja
&lt;/h3&gt;

&lt;p&gt;Do komunikacji asynchronicznej służą Zdarzenia (Events). Ten styl integracji ma ogromna zaletę - tworzy minimalne zależności między modułami. Zdarzenia powinny być jak najmniejsze, ponieważ są częścią kontraktu, który udostępnia moduł. Rzucamy Event, a inne moduły się na niego subskrubują.&lt;/p&gt;

&lt;p&gt;Wady Zdarzeń:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eventual Consistency. Ze względu na naturę asynchroniczności stan całego naszego systemu może być Ostatecznie Spójny i należy to brać pod uwagę definiując granice modułów.&lt;/li&gt;
&lt;li&gt;Możliwa niewłaściwa kolejność Eventów.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Shared Database
&lt;/h3&gt;

&lt;p&gt;Współdzielona Baza Danych powoduje, że dane w modułach są zawsze spójne, ponieważ są to te same dane. Jeżeli moduł płatności zapisuje dane, moduł rezerwacji może je odczytać natychmiast po zakończeniu transakcji bazodanowej. Rozwiązanie jest mało skomplikowane i wygląda idealnie na pierwszy rzut oka, ale ma szereg problemów.&lt;/p&gt;

&lt;p&gt;Mamy wielkie tabele i trudno osiągnąć ujednolicony model danych, który zapewni spełnienie wymagań wszystkich modułów. Drugim problemem jest brak dobrze zdefiniowanego interfejsu ponieważ interfejsem jest tak naprawdę baza danych.&lt;/p&gt;

&lt;p&gt;Moduły łączy wspólny stan co oznacza wysokie sprzężenie oraz brak autonomii dla modułu. Nie ma nic łatwiejszego niż jednym zapytaniem pobrać dane do raportu z kilku tabel. Niemniej jednak każda zmiana w strukturze bazy danych może uszkodzić inny moduł.&lt;/p&gt;

&lt;p&gt;Z tych przyczyn lepiej wystrzegać się integracji modułów przez Shared Database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mapa Kontekstów&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Podczas integracji modułów warto wiedzieć o kolejnym koncepcie z Domain Driven Design czyli Mapie Kontekstów. Mapa Kontekstów (Context Map) to dokument, który przedstawia Konteksty Ograniczone i relacje między nimi. Opisuje też relacje między zespołami, które nad nimi pracują.&lt;/p&gt;

&lt;p&gt;Jaki styl integracji wybrać? Gdy mówimy o architekturze modułowej, najlepiej mieszać różne style i używać razem Direct Call i Zdarzeń. W zależności od potrzeb jedne moduły mogą komunikować się synchronicznie, inne asynchronicznie.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architektura Heksagonalna
&lt;/h2&gt;

&lt;p&gt;Jak konkretnie zaimplementować Architekturę Modularnego Monolitu? Nie trzeba wymyślać koła na nowo. W koncepcje omówione do tej pory idealnie wpisuje się Architektura Heksagonalna (lub podobne Onion i Clean Architecture).&lt;/p&gt;

&lt;p&gt;System typu Modularny Monolit musi posiadać samodzielne moduły, które zapewniają pełną funkcjonalność biznesową. Architektura Heksagonalna (Porty i Adaptery), doskonale wspiera takie projektowanie zorientowane na domenę. Co więcej, moduły muszą mieć dobrze zdefiniowane interfejsy. Cała komunikacja między modułami powinna odbywać się tylko przez te interfejsy. W Architekturze Heksagonalnej te interfejsy będą Portami. Jak widać ta architektura daje wszystko czego potrzebujemy, aby osiągnąć modułowość dlatego jest naturalnym wyborem.&lt;/p&gt;

&lt;p&gt;Moduł będzie zwykle podzielony na warstwy takie jak: Warstwa Aplikacji, Domeny, Infrastruktury. Pomaga to odseparować domenę od reszty kodu. Przy czym część modułów może stanowić tylko proste operacje typu CRUD (Create Read Update Delete). Dlatego stosowanie warstw nie powinno być decyzją globalną - każdy przypadek warto rozpatrzyć osobno. &lt;/p&gt;

</description>
      <category>laravel</category>
      <category>architecture</category>
      <category>modular</category>
      <category>monolith</category>
    </item>
    <item>
      <title>Architektura heksagonalna (Porty i Adaptery) w Laravelu</title>
      <dc:creator>Kamil Kozak</dc:creator>
      <pubDate>Tue, 27 Sep 2022 21:37:43 +0000</pubDate>
      <link>https://dev.to/kamilkozak/architektura-heksagonalna-w-laravelu-7c8</link>
      <guid>https://dev.to/kamilkozak/architektura-heksagonalna-w-laravelu-7c8</guid>
      <description>&lt;p&gt;Punkt wyjścia do Architektury Heksagonalnej (Hexagonal Architecture) stanowi Architektura Warstwowa. Architektura ta dzieli systemy (aplikacje) na odrębne warstwy. Zgodnie z propozycją Erica Evansa z jego "Blue Book'a" zwykle będzie ich 3 lub 4.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Warstwa Interfejsu Użytkownika&lt;/strong&gt;&lt;br&gt;
Przedstawia informacje użytkownikowi i interpretuje jego działania.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Warstwa Aplikacji&lt;/strong&gt;&lt;br&gt;
Organizuje i deleguje obiekty domeny do wykonywania swojej pracy. Nie zawiera logiki związanej z domeną.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Warstwa Domeny&lt;/strong&gt;&lt;br&gt;
Tu znajdują się koncepcje domeny biznesowej. Encje, które są kombinacją danych i zachowań.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Warstwa infrastruktury&lt;/strong&gt;&lt;br&gt;
Przechowywanie oraz dostęp do danych. Framework i biblioteki pomocnicze.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jedną z najważniejszych korzyści stosowania Architektury Warstwowej jest rozdzielenie odpowiedzialności (separation of concerns). Pomaga ona odseparować domenę od pozostałych warstw i należy do wzorców taktycznych z Domain Driven Design. Problemem pozostają wycieki logiki między warstwami. Można łatwo skończyć z logiką biznesową w interfejsie użytkownika lub infrastrukturą w logice biznesowej.&lt;/p&gt;

&lt;p&gt;Rozwiązanie tego problemu przedstawił w 2005 roku Alistair Cockburn. Dla niego system składa się tylko z dwóch odrębnych części: wewnętrznej i zewnętrznej. Wnętrze to nasz rdzeń, a na zewnątrz to miejsce, w którym żyje interfejs użytkownika i infrastruktura.&lt;/p&gt;

&lt;p&gt;Cockburn doszedł do wniosku, że rdzeń współdziała z interfejsem użytkownika lub bazami danych lub testami automatycznymi w podobny sposób. Dlatego wszystkie te systemy zewnętrzne można oddzielić od rdzenia i komunikować się z nim w sposób niezależny od technologii za pośrednictwem &lt;strong&gt;portów i adapterów&lt;/strong&gt;. Unikając w ten sposób sprzęgania i wycieku logiki między warstwą biznesową, a komponentami zewnętrznymi.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Architektura Heksagonalna jest też nazywana Architekturą Portów i Adapterów (Ports and Adapters). Bardzo podobne architektury dzielące system na warstwy to Clean Architecture - Roberta Martina oraz Onion Architecture - Jeffreya Palermo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SXjWbqnt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j3he49ilpk637i35pbas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SXjWbqnt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j3he49ilpk637i35pbas.png" alt="Heksagon" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Porty
&lt;/h2&gt;

&lt;p&gt;Port jest bramą do rdzenia aplikacji. Określa on interfejs, który pozwoli zewnętrznym aktorom komunikować się z Rdzeniem, niezależnie od tego, kto lub co zaimplementuje ten interfejs. Porty umożliwiają również Rdzeniowi komunikację z zewnętrznymi systemami lub usługami, takimi jak bazy danych, systemy kolejek, inne aplikacje itp. Porty w kodzie będą reprezentowane jako interfejsy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adaptery
&lt;/h2&gt;

&lt;p&gt;Adapter zainicjuje interakcję z Rdzeniem przez Port przy użyciu określonej technologii, na przykład kontroler REST będzie reprezentował adapter, który umożliwia klientowi komunikowanie się z Rdzeniem. Może istnieć wiele adapterów dla każdego portu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rdzeń
&lt;/h2&gt;

&lt;p&gt;Alistair do określenia rdzenia używa słowa "Aplikacja". Rdzeń zawiera serwisy aplikacji, które orkiestrują funkcjonalności. Zawiera również model domenowy czyli logikę biznesową. Rdzeń jest reprezentowany przez heksagon (sześciokąt), który za pomocą Portów odbiera polecenia lub zapytania oraz również za pomocą Portów wysyła żądania do innych aktorów zewnętrznych, takich jak bazy danych.&lt;/p&gt;

&lt;p&gt;Alistair nie daje instrukcji, jak powinieneś ustrukturyzować kod w swoim rdzeniu, ale Architektura Heksagonalna jest często łączona z Domain Driven Design. Wtedy rdzeń lub sześciokąt zawiera warstwę aplikacji i warstwę domeny pozostawiając warstwy interfejsu użytkownika i infrastruktury na zewnątrz.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lz1BEK6q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kbqd3jvq27ioh32ayew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lz1BEK6q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kbqd3jvq27ioh32ayew.png" alt="Architektura Heksagonalna" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dlaczego Heksagon?
&lt;/h2&gt;

&lt;p&gt;Alistair wybrał sześciokąt, aby ludzie wykonujący rysunek mieli miejsce na wstawianie portów i adapterów zgodnie z potrzebami, nie będąc ograniczonymi przez jednowymiarowy rysunek warstwowy. Termin Architektura Heksagonalna pochodzi od tego efektu wizualnego. Liczba 6 jest nieistotna - można użyć kształtu z n-krawędziami.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strona sterująca i strona sterowana
&lt;/h2&gt;

&lt;p&gt;W systemie możemy rozróżnić 2 rodzaje aktorów ze względu na to kto inicjuje rozmowę lub jest za nią odpowiedzialny:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Aktor Sterujący (Driving/Primary Actor) to aktor, który steruje rdzeniem - wyprowadza go ze stanu spoczynku w celu wykonania jednej z jej udostępnionych funkcji.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aktor Sterowany (Driven/Secondary Actor) to taki, którym kieruje rdzeń, aby uzyskać odpowiedzi lub po prostu go powiadomić.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Takie rozróżnienie pozwala również podzielić adaptery:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adapter Sterujący&lt;/strong&gt; (Driving/Primary Adapter). Może być kontrolerem, który pobiera dane wejściowe (użytkownika) i przekazuje je do aplikacji za pośrednictwem portu. Adapter Sterujący będzie korzystać z Portu Sterującego, a serwis w rdzeniu zaimplementuje interfejs zdefiniowany przez port, w tym przypadku &lt;em&gt;zarówno interfejs portu, jak i implementacja znajdują się wewnątrz Heksagonu&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adapter Sterowany&lt;/strong&gt; (Driven/Secondary Adapter). Na przykład Adapter bazy danych, który jest wywoływany przez rdzeń, aby pobrać określony zestaw danych z bazy danych. Adapter Sterowany zaimplementuje Port Sterowany, a serwis w rdzeniu będzie z niego korzystać, w tym przypadku &lt;em&gt;Port znajduje się wewnątrz Heksagonu, ale implementacja znajduje się w Adapterze, a więc poza Heksagonem&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tuEJ8KMz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jj04ukdnnzvyfuhqpwmx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tuEJ8KMz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jj04ukdnnzvyfuhqpwmx.png" alt="Porty i Adaptery" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Korzyści
&lt;/h2&gt;

&lt;p&gt;Architektura Heksagonalna nie jest idealnym rozwiązaniem dla wszystkich aplikacji. Doda ona dodatkowy poziom złożoności, ale sprawdzi się jeżeli potrzebujemy w systemie poniższych elementów.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Opóźnienie w czasie decyzji technicznych&lt;/strong&gt;&lt;br&gt;
Na początku projektu programista może nie wiedzieć jaka baza danych (lub inna technologia) sprawdzi się najlepiej. Można napisać tymczasowe adaptery, które będą zwracały dane wpisane na sztywno w pliku tekstowym. Rozwiązanie nie sprawdzi się na produkcji, ale umożliwi testy zanim nasza wiedza będzie na tyle duża, aby podjąć najlepszą decyzję.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prosta zmiana technologii&lt;/strong&gt;&lt;br&gt;
Nawet jeżeli zdamy sobie sprawę, że wybór technologii był błędny to przełączanie się między technologiami to kwestia napisania nowych adapterów. Porty i Adaptery wpisują się w zasadę Open-Closed z SOLIDa sformułowanego przez Roberta Martina (Wujek Bob). Piszemy nowy kod i nie musimy modyfikować istniejącego.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Odwrócenie zależności&lt;/strong&gt;&lt;br&gt;
Realizujemy kolejną z zasad SOLID - Dependency Inversion, która mówi, że "Wysokopoziomowe moduły nie powinny zależeć od modułów niskopoziomowych - zależności między nimi powinny wynikać z abstrakcji.". DI skutecznie zmniejsza sprzężenie (coupling) między różnymi fragmentami kodu. &lt;strong&gt;Mniejszy coupling = mniej uciążliwych zmian w miejscach połączeń&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Po Stronie Sterującej adapter zależy od portu, którego implementacja jest w rdzeniu. Zna tylko metody zagwarantowane przez interfejs dlatego, zależy od abstrakcji.&lt;/li&gt;
&lt;li&gt;Po Stronie Sterowanej serwis rdzenia zależy od portu, którego implementacja jest w infrastrukturze.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lepsza testowalność&lt;/strong&gt;&lt;br&gt;
System może być testowany w oderwaniu od zewnętrznych zależności. Można podmienić prawdziwe adaptery na testowe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Koncentracja na domenie&lt;/strong&gt;&lt;br&gt;
Rdzeń czyli clou naszej aplikacji jest wolny od wpływu technologii. Pozwala to skupić się na domenie, dlatego też Architektura Heksagonalna Często jest łączona z Domain Driven Design.&lt;/p&gt;
&lt;h2&gt;
  
  
  Domain Driven Laravel
&lt;/h2&gt;

&lt;p&gt;Poniżej zaimplementuje uproszczoną wersje systemu służącego do rezerwacji pokoju w hotelu z użyciem Hexagonal Architecture, Domain Driven Design oraz frameworka Laravel.&lt;/p&gt;

&lt;p&gt;Zacznijmy od wyznaczenia warstw naszego systemu. Warto przypomnieć, że Architektura Heksagonalna wspiera DDD przez izolowanie domeny od czynników zewnętrznych. Logika domeny jest zawarta w rdzeniu, który jest częścią wewnętrzną, a reszta to części zewnętrzne. Dostęp do logiki domeny z zewnątrz jest możliwy poprzez porty i adaptery.&lt;/p&gt;

&lt;p&gt;Podzielimy system na 3 warstwy: domena (wewnątrz heksagonu), aplikacja (zewnątrz) oraz infrastruktura (zewnątrz).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Poprzez warstwę aplikacji użytkownik wchodzi w interakcję z systemem. Obejmuje punkty wejścia do naszej aplikacji i koordynuje wykonywanie logiki domeny. Zawiera takie elementy jak kontrolery i interfejs użytkownika.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;W warstwie domeny znajduje się kod odpowiedzialny za logikę biznesową. Zawiera interfejsy definiujące API do komunikacji z częściami zewnętrznymi, takimi jak baza danych. Jedyna warstwa we wnętrzu heksagonu.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Warstwa infrastruktury to część, która zawiera wszystko czego program potrzebuje do działania, na przykład konfigurację bazy danych i innych narzędzi. Zawiera implementacje interfejsów z warstwy domeny, które zależą od infrastruktury (repozytoria).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Więcej informacji o tym dlaczego tak wyznaczam warstwy we wpisie &lt;a href="https://dev.to/kamilkozak/architektura-warstwowa-w-laravelu-52bg"&gt;Architektura warstwowa w Laravelu&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Warstwa domeny
&lt;/h3&gt;

&lt;p&gt;Model &lt;code&gt;Booking&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Src\Booking\Domain\Models&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Eloquent\Model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * @property int $id
 * @property int $customer_id
 * @property int $room_id
 * @property string $check_in
 * @property string $check_out
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Booking&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port sterujący (interfejs w heksagonie):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Src\Booking\Domain\Contracts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BookingService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;storeBooking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implementacja Portu Sterującego w serwisie domeny (to nie jest adapter), używa Portu Sterowanego:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Src\Booking\Domain\Services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Illuminate\Support\Facades\DB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Domain\Contracts\BookingRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Domain\Contracts\BookingService&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;BookingServiceContract&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Domain\Contracts\Events\BookingCreated&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Domain\Models\Booking&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Payment\Domain\Services\StripePaymentService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Room\Domain\Contracts\RoomService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookingService&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;BookingServiceContract&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;BookingRepository&lt;/span&gt;    &lt;span class="nv"&gt;$bookingRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;RoomService&lt;/span&gt;          &lt;span class="nv"&gt;$roomService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;StripePaymentService&lt;/span&gt; &lt;span class="nv"&gt;$paymentService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;storeBooking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Booking&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;beginTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$room&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;roomService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRoomById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'room_id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

            &lt;span class="nv"&gt;$booking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;bookingRepository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createBooking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;paymentService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$booking&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nv"&gt;$room&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UnprocessableEntityHttpException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'booking::errors.failed'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BookingCreated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$booking&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getKey&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$booking&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port sterowany (interfejs repozytorium w heksagonie):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Src\Booking\Domain\Contracts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Domain\Models\Booking&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BookingRepository&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;createBooking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Booking&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Warstwa aplikacji
&lt;/h3&gt;

&lt;p&gt;Adapter Sterujący - kontroler, który korzysta z Portu Sterującego:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Src\Booking\Application\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Controllers\Controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Application\Http\Requests\StoreBookingRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Application\Http\Resources\BookingResource&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Domain\Contracts\BookingService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Domain\Models\Booking&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookingController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;StoreBookingRequest&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;BookingService&lt;/span&gt; &lt;span class="nv"&gt;$bookingService&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BookingResource&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Booking&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$booking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$bookingService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;storeBooking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BookingResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$booking&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Warstwa Infrastruktury
&lt;/h3&gt;

&lt;p&gt;Adapter sterowany - implementacja interfejsu repozytorium:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Src\Booking\Infrastructure\Repositories&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Domain\Contracts\BookingRepository&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;BookingRepositoryContract&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Src\Booking\Domain\Models\Booking&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookingRepository&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;BookingRepositoryContract&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;createBooking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Booking&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Booking&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'customer_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'customer_id'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'room_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'room_id'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'check_in'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'check_in'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'check_out'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'check_out'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Service Container&lt;/strong&gt;&lt;br&gt;
Warto wspomnieć, że Laravel oferuje świetne narzędzie, które umożliwi połączenie interfejsu z daną implementacją, którym jest Service Container.&lt;/p&gt;

&lt;p&gt;Kod aplikacji dostępny jest w serwisie &lt;a href="https://github.com/kamilkozak/hexagonal-architecture-laravel"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Podsumowanie
&lt;/h2&gt;

&lt;p&gt;W przedstawionym przykładzie rdzeń wystawia porty do komunikacji z warstwą aplikacji (kontrolery) oraz bazą danych. Jednak w prawdziwej aplikacji potrzebujemy szeregu innych narzędzi lub zewnętrznych bibliotek jak obsługa cache'u, systemu plików, logowanie, wysyłanie maili, kolejki, sesje, autoryzacja. Laravel oferuje prosty dostęp do tych technologii za pomocą fasad, ale trzymając się ściśle omawianej architektury musielibyśmy z nich zrezygnować. Dla każdej z technologi należałoby zdefiniować interfejs i go zaimplementować w warstwie infrastruktury. Doprowadzony do skrajności, możesz potencjalnie przełączać frameworki bez ponownego kodowania aplikacji. Uważam jednak, że jest to najbardziej brzegowy i nierealistyczny przypadek do, którego nie warto dążyć. Programowanie w Laravelu ma być przyjemne, dlatego stosuj Porty i Adaptery tam gdzie widzisz z tego korzyści. Dla mnie osobiście Architektura Heksagonalna sprawdza się najlepiej jeżeli chcemy osiągnąć Modularny Monolit, ale to już będzie tematem kolejnego wpisu.&lt;/p&gt;

</description>
      <category>hexagonal</category>
      <category>architecture</category>
      <category>modular</category>
      <category>laravel</category>
    </item>
    <item>
      <title>Architektura warstwowa w Laravelu</title>
      <dc:creator>Kamil Kozak</dc:creator>
      <pubDate>Tue, 20 Sep 2022 20:16:40 +0000</pubDate>
      <link>https://dev.to/kamilkozak/architektura-warstwowa-w-laravelu-52bg</link>
      <guid>https://dev.to/kamilkozak/architektura-warstwowa-w-laravelu-52bg</guid>
      <description>&lt;p&gt;Kiedy tworzymy aplikację, duża jej część nie jest bezpośrednio związana z domeną, ale jest częścią infrastruktury. Typowa aplikacja zawiera dużo kodu związanego z dostępem do bazy danych, dostępem do plików, UI (User Interface).&lt;/p&gt;

&lt;p&gt;Gdy kod związany z domeną jest mieszany z innymi warstwami (ponieważ jest to najłatwiejszy sposób, aby wszystko zaczęło działać szybko), staje się niezwykle trudny do czytania i zarządzania. Prowadzi to do niepożądanego sprzężenia (coupling) i może skutkować mniejszą elastycznością w większych aplikacjach. Nie ma izolacji między dwiema warstwami. Sprzęganie zawsze prowadzi do mniejszej elastyczności.&lt;/p&gt;

&lt;p&gt;W swojej książce Domain-Driven Design: Tackling Complexity in the Heart of Software, Eric Evans proponuje architekturę 4-warstwową, aby umożliwić izolację między warstwą domeny, która przechowuje logikę biznesową, a pozostałymi 3 warstwami pomocniczymi: interfejs użytkownika, aplikacja, i infrastruktura.&lt;/p&gt;

&lt;p&gt;Dlatego podziel złożony program na warstwy które będą zależne tylko od warstw poniżej. Skoncentruj cały kod związany z modelem domeny w jednej warstwie i izoluj go od aplikacji, infrastruktury i interfejsu użytkownika. Obiekty domeny, wolne od odpowiedzialności za wyświetlanie się, przechowywanie itd., mogą koncentrować się na wyrażaniu modelu domeny.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aprtjgh773216nveyoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aprtjgh773216nveyoc.png" alt="Architektura warstwowa"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Warstwa Interfejsu Użytkownika (Warstwa Prezentacji/UI)&lt;/strong&gt;&lt;br&gt;
Odpowiada za prezentowanie informacji i interpretację poleceń użytkownika. Przykładowo dla aplikacji webowych, UI obejmuje swoim zasięgiem przede wszystkim kontrolery. Może zostać połączona z Warstwą Aplikacji, gdyż najważniejsze jest wydzielenie domeny.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Warstwa Aplikacji&lt;/strong&gt;&lt;br&gt;
Cienka warstwa która koordynuje działanie aplikacji. Definiuje zamierzone zadania programu i steruje obiektami dziedziny (z warstwy niżej) w celu rozwiązania postawionych przed nimi zadań. Nie zawiera logiki ani wiedzy biznesowej. Nie przechowuje stanu obiektów biznesowych, ale może przechowywać stan postępu zadania aplikacji.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Warstwa Domeny&lt;/strong&gt;&lt;br&gt;
Ta warstwa zawiera informacje o domenie. Serce oprogramowania biznesowego. Przechowuje stan obiektów domeny, którego zapisywanie delegowane jest do warstwy infrastruktury.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Warstwa Infrastruktury&lt;/strong&gt;&lt;br&gt;
Ta warstwa działa jako biblioteka pomocnicza dla pozostałych warstw. Zapewnia komunikację między warstwami. Implementuje utrwalanie obiektów biznesowych. Zawiera biblioteki pomocnicze dla warstwy Interfejsu Użytkownika itp. Zapewnia komunikację ze światem zewnętrznym.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Na przykład tak może wyglądać typowa interakcja domeny, aplikacji i infrastruktury. Użytkownik chce zarezerwować pokój w hotelu i prosi o to serwis aplikacji w warstwie aplikacji. Warstwa aplikacji pobiera odpowiednie obiekty domeny (encje) z infrastruktury i wywołuje na nich metody do rezerwacji pokoju. Gdy obiekty domeny zakończą działania, usługa aplikacji utrwali obiekty w infrastrukturze.&lt;/p&gt;

&lt;h3&gt;
  
  
  Powiązanie warstw
&lt;/h3&gt;

&lt;p&gt;Warstwy mają być luźno powiązane, a zależności muszą być jednokierunkowe. Warstwy wyższe mogą używać elementów warstw niższych poprzez wykorzystanie ich interfejsów. Jeżeli na przykład aplikacja chce wysłać wiadomość e-mail, wtedy w warstwie infrastruktury może zostać zlokalizowany interfejs służący do wysyłania wiadomości, zaś elementy warstwy aplikacji mogłyby tylko zażądać jej wysłania. Dzięki temu warstwa aplikacji jest wąsko skoncentrowana na swoim zadaniu i wie, kiedy ma wysłać wiadomość, lecz nie przejmuje się tym, w jaki sposób to wykonać.&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain Driver Laravel
&lt;/h2&gt;

&lt;p&gt;Tak wygląda próba dopasowania domyślnej struktury Laravela do warstw, które proponuje Evans.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncyhatbyw26ysrcjjeax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncyhatbyw26ysrcjjeax.png" alt="Laravel warstwy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jeżeli popatrzymy na Eloquent, możemy zobaczyć, że żyje on w warstwie infrastruktury (frameworka) jednak duża część naszej logiki domeny znajduje się w modelach, które Eloquenta rozszerzają. Między warstwą infrastruktury (frameworka) i warstwą domeny zachodzi silne powiązanie (coupling). W Laravelu wbrew zasadom DDD nie położono nacisku na rozdzielenie odpowiedzialności (separation of concerns), ale na czysty i prosty kod. Poszukajmy więc miejsca w którym Laravel i DDD współżyją razem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Możliwa struktura folderów
&lt;/h3&gt;

&lt;p&gt;Dokumentacje i tutoriale do frameworków zachęcają do grupowania kodu opierając się na szczegółach technicznych czyli kontrolery z kontrolerami, modele z modelami i tak dalej. Przed wyznaczeniem struktury katalogów zgodnie z DDD warto odpowiedzieć sobie na pytanie czy klient prosi o "pracę nad kontrolerami" lub "katalogiem modeli" czy o pracę nad funkcjonalnością obsługi zamówień czy magazynu.&lt;/p&gt;

&lt;p&gt;Ponieważ chce zostać wiernym Laravelowi, w rzeczywistości nie zmienię wielu aspektów jego struktury bo nie jest to konieczne. Tutaj zasugeruję prostą strukturę folderów, aby konkretnie zaimplementować to, co omówiliśmy do tej pory.&lt;/p&gt;

&lt;p&gt;1) Zaczynamy od domyślnej struktury katalogów Laravela.&lt;/p&gt;

&lt;p&gt;2) Tworzymy folder Domain dla warstwy domeny - można to zrobić na 2 sposoby:&lt;/p&gt;

&lt;p&gt;a) Umieszczając go w &lt;code&gt;/app&lt;/code&gt; (preferowane przeze mnie)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/app/Domain
    |___ /Booking
    |___ /Payment
    |___ /Invoice
        |___ /Actions
        |___ /QueryBuilders
        |___ /Collections
        |___ /DataTransferObjects
        |___ /Events
        |___ /Exceptions
        |___ /Jobs
        |___ /Listeners
        |___ /Models
        |___ /Rules
        |___ /States
    |___ /Shared (funkcjonalności współdzielone)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;b) Umieszczając go w &lt;code&gt;/src&lt;/code&gt;. Trzeba go dodać w pliku composer.json, aby zarejestrować nową przestrzeń nazw.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"autoload"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"psr-4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"App\\"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Domain\\"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/Domain/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nie zapomnij &lt;code&gt;composer dump-autoload&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;3) Tworzymy folder per Bounded Context/Domena  (Booking, Payment...) w poprzednio dodanym katalogu Domain.&lt;/p&gt;

&lt;p&gt;4) Warstawa aplikacji żyje tam gdzie dotychczas czyli w katalogu &lt;code&gt;/app/Http&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;a) można pozostać przy domyślnej strukturze wewnątrz &lt;code&gt;/app/Http&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/app/Http
    |___ /Controllers
        |___ /Admin
        |___ /Api
        |___ /Front
    |___ /Requests
        |___ /Admin
        |___ /Api
        |___ /Front
    |___ /Resources
        |___ /Admin
        |___ /Api
        |___ /Front
    |___ /ViewModels
    |___ ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;b) ale preferuję odwrócenie tego schematu&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/app/Http
    |___ /Admin
        |___ /Controllers
        |___ /Requests
        |___ /Resources
        |___ /ViewModels
    |___ /Api
        |___ /Controllers
        |___ /Requests
        |___ /Resources
    |___ /Front
        |___ /Controllers
        |___ /Requests
        |___ /Resources
        |___ /ViewModels
    |___ /Support (funkcjonalności współdzielone)
        |___ /Controllers
        |___ /Middleware
        |___ Kernel.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;c) a w przypadku dużej aplikacji&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/app/Http
    |___ /Admin
        |___ /Booking
            |___ /Controllers
            |___ /Requests
            |___ /Resources
            |___ /ViewModels
        |___ /Payment
            |___ /Controllers
            |___ /Requests
            |___ /Resources
            |___ /ViewModels
        |___ /Invoice
            |___ /Controllers
            |___ /Requests
            |___ /Resources
            |___ /ViewModels
    |___ /Api
    |___ /Front
    |___ /Support (funkcjonalności współdzielone)
        |___ /Controllers
        |___ /Middleware
        |___ Kernel.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5) Struktura w katalogu &lt;code&gt;/resources&lt;/code&gt;, który też jest częścią warstwy aplikacji może naśladować tą z &lt;code&gt;/app/Http&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Domena
&lt;/h3&gt;

&lt;p&gt;Katalog domen związany jest z biznesem. W każdej z domen znajdują się foldery na koncepty z Laravela, które odpowiadają za logikę biznesową:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Models&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Actions&lt;/li&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;li&gt;Jobs&lt;/li&gt;
&lt;li&gt;itd&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Poza separacją domeny taka struktura me też inne zalety:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Łatwiejsza nawigacja. Wszystko, co związane z zamówieniem, znajduje się w katalogu Order.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Łatwiejsze wdrażanie nowych programistów. W końcu pracujemy w zespołach z innymi programistami. O wiele łatwiej jest wdrożyć nowych deweloperów, jeśli mogę powiedzieć: „jeśli potrzebujesz czegoś związanego z fakturami, możesz przejść do katalogu Domains/Invoices”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ta warstwa zawiera Serwisy Domeny (Domain Services). W przypadku gdy logika biznesowa nie pasuje do klasy modelu można umieścić ją w Serwisie Domeny. &lt;/p&gt;

&lt;h3&gt;
  
  
  Interfejs Użytkownika
&lt;/h3&gt;

&lt;p&gt;W tej warstwie mogą znajdować się kontrolery i widoki. Spełniają one jednak warunki, żeby należeć do warstwy aplikacji dlatego do niej je zakwalifikuje. Ma to większy sens ponieważ warstwa aplikacji w Laravelu jest bardzo cienka. Zwykle jest to miejsce na komendy (command) i command handlery oraz serwisy aplikacji, ale by zachować prostotę w Laravelu tego typu funkcjonalności umieszczam w warstwie domeny.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aplikacja
&lt;/h3&gt;

&lt;p&gt;W tej warstwie mieszczą się Serwisy Aplikacji (Application Services). Warstwa ta może istnieć jako komponenty inne niż usługi - na przykład kontrolery. Stanowi "C" w architekturze MVC.&lt;/p&gt;

&lt;p&gt;Kontroler powinien ograniczyć się do wykonania dwóch rzeczy: przyjęcia żądania i zwrócenia odpowiedzi. Należy stosować podejście “Fat Model, Skinny Controller”. W idealnym przypadku akcja kontrolera powinna zawierać 1-2 linijki kodu. Logika związana z biznesem (domeną) powinna zostać przeniesiona w inne miejsce, w warstwie domeny.&lt;/p&gt;

&lt;p&gt;Często nie ma mapowania 1:1 między kontrolerami (aplikacja) i modelami (domena). Dlatego w podejściu, które stosuje aplikacja może korzystać z kilku domen jednocześnie.&lt;/p&gt;

&lt;p&gt;Umieść tutaj:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controllers&lt;/li&gt;
&lt;li&gt;Requests&lt;/li&gt;
&lt;li&gt;Middleware&lt;/li&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;li&gt;ViewModels&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Infrastruktura
&lt;/h3&gt;

&lt;p&gt;W Warstwie Infrastruktury, która bywa też nazwana Warstwą Frameworka żyje Laravel, a także biblioteki/SDK zainstalowane composerem. Ten obszar obejmuje także konfigurację bazy danych i innych modułów Laravela z katalogu config, migracje, seedery, factory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Podsumowanie
&lt;/h2&gt;

&lt;p&gt;Spojrzenie na architekturę, które przedstawiłem czerpie garściami z DDD i opiera się w głównej mierze na grupowaniu kodu wokół funkcjonalności. Sprawia, że zarządzanie projektem jest łatwiejsze gdy ten się rozrasta.&lt;/p&gt;

&lt;p&gt;W Projektowaniu Opartym na Domenie nie chodzi o idealne wyznaczenie warstwy prezentacji ani warstwy aplikacji. DDD to metodologia, której głównym celem jest warstwa domeny. Oznacza to, że DDD nie nakłada ograniczeń dotyczących żadnej warstwy poza warstwą Domeny. To, że ktoś utworzył katalogi „Warstwa aplikacji” i „Warstwa prezentacji”, nie oznacza, że ​​Twoja aplikacja powinna je mieć. Powinieneś tworzyć warstwy po utworzeniu znacznej ilości kodu, który pogrupowałeś i chcesz nazwać tę grupę ze względu na komunikację między programistami i przejrzystość kodu.&lt;/p&gt;

&lt;p&gt;Możesz się zastanawiać czy Laravel nie wymaga by klasy znajdywały się w domyślnych folderach. Odpowiedź brzmi: Nie. W rzeczywistości Laravel jest pod tym względem bardzo elastyczny. Jeżeli potrzebujesz zmienić istniejącą strukturę bardzo pomocny w tym jest PhpStorm. Można za jego pomocą przenosić w nowe miejsce klasy lub całe namespace'y i zadba on o zmianę ścieżek importu we wszystkich plikach.&lt;/p&gt;

&lt;p&gt;Nie poruszyłem ważnej kwestii separacji warstw, gdyż w tym podejściu jej nie stosuję. Wrócę do tego tematu we wpisie o Architekturze Heksagonalnej.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>laravel</category>
      <category>modular</category>
      <category>ddd</category>
    </item>
    <item>
      <title>Czym jest Domain Driven Design (DDD)?</title>
      <dc:creator>Kamil Kozak</dc:creator>
      <pubDate>Mon, 12 Sep 2022 23:17:00 +0000</pubDate>
      <link>https://dev.to/kamilkozak/czym-jest-domain-driven-design-ddd-53cj</link>
      <guid>https://dev.to/kamilkozak/czym-jest-domain-driven-design-ddd-53cj</guid>
      <description>&lt;p&gt;Wpis ten powstał jako próba usystematyzowania mojej wiedzy po przeczytaniu książki "Domain-Driven Design: Tackling Complexity in the Heart of Software" Erica Evansa.&lt;/p&gt;

&lt;p&gt;Oprogramowanie jest najczęściej tworzone po to, aby rozwiązywać problemy biznesowe pochodzące z domeny świata rzeczywistego. W podejściu Domain Driven Design musisz od samego początku zrozumieć, że oprogramowanie wywodzi się z tej domeny i jest z nią głęboko powiązane. Mimo, że składa się z kodu nie należy go postrzegać tylko jako obiekty i metody.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;W książkach przełożonych na język polski pojęcie "Domain Driven Design" tłumaczone jest jako "Projektowanie Sterowane Domeną", "Projektowanie oparte na dziedzinie", "Projektowanie Dziedzinowe".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aby stworzyć dobre oprogramowanie, musisz wiedzieć, o co w nim chodzi. Nie możesz stworzyć systemu oprogramowania bankowego, jeśli nie masz dobrego zrozumienia, o co chodzi w bankowości, musisz przedtem zrozumieć tę domenę.&lt;/p&gt;

&lt;p&gt;Jak sprawić, by oprogramowanie harmonijnie pasowało do domeny? Najlepszym sposobem na to jest uczynienie oprogramowania odzwierciedleniem domeny. Musi ono zawierać podstawowe koncepcje i elementy domeny oraz precyzyjnie realizować relacje między nimi. Oprogramowanie musi modelować domenę.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Domena. Sfera wiedzy, wpływu lub działalności. Obszar tematyczny, do którego użytkownik stosuje program to domena oprogramowania.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Więc zaczynamy od domeny. Domena jest czymś ze świata rzeczywistego, aby stała się kodem musimy stworzyć abstrakcję domeny. Wiele dowiadujemy się o domenie podczas rozmów z ekspertami domenowymi. Ale ta surowa wiedza nie da się łatwo przekształcić w konstrukcje oprogramowania, chyba, że zbudujemy jej abstrakcję. Na początku będzie niekompletna, ale z czasem będziemy ją ulepszać. Czym jest ta abstrakcja? To model domenowy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Model. Zestaw abstrakcji który, opisuje wybrany aspekt domeny i który, może być użyty do rozwiązania problemu dotyczącego tej domeny.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wg Erica Evansa model domeny nie jest konkretnym diagramem. Jest to idea, którą ma przekazać diagram. Model jest istotną częścią projektowania oprogramowania. Potrzebujemy go, aby poradzić sobie z jego złożonością. Kiedy zostanie wyrażony, możemy zacząć projektować kod stosując różne podejścia takie jak Waterfall, Agile, Extreme Programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Język wszechobecny
&lt;/h2&gt;

&lt;p&gt;Eksperci domenowi i programiści powinni wymieniać się wiedzą wykopując pojęcia z domeny. Może to być proces chaotyczny, niemniej jednak niezbędny do zrozumienia dziedziny. Takie podejście zwykle ma pewne początkowe trudności ze względu na barierę komunikacyjną. Programiści myślą w kategoriach klas, metod, polimorfizmu, OOP, ale eksperci domenowi prawdopodobnie nic o tym nie wiedzą. Znają się za to na swojej specjalizacji. Projekt napotyka problemy, gdy członkowie zespołu nie mają wspólnego języka do omawiania domeny.&lt;/p&gt;

&lt;p&gt;Podstawową zasadą DDD jest użycie języka opartego na modelu. Poproś zespół, aby konsekwentnie używał tego języka w kodzie oraz wszystkich formach komunikacji. Z tego powodu język ten nazywany jest Językiem Wszechobecnym (Ubiquitous Language). Eksperci dziedzinowi powinni sprzeciwiać się terminom których sami nie rozumieją ponieważ oznacza to, że coś jest nie tak.&lt;/p&gt;

&lt;p&gt;Czego można używać do języka? Mowy, diagramów lub pisma. Zalecanym sposobem komunikowania modelu jest wykonanie kilku małych diagramów zawierających podzbiory modelu czyli klasy i relacje między nimi. Dokumenty te mogą być nawet rysowane ręcznie, ponieważ są tymczasowe i mogą zostać zmienione w niedalekiej przyszłości zanim model osiągnie bardziej stabilny status. Uważaj na długie dokumenty. Ich napisanie zajmuje dużo czasu i mogą stać się przestarzałe, zanim zostaną ukończone. Możliwa jest również komunikacja za pomocą kodu.&lt;/p&gt;

&lt;p&gt;Język Wszechobecny obowiązuje w obrębie jednego Kontekstu Ograniczonego gdyż pojęcia mogą mieć różne znaczenia. "Lot" w  zależności od kontekstu może oznaczać start i lądowanie inne definicje odnoszą się do konserwacji samolotu lub biletowania przelotów. Ponieważ każda z tych definicji „lotu” jest jasna wyłącznie we własnym kontekście, to każda powinna zostać ujęta w osobnym Kontekście Ograniczonym. Ujęcie ich wszystkich w jednym wspólnym Kontekście Ograniczonym doprowadziłoby do pomieszania pojęć.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Język Wszechobecny. Język wypracowany wokół modelu domeny i używany przez wszyskich członków zespołu w obrębie Kontekstu Ograniczonego do komunikacji przy pracy nad oprogramowaniem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Kontekst ograniczony
&lt;/h2&gt;

&lt;p&gt;Każdy model ma kontekst. Kiedy tworzymy aplikację, która ma współdziałać z inną starszą aplikacją, jasne jest, że nowa aplikacja ma własny model i kontekst. Nie mogą być łączone, mieszane ani mylone. Ale kiedy pracujemy nad dużą, aplikacją sami musimy zdefiniować kontekst dla każdego tworzonego modelu.&lt;/p&gt;

&lt;p&gt;Po połączeniu kodu opartego na różnych modelach oprogramowanie staje się błędne i trudne do zrozumienia. Dlatego postaraj się umieścić w modelu te elementy, które są ze sobą powiązane i tworzą naturalną koncepcję. Model powinien być na tyle mały, aby można go było przypisać do jednego zespołu. Trudno utrzymać czysty model, gdy obejmuje on cały projekt firmy, ale znacznie łatwiej, gdy ogranicza się do jednego obszaru.&lt;/p&gt;

&lt;p&gt;Kontekst Ograniczony (Bounded Context) nie jest modułem. Kontekst Ograniczony obejmuje moduł. Zapewnia ramę, w której model ewoluuje.&lt;/p&gt;

&lt;p&gt;Za posiadanie wielu modeli trzeba zapłacić pewną cenę. Musimy  określić granicę i relacje między różnymi modelami. Wymaga to dodatkowej pracy. Nie będziemy w stanie przenosić żadnych obiektów między różnymi modelami i nie możemy swobodnie wywoływać zachowania, tak jakby nie było granicy. Jednak korzyści są tego warte.&lt;/p&gt;

&lt;p&gt;Na przykład chcemy stworzyć aplikację e-commerce która posiada obsługę zamówień oraz magazynu. Stworzenie osobnego modelu dla każdej domeny spowoduje, że mogą swobodnie ewoluować, a nawet stać się oddzielnymi aplikacjami. Aplikacja magazynu może wysyłać obiekty DTO (Data Transfer Object) zawierające informacje o produkcie do zamówień. Dwa modele można rozwijać osobno i należy zadbać o to, aby działał interfejs między nimi.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kontekst Ograniczony. Ustalony obszar zastosowania danego modelu. Kontekst pozwala członkom zespołu na jednoznaczne zrozumienie zakresu, obszaru, który ma pozostać spójny, i oddzielenie go od tego, co może zostać zaprojektowane w sposób niezależny.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8uku71s6lholzlf0mg5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8uku71s6lholzlf0mg5d.png" alt="Kontekst Ograniczony"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Continuous Integration
&lt;/h3&gt;

&lt;p&gt;Model nie jest w pełni zdefiniowany od początku. Powstaje, a następnie nieustanie ewoluuje w oparciu o informacje zwrotne z procesu rozwoju. Oznacza to, że do modelu mogą wchodzić nowe koncepcje, a do kodu dodawane są nowe elementy. Dlatego ciągła integracja jest procesem niezbędnym w Ograniczonym Kontekście. Musimy mieć procedurę używaną do scalania kodu. Im szybciej połączymy kod, tym lepiej.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subdomeny
&lt;/h3&gt;

&lt;p&gt;Domena dzieli się na wiele Subdomen inaczej Poddziedzin (Subdomains) i każda z nich skupia się na mniejszych problemach. Np. E-commerce jako domena składa się z Subdomen: koszyk, płatności czy katalog produktów. W DDD Subdomena jest pojęciem relatywnym. Domena i Subdomena mogą być używane zamiennie. Kiedy używamy słowa Subdomena, podkreślamy, że domena o której mówimy, jest dzieckiem innej domeny wyższego poziomu.&lt;/p&gt;

&lt;p&gt;Subdomena która jest częścią świata rzeczywistego wdrażana jest jako Kontekst Ograniczony. Subdomena określa "co" produkt miałby osiągnąć i znajduje się w Przestrzeni Problemów (Problem Space). Kontekst Ograniczony określa "jak" produkt miałby to osiągnąć i leży w Przestrzeni Rozwiązań (Solution Space). W jednym Kontekście Ograniczonym powinniśmy  zawrzeć jedną Subdomenę. W niektórych przypadkach w jednym Kontekście Ograniczonym może się znaleźć wiele Subdomen, ale nie jest to najbardziej optymalna postać modelu.&lt;/p&gt;

&lt;h3&gt;
  
  
  Destylacja
&lt;/h3&gt;

&lt;p&gt;Duża domena ma duży model nawet po wielu refaktoryzacjach. W takich przypadkach może nadejść czas na Destylację. Ideą jest zdefiniowanie Domeny Głównej (Core Domain), która reprezentuję istotę modelu domeny i nie może zostać zaniedbana i nad którą powinni pracować najlepsi programiści. Produktami ubocznymi destylacji będą Subdomeny Generyczne (Generic) i Pomocnicze (Supporting), które będą obejmować inne części domeny.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mapa kontekstów
&lt;/h2&gt;

&lt;p&gt;Duża aplikacja ma wiele modeli, a każdy ma swój kontekst ograniczony. Choć zespoły powinny pracować nad swoimi modelami, dobrze jest, aby każdy miał wyobrażenie o ogólnym obrazie. Mapa Kontekstów (Context Map) to dokument, który przedstawia Konteksty Ograniczone i relacje między nimi. Mapa kontekstów może być mało szczegółowym diagramem podobnym do tego poniżej.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cuuidkrgbk39ctcfrpk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cuuidkrgbk39ctcfrpk.png" alt="Mapa kontekstów"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ważne, aby wszyscy pracujący nad projektem go podzielali i rozumieli, aby uniknąć nakładania się kontekstów na siebie i problemów gdy system zostanie zintegrowany. Każdy Kontekst Ograniczony powinien mieć nazwę, która jest częścią Języka Wszechobecnego ponieważ pomaga to w komunikacji, gdy mówi się o całym systemie.&lt;/p&gt;

&lt;h3&gt;
  
  
  Istnieją różne sposoby interakcji między kontekstami:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Partnerstwo (Partnership)
&lt;/h4&gt;

&lt;p&gt;Pomiędzy zespołami zachodzi relacja Partnerstwa. Każdy zespół odpowiada za jeden Kontekst Ograniczony. Wspólnie tworzą one Partnerstwo, w ramach którego posługują się zależnymi zestawami celów. Oznacza to, że obydwa zespoły wspólnie odnoszą sukces lub porażkę. &lt;/p&gt;

&lt;h4&gt;
  
  
  Wspólne Jądro (Shared Kernel)
&lt;/h4&gt;

&lt;p&gt;Wspólne Jądro, część wspólna dwóch Kontekstów Ograniczonych, opisuje relację pomiędzy dwoma (lub więcej) zespołami, które współdzielą niewielki model. Zespoły muszą być zgodne co do tego, które elementy modelu mają być wspólne. &lt;/p&gt;

&lt;h4&gt;
  
  
  Klient-Dostawca (Customer-Supplier)
&lt;/h4&gt;

&lt;p&gt;Model Klient-Dostawca opisuje taką relację pomiędzy dwoma Kontekstami Ograniczonymi i ich zespołami, w ramach której Dostawca znajduje się na wyższym szczeblu, Klient na niższym. Dostawca dominuje w tej relacji, ponieważ odpowiada za dostarczanie tego, czego Klient potrzebuje. &lt;/p&gt;

&lt;h4&gt;
  
  
  Konformista (Conformist)
&lt;/h4&gt;

&lt;p&gt;Relacja Konformisty zachodzi, kiedy istnieją zespoły na wyższym i niższym szczeblu, a zespół wyższego szczebla nie ma żadnej motywacji do zaspokajania potrzeb tego drugiego. Zespół niższego szczebla z różnych względów nie może pozwolić sobie na tłumaczenie Języka Wszechobecnego zespołu wyższego szczebla, więc dostosowuje się on do jego modelu.&lt;/p&gt;

&lt;h4&gt;
  
  
  Warstwa Zapobiegająca Uszkodzeniu (Anticorruption Layer)
&lt;/h4&gt;

&lt;p&gt;Warstwa Zapobiegająca Uszkodzeniu jest najbezpieczniejszą relacją, w ramach której zespół niższego szczebla tworzy warstwę translacyjną pomiędzy własnym Językiem Wszechobecnym a Językiem Wszechobecnym zespołu wyższego szczebla. Warstwa ta izoluje model niższego szczebla od jego odpowiednika na wyższym szczeblu i tłumaczy ich elementy.&lt;/p&gt;

&lt;h4&gt;
  
  
  Usługa Otwartego Hosta (Open Host Service)
&lt;/h4&gt;

&lt;p&gt;Usługa Otwartego Hosta definiuje protokół lub interfejs, który daje dostęp do Kontekstu Ograniczonego w formie zestawu usług. Protokół jest „otwarty”, wobec czego wszyscy, którym zależy na integracji z Kontekstem Ograniczonym, mogą skorzystać z niego względnie bezproblemowo. &lt;/p&gt;

&lt;h4&gt;
  
  
  Język Opublikowany (Published Language)
&lt;/h4&gt;

&lt;p&gt;Język Opublikowany, jest dobrze udokumentowanym językiem do wymiany informacji, umożliwiającym prosty przekaz i tłumaczenie pojęć.&lt;/p&gt;

&lt;h4&gt;
  
  
  Oddzielne Drogi (Separate  Ways)
&lt;/h4&gt;

&lt;p&gt;Oddzielne Drogi opisują sytuację, w której integracja różnych Kontekstów Ograniczonych i stosowanie wielu Języków Wszechobecnych nie przynosi istotnych korzyści. Jeśli na przykład żaden z Języków Wszechobecnych nie może zapewnić oczekiwanej funkcjonalności, najlepiej stworzyć własne, specjalistyczne rozwiązanie w obrębie swojego Kontekstu Ograniczonego i pominąć integrację na potrzeby tego szczególnego przypadku.&lt;/p&gt;

&lt;h4&gt;
  
  
  Wielka Kula Błota (Big Ball of Mud)
&lt;/h4&gt;

&lt;p&gt;Sytuacja, w której komunikacja przebiega w każdym kierunku. To jest miejsce w którym nie chcesz być.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxzj3o0rmk5oneic656e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxzj3o0rmk5oneic656e.png" alt="DDD Strategiczne"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Czym jest więc DDD w skrócie?
&lt;/h2&gt;

&lt;p&gt;Domain-Driven Design to podejście do wytwarzania oprogramowania, które charakteryzuje:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Skupienie się na domenie.&lt;/li&gt;
&lt;li&gt;Odkrywanie modelu we współpracy ekspertów domenowych z programistami.&lt;/li&gt;
&lt;li&gt;Posługiwanie się językiem wszechobecnym w granicy kontekstu ograniczonego.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Opisane pojęcia to część Strategiczna DDD czyli filozofia stojąca za Programowaniem Opartym Na Domenie. Projektowanie Strategiczne polega na tworzeniu wstępnego szkicu jeszcze przed przejściem do szczegółów implementacji czyli Projektowania Taktycznego. Skuteczne Projektowanie Taktyczne jest w praktyce niemożliwe, jeżeli nie wychodzi się od Projektu Strategicznego.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elementy Składowe
&lt;/h2&gt;

&lt;p&gt;Elementy Składowe (Building Blocks) to wzorce, które należy stosować w Projektowaniu Opartym Na Modelu. Stanowią one część Taktyczną DDD.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fms4h94fqzdpgoktbc7kd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fms4h94fqzdpgoktbc7kd.png" alt="DDD Taktyczne"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain Driven Laravel
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Active Record
&lt;/h3&gt;

&lt;p&gt;Można spotkać się z opinią, że Laravel nie nadaje się do Projektowania Sterowanego Domeną. Jak już wiesz zgodnie z DDD w centrum naszych zainteresowań musi być domena. Domena powinna być wyizolowana i "głupia" w stosunku do świata zewnętrznego. ORM Eloquent jest implementacją wzorca Active Record co oznacza, że że łączy dwa światy: domenę i logikę dostępu do baz danych. Active Record otacza wiersz w tabeli bazy danych, hermetyzuje dostęp do bazy danych i dodaje do tych danych logikę domeny. Tak więc AR jest reprezentacją rekordu bazy danych w skali 1:1. Jeżeli jednak nagniemy tę zasadę DDD Laravel pozwoli zrobić nam wiele fajnych rzeczy. W rzeczywistości Laravel i DDD nie wykluczają się całkowicie. &lt;/p&gt;

&lt;h3&gt;
  
  
  Co dalej?
&lt;/h3&gt;

&lt;p&gt;W kolejnych wpisach pokażę DDD Taktyczne w Laravelu trzymając się zasad:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skup się na domenie. Bez tego tracimy istotę DDD.&lt;/li&gt;
&lt;li&gt;Nie walcz z frameworkiem. Walka taka jest wyczerpująca i bezcelowa. Chcemy mieć dostęp do dobroci całego frameworka. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;W przeciętnej wielkości projekcie ten rodzaj architekty jako całość jest prawie zawsze przesadą. Nie uda się zastosować "czystego" podejścia DDD. Zamiast tego weźmiemy z niego najlepsze części i połączymy je w pragmatyczny sposób.&lt;/p&gt;

</description>
      <category>ddd</category>
      <category>laravel</category>
      <category>php</category>
      <category>domaindrivendesign</category>
    </item>
  </channel>
</rss>
