Wpis z mikrobloga

W dwóch moich projektach w PHP opartych na Koseven wdrożyłem CQRS i to w dość prosty sposób w prostych CRUD-ach i jedyne co mogę powiedzieć to to że ma to same zalety, nie widzę wad (jak na rozmiar tych aplikacji) i zbytniej komplikacji kodu, tylko nie wiem czy to podejście które zastosowałem jest do końca prawidłowe. Tak jak przeglądałem niektóre tutoriale i kody na github temu poświęcone, realizacja w PHP wygląda tak. Każdy Command to właściwie tylko zwykła encja, gettery i settery i przyjmowanie danych np. z POST w konstruktorze, każdy Command Handler wykonuje jakieś operacje np. na ORM biorąc tylko dane z tej encji przez jej gettery i każdy Command ma swój osobny Command Handler. A Command Bus jest jeden i przy użyciu prostego mechanizmu refleksji przyjmując instancję Command odnajduje właściwy Command Handler.
Pierwszy taki przykład to jest tutaj:
https://mevelix.com/articles/laravel-cqrs-from-scratch,1

Na fajnie, spoko, tylko tak się zastanawiam czy w takich frameworkach jak CI, FuelPHP czy Koseven ma sens aż takie rozbijanie? Ja zrobiłem to tak. Każdy Command bierze tylko dane np. z $_POST i wykonuje jakieś operacje np. bazodanowe na ORM w swojej metodzie execute i mam tylko jeden Command Handler dla wszystkich Command który tylko w swojej handle obsługuje wyjątki, profilowanie i hooki np. success, failure, always itd. Command handler po prostu wywołuje metodę execute z komendy jako parametr swojej metody handle, przyjmując tylko instancje Command. Każde Query pobiera np. dane z bazy przez jakiś ORM i mam też tylko jeden główny Query Handler obsługujący wyjątki, profilowanie i hooki. Bardzo dobrze to mi się sprawdza. Żadnego overengineering.

Czy to są tylko szczegóły implementacyjne? W Laravelu inaczej się programuje niż w wymienionych tu frameworkach i pewnie to podejście rodem z tutoriali jest celowe. Ale nie chcę zbyt komplikować kodu i rozbijać na nie wiadomo ile klas. W każdym razie podejście jest bardzo ciekawe. Strasznie jestem ciekaw jak dużo programistów komplikuje sobie pracę, tworząc przeinżynierowane potworki tylko po to żeby się potem pochwalić w CV nowym fantastycznym słowem kluczowym? Co takiego konkretnego daje to że każdy Command ma być tylko zwykłą encją i ma mieć swój Command Handler to nie wiem. Nie można by tego zredukować tylko do jednej klasy Command?

#programista15k #cqrs #programowanie #php
  • 26
  • Odpowiedz
  • Otrzymuj powiadomienia
    o nowych komentarzach

koseven


O matko. Aż mi się przypomniał 2012, jak zaczynałem programować, kohana 3.1, hmvc, aż łezka się kręci.
Ale żeby ktoś to w 2023 używał to nie wiem
  • Odpowiedz
@daro1: no u mnie to się średnio sprawdzało. To znaczy kiedy jeszcze w PHP grzebałem to na upwork mogłem dostać każdy projekt na Kohana, bo nikt inny już wtedy w tym nie robił, a ja miałem kilkanaście tych projektów, własne moduły, itp. Sęk w tym że tych projektów był 1-2 na cały upwork, stawka nie najwyzsza i projekty to głównie support nieciekawy, więc sumarycznie bardziej się opłaca mainstream imo
  • Odpowiedz
@daro1: Nie do końca rozumiem twojego pomysłu do redukowania wszystkiego do jednej klasy Command. Przecież CommandHandler może robić cokolwiek - zapisywać coś do bazy danych, wysyłać request do API, coś liczyć. Jak miałbyś to rozwiązać przy pomocy jendego Command czy CommandHandlera?
  • Odpowiedz
@daro1: Twoje obawy są jak najbardziej słuszne ;)

Strasznie jestem ciekaw jak dużo programistów komplikuje sobie pracę, tworząc przeinżynierowane potworki tylko po to żeby się potem pochwalić w CV nowym fantastycznym słowem kluczowym?

Niestety zbyt wielu. Cała nasza branża jest przeżarta przekomplikowanymi rozwiązaniami, zainspirowanymi jakimiś kursami, prezentacjami lub artykułami. W rzeczywistości większość tych aplikacji nie potrzebuje niczego poza bazą relacyjną i "starym, dobrym CRUD-em". No ale tym nie nakarmisz swojego
  • Odpowiedz
  • 0
@mariecziek: Ja mam wiele osobnych klas Command, każdą do osobnej operacji np. dodaj użytkownika, dodaj produkt, modyfukuj produkt a tylko jedną główną klasę Command Handler która ma za zadanie tylko obsługiwać wyjątki i profilować tzn. czasy wykonania i zużycie pamięci. Po w takich przykładach z tutoriali trzeba tworzyć do wymienionych tu operacji każdą osobną klasę command będącą tylko zwykłą encją (czyli ma tylko pola prywatne, gettery i setery) , osobny
  • Odpowiedz
  • 0
@arsen-zujew: Ja robię projekty na zlecenie klientów którzy i tak się nie znają więc wybieram te technologie które znam najlepiej. Bardzo dobry framework jeśli chodzi o szybkość tworzenia kodu, przynajmniej nie muszę się bawić w jakieś dodawanie przestrzeni nazw jak w Laravelu, bo autoload jest tylko i wyłącznie oparty o położenie plików w katalogach.
  • Odpowiedz
@daro1: Daj przykład kodu. Ale od razu powiem ci, że pomimo, że jestem sceptycznie nastawiony do wielu metodologii/wzorców/zasad, które tylko komplikują kod to tak zasada, że:
klasa albo przechowuje dane albo coś robi jest dla mnie bardzo słuszna i upraszcza zrozumienie kodu.
Z tego co zrozumiałem w twoim przypadku Command przechowuje dane a potem jeszcze na nich operuje, co komplikuje kod.
Ofc klasa która "coś robi" czyli zazwyczaj "service" może
  • Odpowiedz
@daro1: jakbyś patrzył na to, że dentysta by tobie zrobił ząb według procedur czasu PRL i takichże materiałów? No bo mu jest wygodnie, ty i tak się nie znasz, luz i jazda. Tylko u ciebie jest jeszcze taki czynnik że klient nie s-------i i będzie skazany na to żeby cię płacić.
  • Odpowiedz
@daro1: Powiedziałbym tak - jak zawsze wszystko zależy od konkretnego przypadku architektury aplikacji i konkretnych potrzeb.

Czasami opieranie wszystkiego, zwłaszcza CRUD encji o CQRS nie ma sensu, a najchętniej darowałbym sobie używanie encyklopedycznego "Query" (mowa oczywiście tylko o języku PHP), gdy mamy jednocześnie używamy ORM.

Może opowiem, w jaki sposób ja tego
  • Odpowiedz
  • 0
@arsen-zujew: Tylko że kiedyś kochana to był u nas jeden z najpopularniejszych fw jak teraz laravel. Podejrzewam że znalazłby kogoś innego z palcem w dupie bo możliwe że wielu programistów to nadal ogarnia.
  • Odpowiedz
Zawartość "execute" powinna być wewnątrz CommandHandler.
Nie znam tego frameworka ale widzę, że operuje na statycznych klasach zamiast DI.
To nie najlepszy pomysł, nie widać zależności nie da się ich podmieniać do testów.
Generalnie tak jakbyś jechał na globalach albo singletonie.
Nie wiem czy to kwestia frameworka czy tego jak go używasz ale w cywilizowanym frameworku to wygląda tak:
  • Odpowiedz
  • 0
@bmLq: Też mi się wydaje że przyszedł na to najwyższy czas. Symfony. Bo żebym nie wiem jak chciał to w Koseven raczej nie da się zastosować tych praktyk (albo to nie ma sensu). Tak, tam jest albo singletonizm, w stylu Session::instance(), Auth::instance() albo Factory w stylu właśnie ORM::factory. Statyczne metody tworzące nową instancję klasy. I wiele rzeczy jest magicznych, na przykład w modelach ORM nawet nie deklaruje się prywatnych pól
  • Odpowiedz