A cikksorozat első része egy rövid bevezetőt tartalmazott a DDD hátteréről, és arról mit várhatunk a DDD alkalmazásától. Íme a folytatás.
Hogyan képzeljük el?
Eric Evans könyve remek elméleti összefoglaló ugyan – rengeteg valós esettanulmánnyal és példával -, azonban mégis kevés konkrét kódrészletet és technológiai ajánlást ad. Igaz, ez a könyvet időtállóvá is teszi: nem avul el egykönnyen amiatt, hogy újabb és újabb technológiák jelennek meg. Mégis ahhoz, hogy elkezdjünk a DDD szellemében dolgozni, kézzelfogható dolgokhoz kell nyúlnunk.
Az elmúlt évtizedekben egészen a mai napig is a relációs adatbáziskezelők (Relational Database Management System-ek, azaz RDBMS-ek) a legelterjedtebbek. Amikor egy RDBMS-ben tároljuk az adatainkat, az üzleti logikát többféleképpen is megírhatjuk:
- A felhasználói felület közvetlenül az adatbázisba ír: egyszerű alkalmazásoknál ez a legkézenfekvőbb és legegyszerűbb módja az adatok tárolásának. Az általában nem túl képzett PHP-s “szakemberek” által gyártott szoftverektől kezdve, a Delphi-ben megírt sufni alkalmazásokon át még akár a .NET-es platformon megírt programokban is találkozhatunk ezzel a megvalósítási móddal (kulcsszó pl.: data binding). Az űrlapon beviszik az adatokat, az űrlap elvégez egy-két számítást, az eredményeket pedig közvetlenül vagy közvetve beírja az adatbázisba. A kereső felületek önmaguk tartalmazzák vagy állítják össze a lekérdezéshez használt SQL-t is.
- Az üzleti logika az adatbázisban kerül megvalósításra: definiálják a táblákat, annak oszlopait, és tárolt eljárások hívásával valósítják meg az üzleti logikát. A tárolt eljárások végzik az adatok beszúrását, módósítását, törlését és lekérdezését, valamint a különféle számítási algoritmusokat is ezek tartalmazzák. Előnyük, hogy nagyon gyorsak (SQL-re optimalizáltak), hátrányuk viszont, hogy kevéssé rugalmasak: nincs vagy minimális a refaktorálás támogatása, a megvalósítás erősen kötődik az előre definiált 2D-s táblaszerkezetekhez, az IDE támogatás sem erős, és nehezen lehet bennük automatizált teszteseteket írni.
- Az üzleti logika (a felhasználói felülettől leválasztva) teljes egészében objektum-orientáltan kerül megvalósításra (pl. JAVA-ban, .NET-ben), az RDBMS-t csupán adattárolónak használják. Hatalmas előnye tud lenni ennek a megközelítésnek, hogy a teljes üzleti logika egy platformon elérhető, a refaktorálás és az automatizált tesztesetek megírása könnyedén megvalósítható.
A DDD alkalmazásához leginkább a harmadik megoldás passzol, azonban egy objektum-orientált kódban is többféleképpen valósítható meg az üzleti logika. A Martin Fowler által beazonosított minták a következők lehetnek:
- Table Data Gateway: egy adatbázis táblához egy osztály tartozik a kódban (minden osztálynak csak egyetlen példánya van). Ennek az objektumnak a feladata az adott táblába a rekordok beszúrása, módosítása, törlése és lekérdezése (CRUD-műveletek, azaz: creates, reads, updates and deletes). Az objektum tartalmazza mindazon SQL-utasításokat, amelyek ezen műveletek végrehajtásához szükségesek. Pl. az ADO.NET data set-jei.
- Row Data Gateway: itt egy adatbázis tábla egy konkrét rekordjához egy objektum tartozik, amelynek a feladata a CRUD műveletek biztosítása.
- Active Record: itt is egy rekord egy objektum, viszont az objektum már üzleti logikát is megvalósít. Az objektum felelőssége önmagának a lementése, visszatöltése. Fowler szerint egyszerűbb domain model-lek esetén az Active Record még egy jó választás lehet, ahól jórészt csak CRUD-műveletek (creates, reads, updates and deletes) történnek. A gond vele, hogy túlságosan kötődik az adatbázistáblák szerkezetéhez.
- Data Mapper: az objektumok perzisztálása az adatbázisban kvázi automatikusan történhet, amelyről egy object/relational mapper (vagy O/R mapper, pl. Hibernate) gondoskodik. Ez a DDD valódi technológiai támasza, ugyanis a komplex üzleti logikát megvalósító komplex objektumhierarchia (a domain model) könnyedén fejleszthető pl. Javaban, és mögötte az RDBMS-ek által “nyújtott” rugalmatlanság kevéssé korlátozó tényező. A hátránya a dolognak, hogy teljesítményben az így megírt rendszerek (még) alulmaradnak a hagyományos SQL-ben megírt üzleti logika rétegtől, valamint számos új problémával is szemben találjuk magunkat az elején (és közben is :)). Ha ilyenbe kezdenénk, akkor mindenképpen legyen a csapatban egy olyan ember, aki már írt alkalmazást O/R mapper segítségével.
A domain model, az “alkalmazás szíve”
A DDD szellemében megírt alkalmazások központi része a domain model. Csupán technológiailag tekintve a domain model nem más, mint az üzleti probléma objektum modellje, amely egyesíti mind a működést mind az adatokat, összekötött objektumok hálója (Fowler). Ha bonyolultak és állandóan változóak az üzleti szabályok (validáció, számítások, fogalmi rendszer), mindenképpen ezt a megközelítést célszerű alkalmazni (ha adottak ehhez a megfelelő technológiai feltételek is).
Egy domain model esetében kiemelten fontos, hogy a működést az objektumok önmagukban valósítsák meg. A régi EJB 2-s világban alkalmazott módszer az volt, hogy az adatbázis séma alapján elkészítik az osztályokat, amik az adatokat tárolják (entitások), ezeket ellátják egy csomó set-terrel, get-terrel, és magát az üzleti logikát kívül ún. session bean-ekben írják meg (amik az entitások attribútumait lekérdezik, majd visszaírják a kívánt adatokat). Az ilyen “domain model”-t anemic (vérszegény) domain model-nek nevezték el, az üzleti logikát megvalósító állapotmentes metódusokat (EJB2-ben a session bean-ek metódusait) pedig Transaction Script-eknek hívják. Ennek az anti-mintának a hátránya az, hogy az üzleti logika procedurálisan készül el, és nem használja ki az objektum-orientált programozás előnyeit (egységbezárás, felelősség stb). 1 évvel ezelőtt egy microsoftos szakértő szájából is hallanom kellett olyat, hogy az “adatbázisból legeneráljuk az osztályokat”…
Véleményem szerint a domain model azonban több objektumok hálójánál. Ez testesíti meg az üzleti problémáról szerzett ismereteinket, rendszerezi gondolatainkat és egy egységes modellbe foglalja. A modell színtiszta objektum-orientált kód, amely lehetővé teszi a modell egyszerű áttekintését, folyamatos formálását, ahogy egy agyagszobrász formálja a mesterművét.
(folyt.köv.)
U.i. …és ami kimaradt
Köszönet Kristófnak, hogy 2 évvel ezelőtt megismertette velünk a DDD-t, és segített minket az elindulásban