Ubiquitous Language

A területvezérelt tervezés (DDD) nem új keletű téma (Eric Evans több mint egy évtizede formalizálta a koncepciót). Érdekes azonban, hogy a mai napig milyen érdeklődést váltanak ki a témával kapcsolatos alapfogalmak, különösen a .NET közösségekben. Még furcsább, hogy ugyanezeket a fogalmakat hogyan értelmezik félre.

A DDD alapja a mindenütt jelenlévő nyelv fogalmában rejlik. Nem annak meghatározásában rejlik, hogy mi egy entitás, értékobjektum, aggregátum, szolgáltatás vagy tároló.

Az a benyomásunk, hogy aki elkezdi tanulmányozni a DDD-t, elolvassa az Evans-könyv vagy a Vernon-könyv első néhány oldalát, és gyorsan átugrik a mintákat leíró oldalakra.

Gyakran beszélünk olyan informatikusokkal, akik azt gondolják, hogy a definiált mindenütt jelenlévő nyelv azt jelenti, hogy a programozók által írt osztályok és tulajdonságok neve megfelel a tartományi szakértők szókincsének. Ez azonban durva leegyszerűsítés.

Az ubiquitárius nyelv fontosságának megértéséhez kezdjük az alább felsorolt “entitással”:

public class Employee{ public string Id { get; set; } public string Name { get; set; } public string Cpf { get; set; } public decimal Salary { get; set; }}

Ez egy kiváló példa az anémiás megvalósításra! De mielőtt tovább olvasnánk, próbáljuk meg kitalálni, hogy miért:

A mindennapi munkánk során, amikor ezt a példát használjuk, olyan javaslatokat hallunk, hogy ebből az osztályból hiányoznak a viselkedések (Ami igaz is!). Amikor azonban megkérdezzük, hogy mik lennének ezek a “viselkedések”, azt tapasztaljuk, hogy az emberek általános érveket ismételgetnek (olyanoktól, akik szintén nem “értették” az ötletet), és nem tudják azonosítani, hogy mi a baj!

Az egyik leggyakoribb érv az, hogy a tulajdonságbeállítóknak privátnak kellene lenniük. Helyettük “DefineXXX” metódusokra lenne szükség, amelyek validációkat valósítanának meg. Ennek az ötletnek nincs értelme, mert a setterek célja éppen az, hogy értékeket állítsanak be a tulajdonságoknak, és nem lenne probléma, ha érvényesítési logikát implementálnánk beléjük.

Egy entitás metódusainak ki kellene fejteniük az állapotváltozások motivációit. Emellett legalább egy olyan konstruktornak kell lennie, amely képes az entitást kezdettől fogva, érvényes állapotban példányosítani.

Nem ritka, hogy az osztályok implementációi olyan tulajdonságokkal rendelkeznek, amelyek például ellenőrzik, hogy a beállítani kívánt érték nem null-e, még akkor is, ha ugyanezen tulajdonságok alapértelmezett értéke a null. Mi itt a logika?

Lássunk egy másik példát egy vérszegény osztályra:

public class Customer { public string Name { get; private set; } public string Email { get; private set; } public DateTime BirthDate { get; private set; } public Customer(Guid id, string name, string email, DateTime birthDate) { Id = id; Name = name; Email = email; BirthDate = birthDate; } }

A fenti osztályban van egy tipikus “rekord” egy funkcionális megvalósításhoz. De egy objektumorientált nyelvben ez nem egy entitás.

Az ötletnek még egy tisztán funkcionális nyelvben is lenne értelme, ahol az “entitás” fogalmilag szét van szórva különböző, viselkedést meghatározó függvényekben, de a C#-ban ennek egyáltalán nincs értelme.

Kipróbáljunk egy második verziót az Employee osztályra:

public class Employee{ public string Id { get; private set; } public string Name { get; private set; } public string Cpf { get; private set; } public decimal Salary { get; private set; } public Employee(string name, string cpf) { //.. } public void RaiseSalary(decimal amount) { //.. }}

Ezúttal az entitás kevésbé vérszegény. Végül is nyilvánvalóak a motivációk, amelyek a tulajdonságok értékének megváltoztatását mozgatják. Vegyük észre, hogy még a tesztírás értéke is egyértelműbbé válik.

Mindenesetre még mindig vannak problémáink. A metódust “RaiseSalary”-nek neveztük el, azonban a domain szakértők nem így írják le ezt a műveletet. A tulajdonságértékek megváltoztatásának tényleges okait csak úgy határozhatjuk meg, ha beszélünk ezekkel a szakértőkkel.

Az elgondolkodtató…

A mindenütt jelenlévő nyelv meghatározása és implementálása nem csak az osztálynevek vagy tulajdonságok definiálására szolgál. Az ubikvitás nyelvét elsősorban az entitások állapotváltozásainak motivációiban kell explicit módon feltárni.

Az ubikvitás nyelvének megértése sokkal fontosabb, mint a szabványok megtanulása. A szakterület valódi ismerete nélkül a tervezési minták értéke nulla.

Először a legfontosabbak megtanulásával törődjünk. Szánjon időt és energiát arra, hogy jól megértse a tartományt, és kibetűzze annak ubiquitását. Akkor lehet, hogy még van értelme elgondolkodni azon, hogy a DDD-t fejlettebb technikai fogalmakkal társítsuk.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.