A tartományvezérelt tervezés vagy tartományalapú tervezés[1] (angolul: Domain Driven Design, röviden DDD) egy fontos szoftverfejlesztési módszertan, melyben az architektúra elemei (modulok, objektumok, metódusok stb) elnevezésükben és szerkezetükben lekövetik annak a területnek, iparágnak, hivatalnak, kutatásnak a terminológiáját és szemléletét (ez maga a tartomány, vagyis domain), melyhez a szoftver készül. Így a fejlesztők és a terület szakértői „egy nyelvet beszélnek”, sokkal egyszerűbb a közös gondolkodás, és a szoftver természetesebben illeszkedik a terület mindennapjaihoz. A DDD-vel a területen bekövetkező változásokra is jobban tud reagálni a fejlesztőcsapat.[2]
A tartományvezérelt tervezés a következő célkitűzéseken alapul:
A tartományvezérelt tervezés során a szoftverkód szerkezetének és nyelvének (osztályok nevei, metódusai, változói) megfelelnek az üzleti területnek. Például ha egy szoftver hitelkérelmeket dolgoz fel, akkor lehetnek olyan osztályai, mint Hitelkérelem
, Ügyfelek
, és olyan metódusai, mint Ajánlat_elfogadása
és Visszavonás
.
A kifejezés Eric Evans Domain Driven Design című könyvéből származik.[3]
A modell legfontosabb alapfogalmai a következők:[3]
A tartományvezérelt tervezés számos magas szintű koncepciót és gyakorlatot fogalmaz meg.[4] Elsődleges fontosságú a tartomány, az a tárgykör, amelyre a felhasználó egy számítógépes programot alkalmaz. A szoftver tartománya szabályozza a kontextust, azt a környezetet, amelyben egy szó vagy állítás megjelenik, és amely meghatározza annak jelentését. Ebből a fejlesztők felépítenek egy tartománymodellt: egy olyan absztrakciós rendszert, amely leírja a tartomány kiválasztott aspektusait, és amely felhasználható az adott tartományhoz kapcsolódó problémák megoldására.
A tartományvezérelt tervezés ezen aspektusainak célja, hogy elősegítsék egy olyan „általános nyelv” (ubiquitous language) kialakítását, amelyet a terület szakértői, a felhasználók és a fejlesztők használhatnak, és amelyet a tartománymodellhez és a rendszerkövetelmények leírásához használnak. Ez a nyelv a DDD egyik pillére a stratégiai tervezés és a taktikai tervezés mellett.
A tartományvezérelt tervezésben a tartományi réteg az objektumorientált többrétegű architektúra egyik közös rétege.
A területvezérelt tervezés többféle modellt ismer. Az entitás például egy olyan objektum, amelyet nem az attribútumai, hanem az identitása határoz meg. A legtöbb légitársaság például minden járaton egyedi számot rendel az ülőhelyekhez: ez az ülőhely identitása. Ezzel szemben az értékobjektum olyan megváltoztathatatlan objektum, amely attribútumokat tartalmaz, de nincs fogalmi identitása. Amikor az emberek például névjegykártyákat cserélnek, csak a kártyán lévő információkkal (attribútumokkal) törődnek, nem pedig azzal, hogy megpróbálják megkülönböztetni az egyes egyedi kártyákat.
A modellek meghatározhatnak eseményeket is (valami, ami a múltban történt). A tartományi esemény olyan esemény, amellyel a tartomány szakértői foglalkoznak.
A modelleket össze lehet kötni egy gyökérentitással, hogy aggregátummá váljanak. Az aggregátumon kívüli objektumok hivatkozhatnak a gyökérre, de az aggregátum más objektumaira nem. A gyökér-aggregátum ellenőrzi az aggregátumban bekövetkező változások konzisztenciáját. A sofőröknek például nem kell külön-külön irányítaniuk egy autó minden egyes kerekét: egyszerűen csak vezetik az autót. Ebben az összefüggésben az autó több más objektum (motor, fékek, fényszórók stb) aggregátuma.
A tartományvezérelt tervezésben az objektum létrehozása gyakran elkülönül magától az objektumtól.
A tároló (repository) például egy olyan objektum, amely metódusokkal rendelkezik a tartományi objektumok adattárolóból (pl. adatbázisból) történő lekérdezésére. Hasonlóképpen, a gyár (factory) egy olyan objektum, amelynek módszerei közvetlenül a tartományi objektumok létrehozására (példányosítására) szolgálnak.
Ha egy program funkcionalitásának egy része fogalmilag nem tartozik egyetlen objektumhoz sem, akkor azt általában szolgáltatásként fogalmazzák meg.
Bár a tartományvezérelt tervezés nem kötődik eredendően az objektumorientált megközelítésekhez, a gyakorlatban kihasználja az ilyen technikák előnyeit. Ezek közé tartoznak a gyökér-entitások/aggregátumok, mint a parancsok/metódusok hívásainak címzettjei, az állapot egységbe zárása a legfontosabb gyökér-aggregátumokon belül, és magasabb architekturális szinten a határolt kontextusok (bounded contexts).
Ennek eredményeképpen a tartományvezérelt tervezés gyakran társul Plain Old Java Objects és Plain Old CLR Objects (POJO és POCO) objektumokkal. Bár műszakilag a Java és a .NET keretrendszer technikai megvalósítási részletei, ezek a kifejezések azt az egyre inkább terjedő nézetet tükrözik, hogy a tartományi objektumokat pusztán a tartomány üzleti viselkedése, nem pedig egy specifikusabb technológiai keretrendszer alapján kell meghatározni.
Hasonlóképpen, a csupasz objektumok mintája szerint a felhasználói felület egyszerűen egy megfelelő tartománymodell tükörképe lehet. Ha megköveteljük, hogy a felhasználói felület a tartománymodell közvetlen tükörképe legyen, az egy jobb tartománymodell megtervezését eredményezi.[5]
A DDD a szoftverfejlesztés más megközelítéseire is hatással volt. A tartományspecifikus modellezés (domain-specific modeling, DSM) például a doménspecifikus nyelvekkel történő tartományvezérelt tervezés. A DDD nem követeli meg kifejezetten egy doménspecifikus nyelv használatát, bár felhasználható egy ilyen nyelv meghatározásának segítésére és a doménspecifikus multimodellezés támogatására. Másrészt az aspektusorientált programozás megkönnyíti a technikai aggályok (például biztonság, tranzakciókezelés, naplózás) kiszűrését a tartománymodellből, és lehetővé teszi, hogy kizárólag az üzleti logikára összpontosítsanak.
Bár a tartományvezérelt tervezés összeegyeztethető a modellvezérelt tervezéssel és a modellvezérelt architektúrával,[6] a két koncepció mögött álló szándék eltérő. A modellvezérelt architektúra inkább a modell kóddá alakításával foglalkozik a különböző technológiai platformok számára, mintsem a megfelelő tartománymodellek meghatározásával.
A modellvezérelt tervezés által biztosított technikák (tartományok modellezése, doménspecifikus nyelvek létrehozása a szakértők és a fejlesztők közötti kommunikáció megkönnyítése érdekében) azonban megkönnyítik a gyakorlatban a tartományvezérelt tervezést, és segítenek a szakembereknek abban, hogy többet hozzanak ki a modelljeikből. A modellvezérelt tervezés modellátalakítási és kódgenerálási technikáinak köszönhetően a tartománymodell felhasználható a tartományt kezelő tényleges szoftverrendszer létrehozására.[7]
A Command Query Responsibility Segregation (CQRS) egy architekturális minta az adatok olvasásának („lekérdezés”) és az adatok írásának („parancs”) szétválasztására. A parancsok módosítják az állapotot, és megközelítőleg egyenértékűek az gyökér-aggregátumokon vagy -entitásokon történő metódushívással. A lekérdezések olvassák az állapotot, de nem módosítják azt. A CQRS a Bertrand Meyer által megalkotott Command and Query Separation (CQS) elvből származik.
Bár a CQRS nem követeli meg a tartományvezérelt tervezést, a parancsok és a lekérdezések közötti különbséget az aggregátum fogalmával teszi egyértelművé. Az elképzelés lényege, hogy egy adott gyökér-aggregátumnak van egy metódusa, amely megfelel egy parancsnak, és egy parancskezelő hívja meg a metódust. A gyökér felelős a művelet logikájának végrehajtásáért, és vagy egy sor eseményt, vagy egy hibaválaszt ad, vagy csak a saját állapotát módosítja, amely egy adattárolóba írható. A parancskezelő átveszi az állapot mentésével és a szükséges kontextusok (pl. tranzakciók) létrehozásával kapcsolatos infrastrukturális problémákat.
Az event sourcing (kb. események forrásolása) olyan architekturális minta, amelyben az entitások belső állapotukat nem közvetlen szerializálással vagy objektum-reláció leképezéssel követik nyomon, hanem események olvasásával és egy eseménytárolóba való bevitelével.
Amikor az event sourcingot kombinálják a tartományvezérelt tervezéssel és a CQRS-sel, a gyökér-aggregátumok felelősek a parancsok érvényesítéséért és alkalmazásáért (gyakran úgy, hogy a példánymetódusokat egy parancskezelőből hívják meg), majd az események közzétételéért. Ez az alap, amelyre a metódusmeghívások kezelésének logikáját alapozzák. A bemenet tehát egy parancs, a kimenet pedig egy vagy több esemény, amelyeket egy eseménytárolóba mentenek, majd gyakran egy üzenetközvetítőn közzéteszik az érdeklődők számára (például egy alkalmazás nézetében).
Az aggregátumok kimeneti eseményekre történő modellezése még jobban elszigetelheti a belső állapotot, mint az entitásokból származó olvasott adatok kivetítése esetén (mint a szabványos n-szintű adattovábbítási architektúrákban). Ennek egyik jelentős előnye, hogy az axiomatikus tételbizonyítók (pl. Microsoft Contracts és CHESS)[8] könnyebben alkalmazhatók, mivel az gyökér átfogón elrejti belső állapotát. Az események gyakran a gyökér-aggregátum példányának verziója alapján tárolódnak, ami olyan tartománymodellt eredményez, amely optimista konkurrencia révén szinkronizálódik az elosztott rendszerekben.
Bár a tartományvezérelt tervezés nem függ egyetlen konkrét eszköztől vagy keretrendszertől sem, a figyelemre méltó példák közé tartoznak:
A tartományvezérelt tervezés kritikái szerint a fejlesztőknek általában nagyfokú elszigetelést és egységbe zárást kell végrehajtaniuk ahhoz, hogy a modell tiszta és hasznos konstrukcióként maradjon fenn. Bár a DDD számos technikai előnnyel szolgál, mint például a karbantarthatóság, a Microsoft csak olyan összetett tartományok esetében ajánlja, ahol a modell és a terminológia egyértelmű előnyökkel jár a tartomány közös értelmezésének megfogalmazásában.[9]
Ez a szócikk részben vagy egészben a Domain-driven design című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.