Skip to content
Mararok edited this page May 7, 2020 · 2 revisions

Wstęp

Architektura modularnego monolitu(więcej o architekturze: tutaj) w którym moduł będą oparte na architekturze heksagonalnej. Projekt będzie oparty o Symfony 5.0 dostosowanym do modularnego rozbijania aplikacji i wycinania ich w łatwy sposób do oddzielnych microserwisów. Modyfikacja obejmuje też dostosowanie obsługi środowiska multi-tenancy(wielu kont klientów).

Core

Zawiera kod współdzielony przez wszystkie moduły ułatwiający budowanie modularnego monolitu, w tym zawiera kod do obsługi zmiany kontekstu konta(proces zmiany kontekstu konta powinien być niewidoczny dla modułów).

Doctrine ORM

Konfiguracja

Bazy danych:

  • system - zawiera tabele z modułów systemowych, ma własne połączenie i EntityManagera, który rejestruje tylko elementy ze wszystkich modułów oznaczonych jako systemowe.
  • account_ - zawiera tabele z modułów konta, ma własne połączenie(specjalny mechanizm dynamicznie wybiera bazę na podstawie przekazanego id konta - mechanizm przewiduje wiele hostów baz) i EntityManagera, który rejestruje tylko elementy ze wszystkich modułów oznaczonych jako moduł konta.

Moduł

Podział

  • Systemowy - to moduły, które nie potrzebuje do swojego działania żadnego konta, są to jakieś moduły administracyjne.
  • Konta - to moduły, które potrzebują do swojego działania kontekstu konta. Ważne, moduł nie powinien wiedzieć, które obecnie konto jest wybrane.

Struktura katalogów

  • Domain - zawiera logikę biznesową(jest nie powiązana z żadnym frameworkiem) wystawia porty.
  • Application - zawiera punkty wejścia do domeny(Serwisy Aplikacji, CQRS).
  • Infrastructure - zawiera adaptery do komunikacji ze światem zew. np. RestApi, obsługę Doctrina, Messaging itp.

Domain

Serce każdego modułu zawiera logikę biznesową nie powiązaną z żadnym frameworkiem. W katalogu obowiązuje podział pod względem building bloków DDD:

  • Entity - zawiera wszystkie encje domeny
  • Repository - zawiera wszystkie repozytoria domeny
  • ValueObject - tutaj znajdziemy wszystkie obiekty wartości danej domeny
  • SharedKernel - zawiera elementy domeny które mogą wykorzystywać inne moduły
  • Service - serwisy domenowe
  • Exception - wyjątki ściśle powiązane z daną domeną
  • Policy - polityki

Application

Symfony w projekcie jest tak skonfigurowane, że z automatu zarejestruje wszystkie handlery komend, zapytań i eventów dla danego modułu, muszą tylko zaimplementować odpowiednie interfejsy markerów z Core.

  • Command - zawiera wszystkie komendy do domeny, które można wykonać w danym module, struktura: podfolder z nazwą komendy i klasy:
    • <nazwa-komendy>Command
      • implementuje: App\Core\Message\Command\Command,
      • zawiera dane do wykonania komendy,
      • immutable - tylko gettery
    • <nazwa-komendy>CommandHandler
      • implementuje: App\Core\Message\Command\CommandHandler
      • __invoke(Command $command): void
  • Query - zawiera wszystkie zapytania do domeny, które można zadać w danym module, struktura: podfolder z nazwą komendy i klasy:
    • <nazwa-zapytania>Query
      • implementuje: App\Core\Message\Query\Query,
      • zawiera dane do wykonania zapytania,
      • immutable - tylko gettery
    • <nazwa-zapytania>QueryHandler
      • implementuje: App\Core\Message\Query\QueryHandler
      • __invoke(Query $query): void

Infrastructure

Zawiera wszystko co potrzebne do kontaktu ze światem zewnętrznym(obsługa bazy danych, rest api). Moduły które udostępniają REST api komunikują się z domeną poprzez komendy i zapytania, kontroler musi:

  • znajdować się w App\Module<nazwa-modułu>\Infrastructure\Rest\Controller
  • dziedziczyć po wybranej bazie kontrolera z App\Core\Rest\Controller

Symfony jest tak skonfigurowane że automatycznie zarejestruje routy kontrolera na podstawie markera: App\Core\Rest\Controller\Controller

Config

Część rzeczy, które da się zrobić ogólnie dla wszystkich modułów jak automatycznie rejestrowanie kontrolerów są robione w domyślnym Symfonowym config/services.yaml. Elementy specyficzne dla danego modułu znajdują się w config/modules/<nazwa-modułu>:

  • services.yaml - importowany w głównych serwisach
  • doctrine.php - zawiera dodatkową konfigurację Doctrina dla modułu
    • isAccountModule - definiuje czy moduł działa w kontekście konta - wtedy rejestrowane jest mapowania dla EntityManagera od kont
    • enumTypes - lista klas które należy zarejestrować jak typ enum w Doctrinie