Directe afhankelijkheden vervangen door messaging
Soms hoeft een module alleen anderen te informeren dat er gebeurtenissen/wijzigingen in zijn opgetreden, en het maakt niet uit wat er later met deze informatie gebeurt.
In dit geval hoeven de modules helemaal niet "van elkaar af te weten", dat wil zeggen directe links te bevatten en direct te communiceren, maar het is voldoende om alleen berichten (berichten) of gebeurtenissen (gebeurtenissen) uit te wisselen.
Soms lijkt het erop dat modulecommunicatie via berichten veel zwakker is dan directe afhankelijkheid. Omdat de methoden niet worden aangeroepen, is er inderdaad geen informatie over de klassen. Maar dit is niets meer dan een illusie.
In plaats van methodenamen begint logica te worden gekoppeld aan berichttypen, hun parameters en verzonden gegevens. De connectiviteit van dergelijke modules is besmeurd.
Vroeger was het zo van: we noemen methoden - er is connectiviteit, we noemen geen methoden - er is geen connectiviteit. Stel je nu voor dat module A iets andere gegevens begon te verzenden in zijn berichten. En tegelijkertijd zullen alle modules die afhankelijk zijn van deze berichten niet correct werken.
Stel dat eerder, bij het toevoegen van een nieuwe gebruiker, de autorisatiemodule het bericht USER_ADDED heeft verzonden en na de update dit bericht begon te verzenden bij het proberen te registreren en bovendien een succesvolle registratie of niet in de parameters aangeeft.
Daarom is het erg belangrijk om het berichtmechanisme zeer competent te implementeren. Hiervoor zijn verschillende sjablonen.
Waarnemer. Het wordt gebruikt in het geval van een-op-veel-afhankelijkheid, wanneer veel modules afhankelijk zijn van de status van één - de hoofdmodule. Het gebruikt het mailingmechanisme, wat betekent dat de hoofdmodule gewoon dezelfde berichten naar al zijn abonnees stuurt, en de modules die geïnteresseerd zijn in deze informatie implementeren de "abonnee" -interface en abonneren zich op de mailinglijst.
Deze aanpak wordt veel gebruikt in systemen met een gebruikersinterface, waardoor de kern van de applicatie (model) onafhankelijk blijft terwijl de bijbehorende interfaces worden geïnformeerd dat er iets is veranderd en moet worden bijgewerkt.
Hier is het berichtformaat gestandaardiseerd op het niveau van het besturingssysteem, waarvan de ontwikkelaars moeten zorgen voor achterwaartse compatibiliteit en goede documentatie.
De organisatie van interactie door de verspreiding van berichten heeft een extra "bonus" - het optionele bestaan van "abonnees" op "gepubliceerde" (dat wil zeggen verzonden) berichten. Met zo'n goed ontworpen systeem kunnen op elk moment modules worden toegevoegd/verwijderd.
Berichtenbus
U kunt de uitwisseling van berichten organiseren en hiervoor het Mediator- patroon op een andere manier gebruiken .
Het wordt gebruikt wanneer er een veel-op-veel-afhankelijkheid is tussen modules. De bemiddelaar fungeert als tussenpersoon in de communicatie tussen modules, fungeert als een communicatiecentrum en elimineert de noodzaak voor modules om expliciet naar elkaar te verwijzen.
Hierdoor wordt de interactie van modules met elkaar (“all with all”) vervangen door de interactie van modules alleen met een intermediair (“one with all”). Van de bemiddelaar wordt gezegd dat hij de interactie tussen meerdere modules inkapselt.
Dit is de zogenaamde slimme tussenpersoon . Daar beginnen ontwikkelaars meestal hun krukken toe te voegen, die het gedrag van individuele modules beïnvloeden door het ontvangen van bepaalde berichten in of uit te schakelen.
Een typisch voorbeeld uit de praktijk is de verkeersleiding op luchthavens. Alle berichten van vliegtuigen gaan naar de verkeerstoren van de verkeersleider in plaats van rechtstreeks tussen vliegtuigen te worden verzonden. En de controller neemt al beslissingen over welke vliegtuigen kunnen opstijgen of landen, en stuurt op zijn beurt berichten naar de vliegtuigen.
Belangrijk! Modules kunnen elkaar niet alleen eenvoudige berichten sturen, maar ook commando-objecten. Een dergelijke interactie wordt beschreven door de opdrachtsjabloon . Het komt erop neer om een verzoek om een specifieke actie uit te voeren in te kapselen als een apart object.
In feite bevat dit object een enkele methode execute() , waarmee u deze actie vervolgens kunt doorgeven aan andere modules voor uitvoering als een parameter en in het algemeen alle bewerkingen kunt uitvoeren met het opdrachtobject die kunnen worden uitgevoerd op gewone objecten.
Wet van Demeter
De wet van Demeter verbiedt het gebruik van impliciete afhankelijkheden: "Object A mag niet rechtstreeks toegang hebben tot object C als object A toegang heeft tot object B en object B toegang heeft tot object C."
Dit betekent dat alle afhankelijkheden in de code "expliciet" moeten zijn - klassen / modules kunnen alleen "hun afhankelijkheden" gebruiken in hun werk en mogen er niet doorheen klimmen naar anderen. Een goed voorbeeld is een architectuur met drie lagen. De interfacelaag zou moeten werken met de logische laag, maar zou niet direct moeten interageren met de databaselaag.
In het kort wordt dit principe ook zo geformuleerd: "Ga alleen om met directe vrienden, en niet met vrienden van vrienden." Dit zorgt voor minder samenhang van de code, maar ook voor meer zichtbaarheid en transparantie van het ontwerp.
De wet van Demeter implementeert het reeds genoemde "principe van minimale kennis", dat de basis is van losse koppeling en bestaat erin dat een object / module zo min mogelijk details moet weten over de structuur en eigenschappen van andere objecten / modules en alles in het algemeen, inclusief zijn eigen componenten .
Een analogie uit het leven: als je wilt dat de hond rent, is het stom om zijn poten te bevelen, het is beter om het bevel aan de hond te geven, en zij zal zelf met haar poten omgaan.
Samenstelling in plaats van overerving
Dit is een zeer groot en interessant onderwerp en het verdient op zijn minst een aparte lezing. Er zijn veel exemplaren over dit onderwerp op internet gebroken totdat er een consensus was bereikt - we gebruiken overerving tot een minimum, compositie - tot het maximum.
Het punt is dat overerving eigenlijk de sterkste verbinding tussen klassen biedt, dus het moet worden vermeden. Dit onderwerp komt goed aan bod in het artikel van Herb Sutter " Prefer Composition Over Inheritance ".
Wanneer u ontwerppatronen begint te leren, zult u een hele reeks patronen tegenkomen die de creatie van een object of de interne structuur ervan bepalen. Overigens kan ik in dit verband adviseren om aandacht te besteden aan het Delegate/Delegate patroon en het Component patroon, die uit games zijn voortgekomen .
We zullen later meer over patronen praten.
GO TO FULL VERSION