Domeingestuurd ontwerp

In mijn land kom je niet door school zonder te lezen hoe Goethe's Faust klaagt, Ik heb nu filosofie gestudeerd - en jurisprudentie, medicijnen, - en zelfs, helaas! Theologie - Door en door met enthousiasme! - Hier sta ik nu, arme dwaas.

Helaas heeft geen van zijn inspanningen en studies de dokter geholpen om waar te nemen wat de wereld samenhoudt in zijn diepste plooien.

En hier zijn we in IT: we hebben talen en kaders, bibliotheken en zelfs - helaas - de IE! Door en door met enthousiasme. Maar hoe vaak hebben we ons geconcentreerd op alles wat de toepassing samenhoudt in zijn binnenste plooien? Het onderwerp van vandaag is het zakelijke domein.


Business Logic en Software Design

Bedrijfslogica wordt soms als uniek beschouwd en is per definitie! Als de bedrijfslogica van een toepassing niet uniek zou zijn, zou het niet nodig zijn om een ​​toepassing te schrijven, omdat er al een bestaande oplossing is (met uitzondering van wanneer een toepassing bestaat maar niet beschikbaar is). Vandaar dat veel ontwikkelaars zichzelf als pioniers zien, om dapper te gaan waar nog niemand is geweest. Romantici terzijde, terwijl de bedrijfslogica zelf misschien opmerkelijk genoeg uniek is, zijn de technieken om het te implementeren dat niet. Dat is de reden waarom slimme procesmodellen zoals Rational Unified Process of Scrum samen met technieken zoals iteratieve en incrementele ontwikkelingscycli werden uitgenodigd. Getalenteerde software-architecten hebben ook benaderingen voor softwareontwerp uitgewerkt; onder hen Eric Evans wie heeft de term bedacht Domain Driven Design in zijn boek met dezelfde titel.

Ontwikkelaars gaan dapper, waar geen enkele man eerder is geweest.

Ik zal een overzicht geven van de manier waarop Domain Driven Design het consultingproces kan beïnvloeden, evenals de basisconcepten voor het ontwerpen van een domeinmodel. Ten slotte zullen we de infrastructuurvereisten bespreken die nodig zijn om een ​​domein met gemak te implementeren.

Engineering Vereisten

Laten we zeggen dat u een software-architect bent op een niet-triviale toepassing met een niet-triviaal domein, zoals de kernmotor van een groot logistiek bedrijf. Veel mensen doen mee aan de planningbesprekingen, waaronder projectmanagers, accountmanagers, marketing, consultants enzovoort. Niet iedereen is nodig om de klus te klaren (ik deel mijn mening niet over wie dit van toepassing is), maar twee mensen zullen een cruciale rol spelen tijdens het proces van requirements engineering: u, de architect en de domeinexpert.

EEN software architect (althans in zakelijke context) moet een zeer goed abstract begrip hebben over hoe processen werken, hoe ze zijn ontworpen en geoptimaliseerd.

Dat klopt, want zakelijke applicaties gaan vooral over het ontwerpen van efficiënte en mooie digitale equivalenten van bedrijfsprocessen. EEN domeinexpert moet een grondige kennis hebben van een specifieke reeks processen, namelijk de processen die plaatsvinden in het logistieke bedrijf en die door de toepassing moeten worden weerspiegeld. Ik ontdekte dat bedrijfsadviseurs, salesmanager en marketingexperts onderweg een aantal goede en waardevolle punten verdienen, maar zolang je geen iemand in het team hebt die zijn handen vuil heeft gemaakt in jarenlange ervaring, zal het project falen. Uw domeinexpert zou bijvoorbeeld de breedte van de laadhelling bij het depot moeten weten en als er voldoende ruimte is om een ​​barcodescanner te installeren.

Dus jij bent het, gespecialiseerd in digitale bedrijfsprocessen, softwareontwerp en [vul hier je favoriete tools in], en een expert op het gebied van logistiek met kennis van de klanten van het bedrijf, medewerkers en de dagelijkse routine. De kans is groot, dat je op verschillende manieren zult praten. Domain Driven Design suggereert enkele strategieën die een krachtige technische consultingservice kunnen vormen. Hier is die van mij:

  • Maak een ubiquitos-taal
  • Bouw een woordenlijst met zoekwoorden
  • Verschuiving van een procesgeoriënteerde weergave naar een domeingerichte benadering.
  • Bouw een visueel model als de basis van uw bedrijfslogica.

Dat klinkt leuk! Laten we naar de details duiken.

In elke branche heeft elke groep experts zijn eigen terminologie. Het is verfijnd in elk bedrijf en verrijkt met de speciale voorwaarden en productnamen van bedrijven. Denk aan het: wanneer mensen zoals wij elkaar ontmoeten voor een serieuze nerdpraat, wie zullen dan nog meer een woord verstaan? Hetzelfde geldt voor uw domein en het eerste wat u moet doen is een reeks termen definiëren. Doorloop de hele reeks processen die de software moet weerspiegelen en luister aandachtig hoe de domeinexpert dit beschrijft. Eventuele domeinspecifieke voorwaarden moeten op een zodanige manier worden gedefinieerd dat woordenboeken dat doen. Je moet je bewust zijn van woorden die bekend voorkomen maar niet in de gegeven context voorkomen. Sommige bedrijven hebben dat werk nog nooit gedaan, ook al is het waardevol voor andere gebieden.

Maak een speciale verklarende woordenlijst van uw alomtegenwoordige voorwaarden, zorg ervoor dat deze wordt goedgekeurd door de klant en vraag om het raadplegingsproces! Een woordenlijst kan er als volgt uitzien:

Een uittreksel uit een woordenlijst.

Merk op hoe een goed gedefinieerde woordenlijst de afhankelijkheden en associaties al bepaalt. Zoals de bestellen, dat hosts meerdere items. Je zult zeker lessen hebben voor degenen in je bedrijfslogica! Jouw Bestellen klasse zal vermoedelijk een methode hebben zoals getItems (). Zonder rekening te houden met programmeertechnieken, kan een woordenlijst de basis vormen voor uw domeinmodel! Daarnaast bouw je een taal die door het hele project wordt gebruikt: in mails, in vergaderingen en zeker in code! Uw code moet het domein weerspiegelen; daarom moet het in de woordenlijst worden gedefinieerd. Hier is een vuistregel: wanneer u een klasse maakt die niet is genoemd naar een item in uw woordenlijst, is uw alomtegenwoordige taal mogelijk nog niet voldoende gedefinieerd!

Onder de dekmantel van duisternis hebben we de visie op de vereisten verlegd! Normaal gesproken beschrijft een klant wat de te schrijven software zou moeten doen. Een typische beschrijving kan zijn: "We hebben een manier nodig om notities aan een klant toe te voegen en deze uit te printen." Dit is een goed uitgangspunt, maar het is niet gericht op het zakelijke domein. Het introduceert een soort gebruikersinterface, printfunctionaliteit en zelfs meer. Je hebt dat zeker nodig in je applicatie, maar het maakt geen deel uit van het domein. Domain Driven Design richt zich op het modelleren van het ware doel van een applicatie: het bedrijfsdomein.

Al het andere zou daaruit moeten voortvloeien, als het domein klaar is. De omschakeling is het volgende: implementeer geen processen en bouw een puur domein dat de behoeften van de klant in objecten weerspiegelt. Een manier om de beschrijving van de bovenste klant te visualiseren, zou er als volgt uitzien (getters en setters worden alleen toegevoegd, indien nodig voor het begrip):

Een eenvoudig diagram dat het vereiste domein weergeeft.

Nu hebben we een reeks klassen en associaties die niets anders doen dan de definities uit onze woordenlijst weerspiegelen. Is dit model in staat om de benodigde taken uit te voeren? Zeker! Je hebt een Printerservice en een gebruikersinterface ergens in uw app, maar ze moeten gewoon wat gegevens uit het domein halen. Ze zijn op dit moment niet nodig en de implementatie ervan zal niet bepalend zijn voor de uitkomst.

De filosofie van DDD is gebaseerd op de aanname dat een zorgvuldig ontworpen domeinalaag alle benodigde processen gemakkelijk kan uitvoeren. Een domeinmodel is schaalbaar, omdat het niet is gebouwd om aan een bepaalde taak te voldoen, het is gebouwd om een ​​bedrijfsconcept weer te geven. Het is uitwisselbaar, omdat het niet gebonden is aan specifieke software, zelfs niet aan een gebruikersinterface. Je kunt hetzelfde model gebruiken in de barcodescanner op de laadhelling van het depot! Zoals we in het volgende hoofdstuk zullen zien, is het niet eens gebonden aan andere componenten die uw applicatie bouwen.


Het domeinmodel

In een van mijn recente artikelen schreef ik over het toepassen van het KISS-principe.

In een van mijn recente artikelen schreef ik over het toepassen van het KISS-principe: de meeste systemen werken het beste als ze eenvoudig gehouden worden in plaats van complex gemaakt. Welnu, als het gaat om het implementeren van een domein op basis van de filosofie van DDD, kun je een nogal radicale benadering tegenkomen in de moderne wereld van kaders, patronen en disciplines; zoals, implementeer een gewoon object in alleen de duidelijke taal van uw keuze. Geen raamwerkafhankelijkheden, geen bibliotheekconventies, geen sporen van een API, geen mooie namen. Gewoon een gewoon oud object (aangezien een concept niet serieus wordt genomen zonder een fancy naam in de wereld van Java, kregen ze er een).

Entiteiten versus waardeobjecten

Wanneer we het domeinmodel willen weergeven, is een cruciaal punt om de staat te definiëren. Bij objectgeoriënteerd programmeren wordt de toestand van een object bepaald door de staat van zijn eigenschappen. Evenzo wordt de status van het domeinmodel bepaald door de staat van zijn objecten. Daarom moeten we een manier hebben om de staat van objecten duidelijk te definiëren. Als we dat niet zouden kunnen doen, zouden we falen bij eenvoudig gebruik, zoals "Hoeveel bestellingen zijn er?" Omdat het antwoord altijd kennis vereist over de staat van alles Bestellen objecten in een domein en een manier om ze te identificeren en te onderscheiden. DDD definieert twee soorten objecten: entiteiten en waardeobjecten.

Een entiteit is een bekend concept, als u bekend bent met relationele databases.

Tabellen in een relationele database hebben meestal een unieke ID die de ene rij van de andere onderscheidt. Hetzelfde geldt voor entiteiten. Een entiteit moet een duidelijke ID hebben die uniek is in het gehele systeem. Voor een bestelling kan dit een eigenschap zijn van het type uint, genaamd bestellingsnummer. Natuurlijk zou je in je woordenlijst kijken, waar de juiste term zou moeten worden gedefinieerd.

Een entiteit blijft hetzelfde wanneer sommige eigenschappen veranderen. U kunt bijvoorbeeld items uit een order toevoegen of verwijderen, maar het zou dezelfde volgorde zijn. Wat gebeurt er, wanneer je de bestellingsnummer? Welnu, vanuit de POV van uw domein wordt één bestelling verwijderd terwijl een andere wordt gemaakt.

EEN waarde object is een eenvoudige container voor informatie. Het is onveranderlijk zodra het is gemaakt. Als u één eigenschap wijzigt, betekent dit dat u het waardeobject zou wijzigen. Een waardeobject wordt gedefinieerd door alle eigenschappen; het heeft geen unieke identificatie nodig. Het hele object is er een. Een voorbeeld van een waardeobject zou een zijn OrderAddress, zoals het wordt gedefinieerd door de naam, het adres en de stad van de ontvanger. Als u één eigenschap, bijvoorbeeld de stad, zou wijzigen, zou het OrderAddress volledig veranderen.

Als u een eigenschap van een kleur wijzigt, is dit een andere.

Het verdelen van objecten in waardeobjecten en entiteiten is belangrijk om de status van uw domein te bepalen - omdat dit het grondwerk is om componenten te identificeren. Maar het is net zo belangrijk om ze te definiëren om een ​​schaalbaar, onderhoudbaar domein te hebben. Entiteiten zijn de weergave van objecten uit de echte wereld zoals personen, bestellingen of items. Value Objects zijn containers voor informatie zoals kleuren of adressen en ze zijn herbruikbaar en kunnen worden gedeeld tussen entiteiten of zelfs uw volledige systeem. Het definiëren hiervan kan enige oefening vereisen, aangezien het afhankelijk is van de use case of u een waardeobject of een entiteit heeft.

Verenigingen, aggregaten en repositories

Wanneer we terugblikken op de samenvatting van onze woordenlijst, kunnen we verbindingen en afhankelijkheden tussen onze objecten in de domeinalaag zien. In DDD wordt dit genoemd verenigingen en het is het model van interacties dat plaatsvindt.

Items maken bijvoorbeeld deel uit van de bestelling. Als we zouden verwerken tegen een relationele database, zou dit een één-op-veel relatie zijn (of 1: n). Als elke bestelling exact één OrderAddress zou hebben, zou het een één-op-één relatie zijn. Omdat we ons niet druk maken om relationele databases en alleen geïnteresseerd zijn in het voltooien van het domein, kan de relatie eenvoudig worden uitgedrukt met behulp van twee methoden in de klasse Order: getItems () en getOrderAddress (). Merk op dat de eerste meervoud is (omdat er veel items zijn) en de tweede enkelvoudig is. Als je een veel-op-veel-relatie hebt, zou je beide klassen een gettermethode geven. Natuurlijk heb je ook setters nodig - ik heb ze weggelaten om de voorbeelden lichtgewicht te houden.

Artikelen en het besteladres kunnen als kinderen van de bestelling worden gezien.

Bij DDD proberen we veel-op-veel relaties te vermijden, omdat deze de neiging hebben om complexiteit aan het domein toe te voegen. Technisch gezien betekent dit dat twee objecten tijdens hun levenscyclus gesynchroniseerd moeten worden en dat het synchroon houden van de objecten kan leiden tot schending van het DRY-principe. Daarom moet het modelverfijningsproces streven naar eenvoud. In veel tijden is een associatie sterker in de ene richting dan in de andere, en het is een goed idee om de structuur opnieuw in te delen in een een-op-veel-relatie. Controleer of de koppeling relevant is voor de bedrijfslogica van uw toepassing. Als het zich voordoet in niet-essentiële en zeldzame gevallen, wilt u misschien op zoek naar een andere manier om de benodigde informatie te ontvangen.

Associaties bouwen een boom van objecten en je zou eindigen met een associatieconstruct waarbij elk object kan worden teruggevonden via gettermethoden. Dit is een ouder-kindconstructie die uiteindelijk naar één wortelobject leidt. Dit heet aggregatie in DDD. Een goed ontwerp leidt uiteindelijk tot één aggregaat dat in staat is om het hele domein te weerspiegelen. Op dit moment hebben we slechts een klein deel van onze woordenlijst bekeken, maar het lijkt erop dat een klant ons wortelaggregaat is:

Het clientobject is het bovenliggende element van alle domeindelen.

Aggregaten zijn een belangrijk onderdeel, omdat DDD het domein probeert te isoleren van de omliggende applicatie. Als we informatie over een klant willen hebben, vragen we om een ​​basisaggregaat en kunnen we via zijn kinderen informatie vinden via een duidelijke interface van gasbinders en setters.

DDD is als verkoop, het biedt één gezicht voor de klant, het aggregaat voor het omliggende systeem. Daarom geeft het toegang tot een gestructureerde set van processen relevante informatie en methoden; bijvoorbeeld de bestelling.

Domain Driven Design is als verkoop, het biedt één gezicht aan de klant.

De omringende applicatie heeft toegang tot een aggregaat via repository's, die in feite een soort gevel zijn. Met andere woorden: een domeinobject is een aggregaat als het een repository heeft. Repositories bieden methoden voor het opvragen van aggregaten. Voorbeelden kunnen zijn findClientByEmail (string email) of gewoon vind alle(). Ze zijn net zo goed updates aan het uitvoeren en voegen nieuwe objecten toe aan het domein. Dus hebben ze waarschijnlijk methoden zoals toevoegen (Client newClient) of delete (Client toBeDeletedClient).

Met een verzamelobject hebt u alleen toegang tot kinderen via het bovenliggende element. Een klantaggregaat geeft u bijvoorbeeld toegang tot alle bestellingen van de klant. Maar als u vanuit een ander perspectief dan de klant toegang tot de gegevens nodig heeft, kunt u een tweede aggregaat instellen. Stel dat u een lijst met alle bestellingen wilt hebben, ongeacht bij welke klant ze zijn geplaatst. Een orderrepository zal de klus klaren!

De domeinalaag en zijn opslagplaatsen.

Omdat de repository het toegangspunt is voor de omringende applicatie naar de domeinlaag, is dit waar andere spelers het gebied betreden. Bedenk dat we voor nu te maken hebben met eenvoudige objecten.

Heb je jezelf afgevraagd hoe dit echt zal worden? Dit is waar de infrastructuur binnenkomt. DDD is een uitstekende partner voor frameworks, omdat het is gebouwd op eenvoudige objecten, met een eenvoudig schema van waardeobjecten, entiteiten en aggregaten. Omdat eenvoud echter de macht is in IT, zijn we nu in de positie om het volledige infrastructuurgedeelte uit te besteden. Laten we een kijkje nemen onder de motorkap en hoe DDD kan worden verspreid over een toepassing.


Infrastructuur en de domeinalaag

Het is je misschien al opgevallen dat onze focus op het domein een persistentielaag heeft uitgesloten evenals veelvoorkomende zaken zoals weergaven of controllers uit onze takenlijst. De hele applicatie kan bestaan ​​uit veel complexere dingen dan alleen maar objecten, en ik wil een paar stappen aangeven die moeten worden gedaan om het domein en de app samen te brengen, en welke implementatiestrategieën er bestaan. Ik zal een aantal voorbeelden maken op basis van FLOW3, een applicatieframework met de focus op het aanbieden van DDD-infrastructuur. Het is niet nodig, maar het doet geen pijn als je mijn introductie leest. Om het bedrijfsdomein toe te passen op een toepassing, zijn de volgende stappen gebruikelijk:

  • Implementeren van een persistentielaag die onze domeinobjecten bewaart - bijv. een MySQL-database.
  • Een repository bouwen die de toegang tot de relationele database abstraheert en een eenvoudige interface biedt voor query's.
  • Bouw een fabrieksservice die de objecten genereert en de verzamelstructuur bouwt.
  • Zorg voor een service-infrastructuur om relevante logica te introduceren die geen domein is.
  • Applicatie domeinbewust maken.

Wanneer u de opmerkingen over het artikel bekijkt naar Aspect Oriented Programming (AOP), zult u een interessante discussie zien over het al dan niet toevoegen van een kader via commentaarannotaties. De aanpak in FLOW3 is gebaseerd op hoe Domain Driven Design is geïmplementeerd. Bekijk deze code:

/ ** * Een klant * * @ FLOW3 \ Scope ("prototype") * @ FLOW3 \ Entity * / class Client / ** * De naam van de klant. * * @ FLOW3 \ Validate (type = "Text") * @ FLOW3 \ Validate (type = "StringLength", options = "minimum" = 1, "maximum" = 80) * @ORM \ Column (lengte = 80 ) * @var string * / beschermde $ naam; / ** * Haal de naam van de klant op * * @return string De naam van de klant * / public function getName () return $ this-> Name;  / ** * Stelt de naam van deze klant in * * @param string $ Name De naam van de klant * @return void * / public function setName ($ name) $ this-> name = $ name; 

Dit is een heel eenvoudige klasse en het bevat niet veel bedrijfslogica, maar dit zal waarschijnlijk veranderen zodra de applicatie groeit. FLOW3 is aanwezig via een aantal codeaantekeningen. Het definieert de klasse als een entiteit en voegt een aantal validatieregels toe die moeten worden toegepast (dit is optioneel). Merk op dat er een annotatie met de naam is @ORM \ kolom (lengte = 80). Dit is een informatie voor de persistentielaag en we komen hier zo dadelijk op terug.

FLOW3 gebruikt hier annotaties om het domein schoon te houden. Je bent vrij om de klas ergens anders te gebruiken, omdat het nog steeds een eenvoudig object is. U kunt ervoor kiezen om over te schakelen naar de symfony kader, dat dezelfde persistentielaag (Doctrine) gebruikt, vandaar dat de code bijna uit de doos zou werken. Door de framework-configuratie buiten het bereik van de PHP-interpreter te duwen, blijft het domein een eenvoudig oud PHP-object. Je kunt het zelfs zonder enig kader opnieuw gebruiken.

Maar nu het framework op de hoogte is van het object, kan het nu de vereisten voor een MySQL-databasetabel berekenen. Om instanties van de klassenclient op te slaan, zou FLOW3 (en Doctrine als persistentiekader) de volgende stappen voor u uitvoeren:

  • Maak een tabel met de naam cliënt.
  • Voeg een kolom toe met de naam naam van het type string met de lengte van 80 tekens
  • Omdat we geen unieke ID hebben verstrekt (die vereist is voor entiteiten), zou FLOW3 vriendelijk een voor ons genereren en er een tabelcel voor toevoegen.

De eigenschapsdefinitie voor de artikelen in onze bestelling kan er als volgt uitzien:

/** * De artikelen. * * @ORM \ OneToMany (mappedBy = "order") * @ORM \ OrderBy ("price" = "ASC") * @var \ Doctrine \ Common \ Collections \ Collection<\LogisticApp\Domain\Model\Item> * / beschermde $ items;

Merk op dat dit een Doctrine Collection retourneert, wat een soort wrapping is voor een array, zoals ArrayLists in Java. In essentie betekent dit dat alle elementen van het gegeven type moeten zijn, in dit geval Item. Ik heb ervoor gekozen om een ​​orderinstructie toe te voegen over hoe ik wil dat de verzameling wordt georganiseerd (op basis van de prijzen van de artikelen).

De tegenpartij in de klasse Item zou kunnen zijn:

/** * De bestelling. * * @ORM \ ManyToOne (inversedBy = "items") * @var \ LogisticApp \ Domain \ Model \ Order * / protected $ order;

Het is slechts het topje van een ijsberg, maar het moet u een idee geven van hoe dingen kunnen worden geautomatiseerd: Doctrine biedt een krachtige strategie voor het toewijzen van koppelingen aan de tabellen waarin het object wordt opgeslagen. Omdat de items bijvoorbeeld zouden vertalen naar een één-op-veel relatie (één bestelling kan veel items bevatten) in de database, zou Doctrine een vreemde sleutel voor de bestelling in de itemtabel toevoegen. Als je besluit een repository voor het item toe te voegen (waardoor het een aggregaat wordt), kun je magisch toegang krijgen tot a findByOrder (bestelbon) methode. Dat is de reden waarom we ons niet druk maakten om databases of doorzettingsvermogen tijdens het maken van een domein - het is iets dat een framework kan regelen.

In het geval dat u nog niet bekend bent met persistentiekaders, wordt de manier om objecten aan een relationele database toe te wijzen ORM genoemd (Object-Relational-Mapping). Het heeft een aantal prestatienadelen, die voornamelijk worden veroorzaakt door de verschillende benaderingen die relationele databases en het objectmodel hebben. Er zijn lange discussies over. In moderne CRUD-apps (niet alleen domeingestuurd) is ORM echter de beste keuze, vooral vanwege redenen van onderhoud en uitbreiding. U moet echter uw ORM kennen en goed begrijpen hoe dit werkt. Denk niet dat je niet langer kennis over databases meer nodig hebt!

Zoals je misschien hebt gemerkt, kunnen je objecten stil complex zijn en een lange transversale lijn hebben als ze veel kinderen hebben, die op hun beurt weer veel eigen kinderen hebben.

Wanneer de repository gegevens uit een database ophaalt, moeten ze dus op een intelligente manier naar objecten worden getransformeerd. Omdat we nu een persistentielaag hebben, is transformatie veel complexer dan alleen het instantiëren van een object. We moeten de traversalijn beheren door de relevante oproepen naar de database tot een minimum te beperken. Niet alle kinderen zijn altijd nodig, dus ze kunnen op afroep worden opgehaald.

Sommige objecten zijn waardevoorwerpen die maar één keer hoeven te worden gemaakt, waardoor u veel geheugen kunt besparen. Daarom heeft elke domeinalaag een slimme fabriek nodig die de objecten voor u genereert. Vandaar dat in moderne kaders de nieuwe operator wordt veel te laag geacht voor moderne toepassingen. FLOW3 gaat een lange weg om de mogelijkheid te bieden om objecten te instantiëren met de nieuwe zoekwoord, maar de achtergrondcompilatie zorgt voor een automatische wijziging van het maken van eenvoudige objecten in krachtig objectbeheer. Sommige functies die uw objectbeheerder / fabriek moet kunnen zijn, ongeacht het framework dat u gebruikt, zijn:

  • Beheren van entiteiten en waardeobjecten
  • Een intelligente manier om kinderen van objecten op afroep te voorzien
  • Injecteer afhankelijkheden en diensten

Je hebt mogelijk de laatste zin gefronst. In het hele artikel heb ik de nadruk gelegd op het gebruik van eenvoudige objecten in het domein en ik heb zelfs het paradigma 'niet herhalen' gemeden en het meerdere keren genoemd omdat het zo belangrijk is voor DDD. En nu vertel ik u dat u afhankelijkheden en services hebt die deel moeten uitmaken van uw domein ...

Er is een trieste waarheid in de echte wereld: er is niet zoiets als een puur domein. Je zult bijna nooit een klant tegenkomen die helemaal opnieuw begint; dus je moet voldoen aan omstandigheden zoals legacy-systemen. Ze kunnen een vreselijke implementatie hebben, maar het bedrijf kan er niet vanaf komen. Mogelijk moet u services en API's bellen en gegevens ophalen van verschillende externe partijen, en deze oude systemen beïnvloeden het bedrijfsdomein.

Alles wat we tot nu toe hebben besproken, is belangrijk, maar de vraag hoe een framework de afhankelijkheid van niet-domeinservices oplost, is van cruciaal belang voor een schoon Domain Driven Design. Dat is de reden waarom het FLOW3-team enorme inspanningen heeft geleverd voor de implementatie van aspectoriëntatie; het is een manier om services aan het domein te introduceren zonder de code aan te raken zonder inbreuk te maken op de regel van gewone oude objecten. Er zijn andere benaderingen, zoals het verschuiven van de afhankelijkheden tussen services en het domein naar de controller, maar aspectgericht programmeren is veruit de elegantste manier die ik ken. Ik zou graag uw mening horen over dit onderwerp!

Een goed kader kan u veel steun geven naast de punten die ik noemde. FLOW3 geeft bijvoorbeeld de domeinobjecten transparant door in de weergave met de opmerkelijk koele vormgevende engine, Fluid genaamd. Vloeiende sjablonen schrijven, als het domein klaar is, is net zo ontspannend als een dag op het strand.


Samenvatting

Dit artikel is slechts een inleiding tot Domain Driven Design. Ik heb enkele van de kernbegrippen gepresenteerd, maar ik moet toegeven dat het misschien moeilijk is om de theorie alleen te begrijpen. Ik wil u aanmoedigen om Domain Driven Design voor uw eigen te proberen in een echt wereldproject. U zult ervaren dat de domeinconcepten zeer intuïtief te gebruiken zijn.

Ik ben als een vis uit het water gegooid in een zeer groot extbase-project, zonder al te veel kennis van de concepten (extbase is een Domain Driven Design-framework voor het bouwen van extensies voor de CMS Typo3 en is gebaseerd op FLOW3). Het heeft mijn kijk op het denken over softwareontwerp verbreed en ik hoop dat het ook de uwe zal verbreiden.