Limbajul omniprezent

Designul condus de domeniu (DDD) nu este un subiect nou (Eric Evans a formalizat conceptul cu peste un deceniu în urmă). Cu toate acestea, este curios cum, până astăzi, conceptele de bază pe această temă stârnesc interes, mai ales în comunitățile .NET. Și mai ciudat este modul în care aceleași concepte sunt interpretate greșit.

Fondamentul DDD constă în conceptul de limbaj omniprezent. Ea nu constă în determinarea a ceea ce este o entitate, un obiect de valoare, un agregat, un serviciu sau un depozit.

Impresia pe care o avem este că oricine începe să studieze DDD citește primele pagini ale cărții Evans sau ale cărții Vernon și sare rapid direct la paginile care descriu tiparele.

Deseori vorbim cu oameni din domeniul IT care cred că a avea un limbaj ubicuu definit înseamnă că numele claselor și proprietăților, scrise de programatori, se conformează vocabularului experților în domeniu. Totuși, aceasta este o simplificare grosolană.

Pentru a înțelege importanța limbajului ubicuu, să începem cu „entitatea” enumerată mai jos:

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

Iată un exemplu excelent de implementare anemică! Dar înainte de a citi mai departe, încercați să vă dați seama de ce.

În munca noastră de zi cu zi, când folosim acest exemplu, auzim sugestii că acestei clase îi lipsesc comportamentele (Ceea ce este corect!). Cu toate acestea, atunci când întrebăm care ar fi aceste „comportamente”, constatăm că oamenii repetă argumente generice (de la persoane care nici ele nu au „prins” ideea) și nu pot identifica ce este greșit!

Unul dintre cele mai frecvente argumente este că cei care stabilesc proprietăți ar trebui să fie privați. În locul lor, ar trebui să avem metode „DefineXXX” care să implementeze validările. Această idee nu are nici un sens, deoarece scopul setterilor este tocmai de a stabili valorile proprietăților și nu ar fi nici o problemă să se implementeze logica de validare în ele.

Metodele unei entități ar trebui să expliciteze motivațiile pentru schimbările de stare ale acesteia. De asemenea, trebuie să existe cel puțin un constructor capabil să instanțieze entitatea de la început, într-o stare validă.

Nu este neobișnuit să găsești implementări de clase cu proprietăți care verifică, de exemplu, dacă valoarea pe care încerci să o setezi este non-null, chiar și atunci când aceleași proprietăți au null ca valoare implicită. Care este logica aici?

Vezi un alt exemplu de clasă anemică:

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; } }

În clasa de mai sus, avem o „înregistrare” tipică pentru o implementare funcțională. Dar într-un limbaj orientat pe obiecte, aceasta nu este o entitate.

Ideea ar avea chiar sens într-un limbaj pur funcțional în care „entitatea” este răspândită conceptual în diverse funcții care definesc comportamentul, dar în C#, nu are niciun sens.

Să încercăm o a doua versiune pentru clasa Angajat:

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) { //.. }}

De data aceasta, entitatea este mai puțin anemică. La urma urmei, motivațiile care conduc la schimbarea valorii proprietăților sunt evidente. Observați cum chiar și valoarea scrierii testelor devine mai explicită.

În orice caz, încă avem probleme. Am numit metoda „RaiseSalary”, însă nu acesta este modul în care experții din domeniu descriu această operațiune. Singura modalitate de a defini motivele reale de modificare a valorilor proprietăților este de a discuta cu acești experți.

Să ne gândim la…

Identificarea și implementarea limbajului omniprezent nu este doar pentru a defini nume de clase sau proprietăți. Limbajul ubicuu trebuie să fie dezvăluit în principal în motivațiile pentru schimbările de stare ale entităților noastre în mod explicit.

Înțelegerea limbajului ubicuu este mult mai importantă decât învățarea standardelor. Fără o cunoaștere reală a domeniului, valoarea modelelor de proiectare este nulă.

Îngrijiți-vă mai întâi de învățarea celor mai importante. Acordați-vă timp și efort pentru a înțelege bine domeniul și pentru a preciza limbajul său ubicuu. Atunci s-ar putea chiar să aibă sens să vă gândiți să asociați DDD cu concepte tehnice mai avansate.

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.