Bye Bye MVC

Tworzenie aplikacji nie jest proste, a ostatnio zrobiło się jeszcze bardziej skomplikowane. Bo kiedyś to było łatwo: model i kontroler plus „głupi” widok jako prezentacja. Z tym „głupi” to tylko teoria, bo w praktyce każdy z nas widział różne kreatywne rozwiązania na temat tego co można do widoku wcisnąć. Więc, mieliśmy model i kontroler, rzut monetą i już wybrana funkcjonalność trafia albo tu, albo tam. Stąd też pytania: gdzie powinna być walidacja, w modelu czy kontrolerze. Ale to było kiedyś. W międzyczasie PHP dojrzało (o czym już wspominałem w innym artykule) i teraz, mając wsparcie języka, możemy tworzyć znacznie bardziej elastyczne rozwiązania. Wcześniej też można było się do nich przymierzać, ale wtedy też świadomość programistów PHP dotycząca poprawnej architektury była niewielka (konia z rzędu temu kto np. w 2008 roku wiedział co to DDD, realnie ogarniał SOLID, a nie tylko z nazwy). Teraz mamy jednak rok 2013 i dawno już nadszedł czas czegoś co na potrzeby niniejszego artykułu nazwałem roboczo MVC(B)L, czyli Model View Controller (Business) Logic. Do trójcy dodałem Logikę Biznesową.

I stała się światłość: MVC(B)L

Logika Biznesowa. Coś o czym przez lata zapominaliśmy. Pojawiały się kolejne frameworki, zachwycaliśmy się jak fajnie w nich tworzyć aplikacje, o ile wygodniej mamy, a nikt nie myślał o samej aplikacji. Każdy wchodził w schematy jakie nam frameworki narzuciły jak w masło, nawet nie pytał dlaczego, po co, ale jak to – skoro tak ktoś wymyślił, to tak ma być i ważne, że teraz jest jakby szybciej. Były mniej lub bardziej sztywne reguły to się do nich stosowaliśmy. Architektura aplikacji była efektem ubocznym stosowania frameworka, powstawała niejako przy okazji. W końcu jednak nadszedł czas aby to zmienić – dla mnie takim punktem granicznym jest wydanie Symfony2, bo to pierwszy duży gracz, który tak mocno postawił na architekturę, wzorce i dobre praktyki. Można S2 nie lubić, można mieć mu za złe różne rzeczy, ale trzeba oddać mu cześć i chwałę za to, że skierowało myślenie masy programistów na głębokie wody oceanu architektury aplikacji.

LB

Logika Biznesowa w MVC(B)L jest tym czymś co jest po prostu oczywiste, ale ze względu na ograniczenia jakie (domyślnie) narzucają nam frameworki było pomijane. Jest to nasza aplikacja. Kontroler to sterownik przepływu. Model to emanacja źródła danych, np. bazy. Widok powinien być „bezmyślny”, czystą prezentacją. Dodajmy helpery itp. rzeczy czyli małe klasy/biblioteki pomocnicze, niezwiązane z aplikacją, typowe narzędzia. A reszta to jest logika biznesowa. Gdzie powinna być walidacja? W logice biznesowej. Gdzie powinno być składane i sprawdzane zamówienie? W logice biznesowej. Gdzie powinna być obliczana rata kredytu? W logice biznesowej. To nie są tematy dla modelu i kontrolera. Kontroler może przyjąć żądanie i uruchomić proces składania zamówienia. Dalej powinien on przebiegać w osobnych klasach, osobnej warstwie – logice biznesowej. Jak wszystko przeszło poprawnie, to dane powinny być przekazane do modelu i zapisane do bazy. Najprościej model wyobrazić sobie jako repozytorium korzystające z encji. Encją jest zamówienie (ma swoje ID, a to jest wyróżnik encji), a repozytorium zajmuje się jego pobraniem, zapisaniem i innymi operacjami na encjach, zarówno pojedynczych, jak i np. przygotowywaniu danych do raportów. Cała logika tego co się dzieje przy zamówieniu, obliczanie podatków itp. jest nie w modelu, nie w kontrolerze, ale w warstwie logiki biznesowej – tam jest nasza aplikacja.

Nie ma lekko

MVC(B)L nie jest łatwe. To inny sposób myślenia. Polecam obejrzeć, przemyśleć i raz jeszcze się zastanowić się nad prezentacją Architecture the Lost Years by Robert Martin.

Nie jest to proste, bo to nie jest kolejny framework, nie ma gotowej dokumentacji wyjaśniającej nam jak powinna wyglądać architektura aplikacji którą tworzymy. Jedyny sposób aby do tego dojść to… myślenie. Nie boli, ale łatwe nie jest. Warto poczytać o DDD aby zobaczyć bardziej skomplikowaną wersję MVC(B)L. Załapać o co chodzi z repozytoriami, encjami i jak podchodzić do samej aplikacji. Tylko bez stresu, DDD to jest na prawdę ciężki temat, nie na każdą aplikację, warto jednak trochę o nim poczytać aby zrozumieć jak ważna jest logika biznesowa i „poczuć ducha” aplikacji 😉 Wiele z ogólnych koncepcji jakie tam są poruszone ułatwi nam zrozumienie tematu.

Konkluzja

Można zastanawiać się: po co to wszystko. Przecież mam framework, od lat tworzę w nim strony i jest OK. Jest, ale może być lepiej 😉 A tak serio, MVC(B)L ma kilka istotnych plusów:

  • łatwiej testować. Nie jesteśmy zależni od frameworka, bo kluczową logikę, którą powinniśmy testować mamy poza nim.
  • łatwiej ogarniać. Wszystko mamy w osobnych klasach, nie mieszają się ze sobą koncepcje frameworka, walidacji danych, składania zamówienia i zapisu do bazy. Bardziej świadomie tworzymy aplikację.
  • łatwiej przenosić. Możemy śmiało podmienić cały framework na inny bez ruszania ani jednej linijki kodu z logiki biznesowej. Czasami trzeba będzie dodać pewne proxy, które np. dane z nowego frameworka doprowadzi do standardu jaki miał stary framework i jakiego oczekuje logika biznesowa, ale samej istoty składania zamówienia nie będziemy zmieniali. Jest to plus trudny do przecenienia.
  • łatwiej wynosić. Możemy bardzo łatwo przenosić porcje logiki biznesowej między projektami/frameworkami.

Jeśli masz jakąś funkcjonalność, zastanawiasz się gdzie ją dać i zawsze wybierasz tylko między modelem i kontrolerem, to znak, że powinieneś na chwilę się zatrzymać, przestać myśleć schematami jakie proponują frameworki, a zacząć myśleć o aplikacji.

Bibliografia

Polecam prezentacje:
Clean Architecture and Design by Robert Martin
The A word, Discussion About Architecture

A jak ktoś woli czytać to np. darmowy ebook Domain Driven Design Quickly czy też liczne wpisy na temat DDD na internecie. Ponieważ to jest temat dotyczący architektury, więc nie ma większego znaczenia czy chodzi o PHP, czy Javę czy .NET – łatwo załapać analogię.

DDD było też poruszane w serii artykułów w ProgramistaMag, są one dostępne do pobrania (PDF) na stronie autora wraz z kompletnym przykładem DDD i CqRS (Java i .NET)

I jeszcze raz przypomnę: DDD jest ciężkie, nie chodzi o to aby od razu je całe zrozumieć, ale o to aby zacząć myśleć o logice biznesowej. Jak to załapiemy to wiele rzeczy stanie się oczywiste, a ograniczenia i schematy w jakie pakują nas frameworki będą dobrze widoczne.

Polecam też ten wpis: Clean Architecture by Robert Martin

Freelancer, programista php, wiecznie niezadowolony ze swojego kodu. Toleruje frontend, kocha backend, miłośnik integracji :)

  • Hmmm… używam tego od przeszło 3 lat w Zendzie 😛 nawet nie wiedziałem że tak to się nazywa. Przynajmniej teraz wiem, że nie jestem odmieńcem i że można tak to robić 😛

    Chociaż i tak podstawową walidacje (sprawdzanie czy pola z formularza są uzupełnione, czy parametr został przekazany) robię w C.

    • Inna sprawa że chyba tylko Yii (nie jestem pewien) ma poprawie zaimplementowany MVC, reszta frameworków trochę go zmodyfikowała.
      Wg. standardu MVC, to M powinien wysyłać dane do V. A zwykle obsługa V jest w pełni realizowana w C.

    • thejw23

      Z tym jak to się nazywa to tylko moja luźna sugestia, wymyślona na potrzeby tego wpisu, więc nie ma co się do nazwy MVC(B)L przywiązywać 😉

      • rko73

        Niestety jeżeli chodzi o DDD to ma się to ni jak do MVC, a MVC(B)L to niestety zły skrót. Model w głowach ludzi pracujących z MVC to reprezentacja danych, która czasami przypomina rzeczywistość (Domenę) ale niestety nie o taką domenę chodzi.

        Pierwszym i najważniejszym elementem DDD jest język domeny (ubiquitous language) i jego implenetacja w domenie. Niestety większość programistów MVC rozumie to jako zestaw setterów i getterów w Modelu który jest przekazywany do innej klasy odpowiedzialnej za logikę. Takie modelowanie w DDD to antypattern.

        Dodatkow w MVC model mocno wiąże się z widokiem. Więc kolejny problem w zrozumieniu u osób na co dzień programujących w frameworkach MVC.

        Inna sprawa to enkapsulacja. Na przykład prosta prośba o implementacje w Modelu niemutowalnego obiektu wartościowego które to typy w logice biznesowej są standardem powoduje że większość programistów MVC wymięka bo wciska je w model.

        Dlatego lepiej używać nazwy obiekt domenowy. Nie ma on w głowach programistów MVC żadnej reprezentacji więc lepiej można wytłumaczyć o co chodzi.

  • Grzesiek

    Ciekawy artykuł i fajnie, że pisze się o tym aspekcie programowania. Jednak nie zgodzę się z dwoma tezami:

    1) „…dane powinny być przekazane do modelu i zapisane do bazy”. Encje powinny być przekazywane do warstwy dostępu do bazy. Model modeluje encje.

    2) „DDD jest ciężkie” – po co straszysz ludzi? 🙂 Jestem pewien, że są na tyle otwarci ludzie, że szybko zrozumieją o co w tym chodzi.

    • thejw23

      Ad 1) Tak, to taki skrót myślowy. Generalnie wpis ma być ogólny, bez konkretnej implementacji, bo to już jest temat na osobny artykuł 🙂

      Ad 2) Ja nie straszę, tylko lojalnie uprzedzam 😉

      • Grzesiek

        Ty to wiesz, ale ktoś kto nie zna idei jest wprowadzony w błąd. DDD jednak podkreśla istotną rolę modelu w architekturze aplikacji. Przy tych założeniach Model nie powinien być zależny od bazy danych (to może być cokolwiek: plik tekstowy, json, xml, mysql itd). W takim wypadku DAL powinno się wstrzykiwać do Modelu, a Model powinien przyjmować w argumencie instancję klasy z interfejsem np DalInterface. Piszę o tym, bo dla mnie to było bardzo ważne w zrozumieniu tej koncepcji.
        Zabrakło jeszcze napisania jednego zdania, że encja to rzeczownik, a czynności wykonują usługi. To nie wiele, ale to taka (imho) podstawa, żeby zasiać ziarno ciekawości 🙂

        • thejw23

          To nie jest DDD i nawet nie staram się w tym wpisie być specjalnie blisko niego. Jedyny element wspólny to separacja logiki biznesowej i kilka nazw, ale DDD robi to inaczej i znacznie, znacznie bardziej konkretnie, poukładanie, na innym poziomie. Ja wiem, że Ty to wiesz, ale to było info dla tych, którzy mogli odnieść wrażenie, że opisałem tutaj prawie DDD 🙂

          Celowo nie wchodzę w implementację, bo nie o to w tym wpisie chodzi – to być może będzie temat następnego wpisu, za jakiś czas i też nie będzie to przykład stricte DDD, bardziej „prosta koncepcja jak odseparować logikę od frameworka”. Materiałów na temat DDD jest bardzo dużo, ja od siebie mogę polecić kurs Bottegi oraz książkę „Implementing Domain-Driven Design” którą nie tak dawno napisał Vaughn Vernon.

    • rko73

      Niestety DDD jest ciężkie. Nie wystarczy przeczytać książki. Zrobiłem już 5 projektów w DDD i dopiero piąty tak naprawę ogarnia wszystkie pojęcia DDD.

      Bez urazy 4 lata temu myślałem też że DDD to pikuś. Niestety tak nie jest. To jest inny sposób myślenia co widać w komentarzach ludzi którzy nigdy nie pracowali z DDD.

  • Mokry

    Mhm… Artykuł ciekawy, chociaż szerze mówiąc od jakiegoś czasu nieświadomie wypracowałem u siebie, że logikę biznesową trzymam poza FW w bazie danych. Dlatego też walidację, wszystkie procedury i funkcje oraz sesję trzymam po stronie bazy danych.
    Przy okazji nie miałem żadnego problemu podczas przenoszenia aplikacji już nie na inny FW, ale też na inną platformę.

    • piotrooo

      A co z przenoszeniem na inny SZBD? To FW powinien to ogranąć. Zmieniasz driver bazy danych i nie przejmujesz się tym ze masz jakieś np CHECKI w postgresie które mogą nie działać w MariaDB. Uważam, że logika biznesowa powinna być w modelu a nie bazie danych która ma pomóc jednynie w efektywnym przetrzymywaniu danych.

      • Mokry

        Niestety, ale nie ma rozwiązania idealnego. Zmiany DBMS w ciągu życia aplikacji jako takiej się nie robi, a jeśli już to baaardzo rzadko (częściej zmienisz lub podniesiesz FW). Co najwyżej zdarzy się podniesienie wersji DB co nie stanowi w większości żadnego problemu. Dodatkowo, jeśli aplikacja działa jednocześnie w jakimś FW w PHP i jako apka w Javie, to zmian w mechanizmach logiki biznesowej dokonujesz w jednym miejscu.

        • Potfur

          A co jeśli apka działa na pgsql, mssql, mysql, soap (cholera wie co za nim jest) itd.?
          Kto powiedział, że repozytorium jest jednorodne? 🙂

          • thejw23

            Mając LB z dala od FW i traktując model jako DAL – logiki biznesowej nie interesuje skąd są dane, czy to pgsql, mysql, soap czy rest, można je dowolnie podmieniać sprawdzając tylko spójność danych. Cała logika jest z dala od modelu czyli FW, czyli jest bezpieczna na podmianę źródła danych.

      • thejw23

        Wspomniałem o tym, jeśli model to tylko operacje na bazie, a cała logika odpowiadająca za przygotowanie danych itd jest gdzieś indziej, to podmiana bazy polega na podmianie zapytań plus dopisaniu jakiegoś proxy doprowadzającego dane do stanu oczekiwanego przez logikę biznesową. Odseparowanie logiki od modelu upraszcza sprawę, masz pewność, że zmiana SZBD nie zmieni niczego w logice biznesowej, że przypadkiem nic tam nie namieszasz.

  • Programując aplikacje MVC zawsze mi czegoś brakowało. Właściwego umiejscowienia Logiki Biznesowej 🙂 Dziękuję.

  • Riu

    Dobry wpis. Temat trudny bo i projektowanie jest znacznie trudniejsze niż programowanie.

    • Potfur

      Dlatego to taka fajna robota 🙂

  • letMeSee()

    jedna rzecz:
    po co oddzielać na siłę Twoje BL od MVC jak BL mogłoby się zmieścić w M? i właśnie zastanawiam się czy tego przypadkiem już niektórzy nie stosują bez tej zbędnej teorii 🙂

    • thejw23

      Po co oddzielać? Opisałem to w akapicie Konkluzja. Myślę, że wstęp do DDD by Bottega znacznie lepiej wyjaśnia po co to wszystko: http://www.bottega.com.pl/pdf/materialy/sdj-ddd.pdf‎ i raz jeszcze przypomnę: ja rozpisałem się tylko o wydzieleniu BL z FW, a nie o samym DDD i jego konkretnym podejściu do tego tematu. Jednak czytając o DDD na pewno można dojść do ciekawych przemyśleń i stworzyć swoją własną implementację separacji BL od FW.

      • BL === M. Model to nie tylko warstwa dostepu do danych. To jest wlasnie miejsce na logike biznesowa.

        • thejw23

          Plusy wydzielenia LB z modelu napisałem w akapicie Konkluzja. Więc zadam pytanie: jakie plusy ma trzymanie LB w modelu? Modelu rozumianym jako typowy model z frameworka MVC, jakiś 1 plik, dziedziczący po MainModelClass. Wygoda, to jest pewien plus. Jakieś jeszcze?

          • Problem w tym, ze model rozumiany jako DAO jest nieporozumieniem. W warstwie modelu w MVC nie chodzi o dziedziczyenie z MainModelClass. Active record wrecz zacheca do takiego podejscia i stad mysle wzielo sie cale nieporozumienie 🙂 Przy active record jest nieco trudniej oddzielic logike zapisu do bazy danych od „czystego” modelu. Przy unit of work, implementowanym przez Doctrine2, jest juz duzo latwiej. Mapowanie mozna umiescic w osobnych plikach, a zamiast polegac na konkretnych implementacjach repozytoriow – polegac na interfejsach.

          • thejw23

            Większość FW nadal traktuje Model = AR lub ORM. I do nich upycha wszystko, całą logikę. Doctrine i Symfony2 czy Zend2 to inna liga, tam jest inna architektura i mój wpis nie jest o nich.

            Mea Culpa, we wpisie zabrakło chyba tego stwierdzenia, że punktem wyjścia jest AR/ORM, a nie nowoczesny FW pokroju S2 czy Z2 + Doctrine, gdzie na prawdę można wiele zdziałać z architekturą bez poczucia, że się walczy z frameworkiem.

          • Moze brak mi perspektywy, bo dawno nie pracowalem z frameworkiem, ktory by mnie tak ograniczal 😉

          • łukasz

            Dokładnie taki komentarz chciałem przeczytać/napisać czytając ten post. Zupełnie sztuczne wydzielanie, które bierze się właśnie z używania ActiveRecord jako modelu i szablonu jako widoku. Co sprowadza MVC do pojedynczych klas/plików, a to mają być warstwy.
            Fajnie, że napisałeś ten post, bo może faktycznie komuś otworzy oczy, ale ze sztucznym dublowaniem warstw zgodzić się nie mogę.

          • thejw23

            Z tego co widzę, to tak na prawdę wszystko rozbija się o słowo „warstwa”. Czy LB to nowa warstwa, czy jedna z warstw modelu. Trochę było po drodze niezrozumienia o jaki model mi chodzi (kolejny problem z nazwą), dopiero przejście na AR/ORM to wyjaśniło – my bad, na przyszłość będę bardziej precyzyjny. Ale do rzeczy. Tekst jest niewątpliwie skierowany do początkujących i pewno też średniozaawansowanych. Nie oszukujmy się, dla takich osób Model = AR/ORM bo tak głosi wiele frameworków, taki styl promują. On nie ma warstw. Pisząc tekst bardziej techniczny, wyjaśniający pewne pojęcia i ich szerokość… moim zdaniem zagubiłbym gdzieś przekaz. A przekaz jest prosty: Nie pakujmy LB do pliku z AR/ORM. Tak, wiem, jest oczywisty 🙂 Ale nie dla wszystkich. I mam wrażenie, że takie podejście do tematu bardziej otworzy oczy – proste wyjaśnienie, że LB powinna być gdzieś indziej niż nam proponują frameworki (oczywiście nie wszystkie). Ten tekst to wstęp do myślenia, jak ktoś zacznie to podałem kilka linków, z nich trafi na inne linki i sam dojdzie do tego jak to powinno wyglądać. Łatwo jest przeczytać jakiś tekst i nic z niego nie rozumiejąc zacząć ślepo stosować, tego uczą nas dokumentacje i pokazywanie, że Model = 1 plik. Ja chciałem pokazać, że nie tak to powinno wyglądać, skłonić do zastanowienia i świadomego zadecydowania gdzie powinna być logika biznesowa. Że coś takiego istnieje, bo frameworki zdają się o tym zapominać. Na szczęście powstają nowe, które już nie pomijają tego tematu, a starsze wymierają.

            Bo z tym, że w AR/ORM lepiej nie mieć LB raczej nikt nie polemizuje. Wszystko poszło o słowo „warstwa” 😉

            Oczywiście cieszę się, że są te wszystkie komentarze, że jest dyskusja, bo o to tutaj chodzi – dzielić się poglądami, wyjaśniać, tłumaczyć. W skrócie: uczyć się od siebie. Ja się nauczyłem, aby lepiej dobierać słowa 🙂

      • letMeSee()

        stosujesz już LB? przenosiles juz LB z jednego frameworka na drugi? widzisz różnice? przecież głównie jak się cos przepisuje to nie z frameworka na framework tylko na inne języki, a wtedy LB nic nie znaczyznaczy (jak by to było w M). Ja tego trochę nie rozumiem po co na sile tworzyć 4 ta warstwe , której we frameworkach nie ma i którą (i jej implementacje) i tak trzeba bedzie pisać w przypadku przepisania. wg mnie dobrze zaprojektowany M załatwia sprawe

        • thejw23

          Wiele razy przepisywałem strony na ich nowsze wersje. Frontend zmienił się bardzo, Backend trochę unowocześnił graficznie, ale generalnie biznes za tym stojący pozostał bez zmian, bo firma działa bez zmian. Z zewnętrzną LB można zaoszczędzić sporo pracy, wpiąć się w gotowe, sprawdzone, działające mechanizmy bez ryzyka ich zepsucia. Można napisać do nich testy niezależnie od frameworka, zrobić nową wersję strony i wpiąć się sprawdzając czy wszystko działa. itp itd.

  • Damian Tylczyński

    Przepraszam za tak oschły komentarz, ale mam dosyć nic nie wnoszących tekstów wymyślających na swoje potrzeby nic nie znaczące skróty. MVC(B)L? Nie wiem czy wymyślił to autor, ale błagam Was, odnośnie MVC:
    1) [M]odel odzworowuje część rzeczywistości.
    2. Jedną ze składowych modelu (rzeczywistości) są procesy w nim zachodzące.
    3. Procesy zaś to oczywiście nasza logika biznesowa.
    Kto wyciąga procesy biznesowe jako osobną składową? Prawdopobnie ktoś kto cały czas myśli o modelu jako o abstrakcji dostępu do danych… Tak więc z całym szacunkiem do kogokolwiek (widzę jakiś filmik na YouTube stąd wątpliwość) kto jest autorem tego skrótu: MVC(B)L to kompletne, nic niewnoszące, nieporozumienie. To chyba nowy trend w internecie by to co znane i zrozumiałe nazywać inaczej, i publikować dalej. Taki nietrafiony remix.

    • Grzesiek

      Artykuł nie jest o MVC, a o innej architekturze, w której ideą jest właśnie wyodrębnienie logiki biznesowej. Dochodzi dodatkowa warstwa. To wcale nie oznacza, że ona jest lepsza, jest po prostu inna.
      Co do tego co napisałeś o samym MVC, to zgadzam się, taki podział jest (imho) dobry.

      PS. Ja np wyciągam procesy biznesowe jako osobną składową. Nie narzekam, podoba mi się to rozwiązanie 🙂

    • thejw23

      Skrót MVC(B)L jest tylko nic nie znaczącą nazwą stworzoną na potrzeby tego wpisu (o czym wspomniałem w tekście).

      Kto wyciąga procesy biznesowe jako osobną składową? Wystarczy np. pogooglać na temat DDD. A dla PHP jest to temat głównie związany z Symfony2.

      I tak jak Grzesiek napisał: „Artykuł nie jest o MVC, a o innej architekturze, w której ideą jest właśnie wyodrębnienie logiki biznesowej. Dochodzi dodatkowa warstwa. To wcale nie oznacza, że ona jest lepsza, jest po prostu inna.”

      Dokładnie o to chodzi. Dużo osób jest zafixowanych na MVC, nie widzi świata poza MVC, uważa, że prawie całą aplikacja powinna być rozsmarowana po modelach, kontrolerach i może paru rzeczach na boku. Ale jest inny świat i to chciałem pokazać tym wpisem. A w tym świecie jest kraina przewidziana dla dużych systemów: DDD.

      Jeśli chodzi o filmik, to jest to prelekcja będąca gdzieś pomiędzy tym co ja napisałem czyli prostym „wyodrębnijmy logikę biznesową”, a złożonym DDD, jaką prowadzi Martin Fowler „Uncle Bob”. Warto obejrzeć, posłuchać mądrzejszych od siebie.

      • Damian Tylczyński

        MVC cały czas jest aktualną architekturą, także w kombinacji z DDD. Miejsce DDD jest w modelu, bo gdzieżby indziej? I to właśnie o samym DDD powinien być wpis: o błędach w implementacji modelu jako warstwy dostępu do danych, połączonej w relacji 1:1 ze źródłem danych oraz o teorii grubego-chudego kontrolera, a nie o wyssanych z palca teoriach architektonicznych.

        • Grzesiek

          Uzasadnij czemu miejsce DDD jest w modelu? Czemu nie może być gdzie indziej?

          • Damian Tylczyński

            Pisałem już wcześniej. Model, niezależnie czy matematyczny, fizyczny czy ten, który istnieje w architekturze MVC jest odzworowaniem skrawka rzeczywistości. Modelować coś, np. w symulacji komputerowej, to znaczy opisywać zachowanie pewnego układu. Układ ma swoje właściwości i procesy, które w nim zachodzą. Wrając do naszego przykładu. Pisanie, że logika biznesowa (procesy) zachodzą poza modelem to bzdura. Mylicie model z warstwą dostępu do danych – taka interpretacja pojęcia „model” zaistniała ze względu na wszechobecne implementacje tzw. grubego kontrolera i funkcjonuje często, ale co najważniejsze, jest błędna.

          • Grzesiek

            Nie, dla mnie model jest odpowiedzialny za wymodelowanie jakiegoś obiektu, który ma odzwierciedlenie w rzeczywistości. Z niego wychodzi encja, która ma w sobie settery, gettery itd. Ale encja sama z siebie nie decyduje o tym co się z nią stanie. Od tego jest właśnie logika biznesowa. Ona przyjmuje argumenty i to w niej jest zawarty „mózg”. Do niej (LB) trafiają elementy, które są niezbędne, aby proces biznesowy zaszedł. Rezultatem „pracy” logiki biznesowej może być nowa, zupełnie inna encja, lub ta sama encja, ale dostosowana do oczekiwań.

            Modelowanie, to nie opisywanie zachowań, to opisywanie obiektu, jego właściwości i możliwości. Z modelowania wychodzi encja, która jest poddawana „czynnościom”.

            Nie mylimy modelu z DAL. To DAL jest wstrzykiwany do modelu. Ostatecznie musi być źródło danych, aby móc wymodelować obiekt.

            Ostatecznie dochodzi kwestia grubego kontrolera. Ta architektura pozwala doskonale uniknąć takiej sytuacji, ze względu na to, że kontroler przekazuje LB co chce zrobić. To logika biznesowa decyduje o tym czy może to zrobić.

          • Damian Tylczyński

            Dla Ciebie „model” może być nawet zupą pomidorową, ale to nie zmienia faktu, że logika biznesowa zachodzi w modelu, a nie gdzie indziej. DAL jest elementem pomocnicznym bez którego „model” nie może funkcjonować – stan modelu (i jego encji) musi być przecież gdzieś przechowywany. Kombinujesz z tym wydzieleniem logiki biznesowej jak możesz. Traktujesz model jako fabrykę encji (de facto repozytorium) co jest kolejnym bezsensownym uproszczeniem.

            Na model, zachaczajac o praktyki DDD, składa się:
            1. warstwa dostępu do danych [DAL]

            2. współpracująca z [repozytorium]
            3. które wypluwa [encje]
            4. w których mogą być zapisane procesy biznesowe
            a) jeśli proces biznesowy nie ma właściciela proces może istnieć jako osobny byt.

          • Grzesiek

            I ok, teraz rozumiem co masz na myśli i stwierdzam, że masz rację. Dla mnie to co ja mówię i to co Ty mówisz jest prawdą. Znam to o czym Ty piszesz, ale ja wybrałem jednak inne rozwiązanie.

          • thejw23

            Można też tradycyjny model w MVC jaki nam oferują frameworki (czyli zazwyczaj 1 plik z 1 klasą która dziedziczy po czymś w stylu MainModelClass) traktować jako DAL, a resztę (repozytoria, encje itd, generalnie logikę biznesową) wydzielić do osobnych klas w miarę niezależnych od FW (o ile się da).

          • Damian Tylczyński

            Jak najbardziej.

  • Daniel R

    Dobry wpis. Czekam na rozwiniecie tematu i w wolnej chwili siadam do bibliografii 😀

  • Gość

    A ja nadal piszę strukturalnie (z użyciem klas tam gdzie to ma sens) i nie mam tych problemów co wy 😛 … i wiecie co? wcale się tego nie wstydzę

    • aaltruista

      To znaczy że nie umiesz programować albo nie robiłeś nic większego… Przez takich jak ty ludzie się śmieją z PHP… W życiu bym cie nie zatrudnił do jakiejkolwiek pracy. To może być dla Ciebie szok ale ludzie pisza obiektowo z pewnych przyczyn

      • erochan

        Ja się już poduczyłem kilka języków c,c++,c#,php,python,java i ze wszystkich i tak wolę php bo konkretne projekty się w nim robi no i łatwo jak dla mnie. A poza tym kto co lubi nie czepiajmy się tego kto jak chce programować. MVC i MVC(B)L to piszę się w dużych projektach który nie będzie rozwijany o żadne dodatki itp. to czemu by nie napisać tylko strukturalnie. Zobacz jak się programuje w C, tam to tylko strukturalnie a obiektowo wcale, jest objective-c ale tylko na osx więc się nie opłaca wydawać kilka tysiaków po to by się nauczyć programować w objective-c.

  • Damian W.

    Hmm, ja w sumie od zawsze unikałem wrzucania logiki do kontrolerów, czy modeli. Tworzę osobny folder, zwany „plugins” albo „modules” i tam umieszczam klasy. W kontrolerach tworzę ich instancje, operuję na nich, oczywiście posiłkując się modelami (którym także dorzucam metody gdy trzeba wykonać jakieś obliczenia).

    Zauważyłem, że programiści często wrzucają za dużo kodu i logiki do kontrolerów, a także często popełniają błąd poprzez traktowanie modeli tylko jako strukturę danych (bez zachowania, tj. bez metod).

    Model to nie tylko dane.

  • Adam

    Bardzo ciekawy post, tego mi brakowało w projektowaniu.

    Tylko gdzie umieścić logikę biznesową? Jak do niej podejść? Widzę kilka rozwiązań:

    1. Robimy metamodele, czyli modele, które nie mają własnych baz danych a jedynie za pośrednictwem normalnych modeli realizują większe zadania. Przykładowo model młotek i model gwóźdź odzwierciedlają podstawowe modele ale metoda PrzybijCośGwoździami() już jest logiką biznesową w metamodelu.

    2. Zrywamy całkowicie z MVC i dzielimy aplikację na dwie połówki: MA (Model, Api) gdzie api jest właśnie warstwą logiki biznesowej oraz drugie AVC (Api, View, Controller) gdzie zamiast korzystania z modeli widoki i kontrolery są głupie a jedynie korzystają z api. W takim układzie drugi element nie ma żadnej logiki biznesowej, której api nie udostępni.

    Czekam na rozwinięcie tematu na blogu, ew na podcast w tym temacie 🙂

  • Rafał Łużyński

    Jak juz ktoś chce stosować DDD, to przede wszystkim musi przeczytać książkę Evansa – http://books.google.pl/books/about/Domain_driven_Design.html?id=7dlaMs0SECsC&redir_esc=y. Bez tego lepiej nawet nie próbować.

  • freebox

    Hmm, nie czytałem nigdy o tym, a stosuję :). Pewnie wynika to z faktu, że jako programista aplikacji desktopowych mentalnie i funkcjonalnie przenoszę interfejs aplikacji z Delphi do PHP. Kontroler u mnie to tylko złapanie tego, co przychodzi i zależnie od informacji skierowanie do odpowiedniego modułu. Mam 2 foldery modułów – jeden nie związany z żadnymi konkretnymi widokami i zawiera biblioteki/klasy uniwersalne, np. menu, permissions itp. i drugi, podzielony na moduły/foldery funkcjonalnie, np. users, products itd. Każdy z modułów (folderów) jest samodzielny (można go usunąć z aplikacji) i zawiera plik/klasę bazową dziedziczacą z głównej klasy modules i klasy/pliki z akcjami powiązanymi z widokami w podfolderze widoków modułu – jedna publiczna metoda generująca widok na plik + prywatne metody.Klasy dziedziczą z klasy bazowej modułu. Do tego dochodzi jedna klasa na moduł z metodami nie generującymi bezpośrednio widoku, np. walidacja biznesowa, usuwanie rekordu w widoku listy lub edycji itd. oraz klasa modelu dla modułu, dziedzicząca z głównej klasy modeli – generatora zapytań. Widoki modułu generują tylko fragmenty związane z samym modułem i zwracają do kontrolera informację o gotowości, a kontroler wywołuje widok całościowy, który sam pobiera dynamicznie (ajax) widoki modułów. Po co? Ano po to, żeby będąc w widoku można było dynamicznie, zależnie od zdarzenia zmieniać część treści strony bez konieczności przeładowania całego widoku. Przykład: dodajemy produkt do magazynu, ale okazuje się, że konieczna będzie nowa kategoria produktów, więc w trakcie dodawania produktu można dodać nową kategorię bez przerywania transakcji dodawania produktu. Dodatkowo widoki korzystają z socketów, więc zmiana danych na stronie wprowadzona przez innego użytkownika jest widoczna w czasie rzeczywistym. Tak więc MVC w swojej tradycyjnej postaci przestaje się liczyć na rzecz CBLAV – Controller + Business Logic (czy Modules jakbkto woli) + Active View, a aplikacja napisana w CC+ lub Delphi ma taką samą funkcjonalność jak ta w PHP + Ajax.

Send this to friend

webmastah.weekly
Cotygodniowa porcja linków ze świata WEBDEV BEZ spamu, TYLKO samo mięcho!
Zobacz poprzednie wydania. Dołącz do 2 tysięcy webdeveloperów!
HTML5, CSS3, JS (React, Angular, Ember, Vue), PHP, SQL
webmastah.weekly
Cotygodniowa porcja linków ze świata WEBDEV BEZ spamu, TYLKO samo mięcho!
Zobacz poprzednie wydania. Dołącz do 2 tysięcy webdeveloperów!
HTML5, CSS3, JS (React, Angular, Ember, Vue), PHP, SQL