Breng duidelijkheid in uw monoliet met begrensde contexten
bekijk de video van deze talk van ElixirConf 2017 hieronder
monolithische toepassingen zijn geweldig wanneer u begint met het opbouwen van uw bedrijf, maar naarmate de tijd vordert, worden ze moeilijk te onderhouden. Deze codebases, als ze groeien, gemakkelijk worden grote ballen van modder.
bij het bouwen van grote toepassingen in frameworks zoals Rails, beginnen juist de Conventie-over-configuratie ontwerpprincipes die Rails zo ‘ n plezier maakten om te gebruiken, in de weg te zitten wanneer de toepassing groeit in omvang. Het kan zijn dat u dezelfde pijn ervaart als:
- Refactoring is moeilijk en vervelend, omdat methoden en klassen afhankelijk zijn van te veel andere klassen
- u heeft een steeds groeiende lijst van zakelijke objecten die moeilijk in uw hoofd te houden zijn. In feite lijkt niemand in staat om het systeem te begrijpen als een samenhangend geheel
- het veranderen van code in een gebied van de code leidt tot onverwachte en onbedoelde bijwerkingen in andere gebieden van de code, omdat het gemakkelijk is om wereldwijde Diensten en objecten
aan te roepen in onze laatste chat samen hebben we het ontwikkelen van een alomtegenwoordige taal besproken samen met de business experts en uw ontwikkelingsteam om uw team te helpen nauwer samen te werken. Vandaag gaan we daarop voortbouwen met de introductie van nieuwe Domain-Driven Design (DDD) tools. Vervolgens introduceren we een nieuwe mapstructuur voor uw Rails-apps, waarmee we ze voorbereiden op een toekomst waarin uw applicatie minder gekoppeld en samenhangender is. Laten we beginnen!
- Let ‘ s talk domains
- begrensde contexten in de oplossingsruimte
- het grote idee: organiseer Rails code in modules per business subdomein
- mapstructuren omkeren naar een platte domeingeoriënteerde groepering
- Modulize classes
- reference associated models by full class name
- houd controllers up-to-date over waar ze hun nieuw gemoduleerde weergaven kunnen vinden
- wat werkt goed met deze aanpak?
- wat hebben we geleerd?
Let ‘ s talk domains
een belangrijk principe in DDD is dat de software die u bouwt nauw moet aansluiten bij het (bedrijfs) domein van de organisatie die het bouwt. Dus, we moeten wat huiswerk te doen om het zakelijke domein van uw software te begrijpen.
een domein is wat het bedrijf doet, en de context van hoe het het doet.
laten we ons DeLorean voorbeeld van de vorige post opnieuw bekijken. Hierin wordt het bedrijf op de markt gebracht als Uber voor tijdreizen. Dus, zijn “domein” (het “wat het doet”) is tijd-reizen Ritesharing. Ook inbegrepen in het domein is het “hoe” van hoe het doet het – door samen te werken chauffeurs die tijd reizen Delorean Voertuigen met passagiers die willen tijd reizen reizen.
om meer nuances in het zakelijke domein te krijgen, introduceert DDD een ander concept, het subdomein genaamd:
een subdomein vertegenwoordigt de kleinere groepen of eenheden van het bedrijf die in de dag-tot-dag samenwerken om de doelstellingen van het bedrijf te bereiken.
Delorean is verdeeld in verschillende teams binnen het bedrijf. Laten we eens kijken naar twee van hen, en zien waar ze verantwoordelijk voor zijn:
Reis Platform team | Finance Operations team | |
---|---|---|
Missie | Ontwerp en de ondersteuning van de systemen die route reizen en connect stuurprogramma ‘ s voor passagiers | het Beheren van de systemen die betrekking hebben op financiële instellingen en credit card processors |
Verantwoordelijkheden |
|
|
elk van deze twee groepen animeren een zakelijke verantwoordelijkheid, of subdomein. Laten we ze respectievelijk Ridesharing Experience en E-Commerce noemen.
nu hebben we een algemene illustratie van het bedrijf en twee van zijn eenheden die het helpen functioneren in de dag-tot-dag. Het domein en subdomein zijn manieren om de probleemruimte van uw bedrijf te modelleren – en hoe het werkt om deze rollen te vervullen. De kans is groot, uw bedrijf org grafiek zal nauw overeenkomen met de subdomeinen van uw bedrijf. In de echte wereld kunnen de omschrijvingen minder duidelijk zijn – teams kunnen verantwoordelijk zijn voor meerdere, overlappende subdomeinen.
laten we dit diagram invullen met een paar subdomeinen in de DeLorean business:
- Customer Support subdomein: het oplossen van klantenservicetickets die binnenkomen via e-mail
- Marketing subdomein: beheer van marketing-e-mailcampagnes en marketingcouponcodes
- identiteit subdomein: hoe het systeem elke gebruiker en zijn/haar identificatiegegevens traceert
begrensde contexten in de oplossingsruimte
dit diagram voor ons weerspiegelt nu de bedrijfsdoelstellingen van het bedrijf, verdeeld in logische eenheden die (hopelijk) zijn doelen in de echte wereld bereiken. Nu gaan we de software systemen die deze doelen te bereiken over dit diagram. Deze software systemen worden beschreven als begrensde contexten:
een begrensde Context is een systeem dat de doelen van het bedrijf in de echte wereld vervult.
al onze software systemen (zoals een web service of web app) die als concrete instanties in de echte wereld werken, worden beschouwd als begrensde contexten.
technisch gesproken is de begrensde Context in DDD-speak een specifieke grens binnen uw domein die uw woordenlijst vanuit uw alomtegenwoordige taal alleen kan toepassen – het idee is dat verschillende subdomeinen concurrerende of tegenstrijdige definities van termen kunnen hebben. Dit bericht zal niet ingaan op de taalkundige nuances van de begrensde Context. Voor meer informatie, zie Martin Fowler ‘ s uitleg over begrensde contexten.
nu gebeurt het dat bij Delorean al deze subdomeinen worden geà mplementeerd in één systeem – één grote bal Modderrails monoliet. We tekenen een blue box rond de subdomeinen waarvan de functies worden geïmplementeerd door het software systeem. In dit geval beginnen we met onze eerder genoemde Rails monoliet.:
omdat het de monoliet is, doet het in principe alles – en dus eet het hier alle andere subdomeinen in het diagram op.
laten we niet vergeten – we hebben een paar andere software systemen die we hier niet hebben gemodelleerd. Hoe zit het met alle mooie derden integraties die het bedrijf gebruikt? Dit zijn ook software systemen. We tekenen ze als blauwe dozen.
trouwens-wat we hier hebben getekend is een Context Map – een diagram dat zakelijke doelstellingen en concrete implementaties van software systemen combineert. Het is handig voor het beoordelen van de lay van het land van uw software systemen en het visualiseren van afhankelijkheden tussen teams.
nu, dit is redelijk en schoon, maar we leven in de echte wereld, en echte wereld software komt zelden uit op zoek consistent en coherent. Als u uw Rails app gebouwd volgens de out-of-the-box conventies, uw app intern mist de groeperingen die nodig zijn om uw app visualiseren in de samenstellende componenten. In werkelijkheid ziet de DeLorean codebase er ongeveer zo uit:
het punt is – Rails legt geen organisatorische beperkingen op onze software systemen – wat betekent dat logische business units (onze subdomeinen) die ontkoppelde interfaces suggereren – niet worden gematerialiseerd in de code, wat leidt tot verwarring en toenemende complexiteit in de loop der jaren.
het grote idee: organiseer Rails code in modules per business subdomein
hoewel uw Ruby klassen in uw applicatie waarschijnlijk in de Globale naamruimte leven, kunnen ze gemakkelijk worden geplukt in modules. Ons doel is om logische groepen van domeincode te creëren die kunnen worden geà soleerd in zelfstandige componenten.
inderdaad, een van de doelen van Domein-gedreven ontwerpen is om een een-op-een afbeelding van een subdomein naar een begrensde Context te hebben.
OK, wat betekent dit? Laten we in een aantal aanbevelingen, samen met voorbeelden.
mapstructuren omkeren naar een platte domeingeoriënteerde groepering
u herinnert zich misschien dat het volgen van Rails-conventies ons leidt tot maphiërarchieën die klassen groeperen op rollen:
laten we alles verplaatsen naar een nieuwe mapstructuur: laten we groeperen zoals functionaliteit per domein, in plaats daarvan. We beginnen met een eerste variant, die ik een platte domein-georiënteerde groepering noem.
Modulize classes
vervolgens wilt u de classes moduliseren van wat ze voorheen waren. Omdat de Driver class Onder het Ridesharing domein valt, zullen we het toevoegen aan een Ridesharing module:
je wilt dit doen voor elke klasse die je verplaatst naar de app/domains
platte directory structuur.
reference associated models by full class name
daarnaast moet u uw ActiveRecord model associaties wijzigen om naar de class te verwijzen door het volledige, gemoduleerde pad:
houd controllers up-to-date over waar ze hun nieuw gemoduleerde weergaven kunnen vinden
u moet ook dit kleine bit invoegen om routes van de controller te laten weten waar ze de weergaven moeten zoeken:
hier is het coole: u hoeft niet te verplaatsen al je code tegelijk. U kunt een klein domein kiezen in uw applicatie, het meest volwassen gebied van uw code of het gebied dat u het beste begrijpt rond, en beginnen met het verplaatsen van de zorgen in een enkele domeinmap, allemaal terwijl de bestaande code in rust totdat het klaar is om te verplaatsen.
nu hebben we enkele kleine stappen gezet om architecturale helderheid te bereiken in onze toepassing. Als we nu kijken, hebben onze modulaire mapstructuren ons geholpen onze code zo te groeperen:
onder de motorkap ziet onze app er misschien meer als volgt uit:
wat werkt goed met deze aanpak?
- er is minder ruis in elke bestandsmap – door bestanden te groeperen op domeinspecificiteit, vinden we een natuurlijk organisatorisch punt
- de entiteiten die in elke domeinmap blijven, zijn zeer samenhangend-ze hebben waarschijnlijk de neiging om met elkaar te communiceren en verschijnen op natuurlijke wijze met elkaar
- entiteiten die niet bij elkaar horen zijn nu gescheiden (losser gekoppeld)
- als u engineeringteams hebt die werken langs subdomein – verantwoordelijkheden, kunnen deze engineers nu in een meer gestroomlijnde, geïsoleerde mode. Losser koppeling stelt deze teams in staat om wijzigingen aan te brengen met het vertrouwen dat ze geen regressies zullen introduceren of conflicten zullen samenvoegen terug naar de codebase
- de fase is nu ingesteld op de lange termijn om te beginnen met het verplaatsen van elk van deze domeinmappen in een onafhankelijke software service (meer daarover in een toekomstige blog post)
Als u meer informatie wilt over deze mapstructuur, heb ik een voorbeeldapp ontwikkeld die deze domein-georiënteerde mapstructuur vertoont: http://github.com/andrewhao/delorean. Neem een kijkje en laat me weten wat je ervan vindt.
wat hebben we geleerd?
in onze tijd samen leerden we over domein-gedreven ontwerpconcepten rond domeinen en subdomeinen. We leerden hoe we onze softwaresystemen konden visualiseren als begrensde contexten op een Contextkaart, die ons de gebieden van het systeem liet zien die bij elkaar horen als coherente onderdelen.
eindigend op een praktische Noot, we geïllustreerd hoe Rails bestanden en mappen kunnen worden “omgekeerd” en opnieuw bedacht als domein-eerste groepen.
in mijn volgende post, zullen we onze discussie voortzetten in een komende blog post over hoe we onze domein-georiënteerde Rails code verder kunnen ontkoppelen met domeingebeurtenissen, en uiteindelijk onze weg vinden naar het land van microservices.