Ersätter direkta beroenden med meddelanden

Ibland behöver en modul bara meddela andra att vissa händelser/ändringar har inträffat i den, och det spelar ingen roll vad som händer med denna information senare.

I det här fallet behöver modulerna inte alls "känna till varandra", det vill säga innehålla direktlänkar och interagera direkt, utan det räcker med att bara utbyta meddelanden (meddelanden) eller händelser (händelser).

Ibland verkar det som att modulkommunikation via meddelanden är mycket svagare än direkt beroende. Eftersom metoderna inte anropas finns det faktiskt ingen information om klasserna. Men detta är inget annat än en illusion.

Istället för metodnamn börjar logiken att knytas till meddelandetyper, deras parametrar och överförda data. Anslutningen av sådana moduler är utsmetad.

Det brukade vara så här: vi kallar metoder - det finns uppkoppling, vi kallar inte metoder - det finns ingen uppkoppling. Föreställ dig nu att modul A började skicka lite olika data i sina meddelanden. Och samtidigt kommer alla moduler som är beroende av dessa meddelanden inte att fungera korrekt.

Anta att behörighetsmodulen tidigare, när en ny användare lades till, skickade meddelandet USER_ADDED, och efter uppdateringen började den skicka detta meddelande när man försökte registrera sig och dessutom indikera framgångsrik registrering eller inte i parametrarna.

Därför är det mycket viktigt att implementera meddelandemekanismen mycket kompetent. Det finns olika mallar för detta.

Observatör. Det används i fallet med ett-till-många-beroende, när många moduler beror på tillståndet för en - den huvudsakliga. Den använder e-postmekanismen, vilket innebär att huvudmodulen helt enkelt skickar samma meddelanden till alla sina prenumeranter, och de moduler som är intresserade av denna information implementerar "subscriber"-gränssnittet och prenumererar på e-postlistan.

Detta tillvägagångssätt används ofta i system med ett användargränssnitt, vilket gör att kärnan i applikationen (modellen) kan förbli oberoende samtidigt som den informerar dess associerade gränssnitt om att något har förändrats och behöver uppdateras.

Här är meddelandeformatet standardiserat på operativsystemnivå, vars utvecklare ska ta hand om bakåtkompatibilitet och bra dokumentation.

Organiseringen av interaktion genom distribution av meddelanden har en extra "bonus" - den valfria existensen av "prenumeranter" till "publicerade" (det vill säga skickade ut) meddelanden. Ett väldesignat system som detta gör att moduler kan läggas till/ta bort när som helst.

Meddelandebuss

Du kan organisera utbytet av meddelanden och använda Mediator -mönstret för detta på ett annat sätt .

Det används när det finns ett många-till-många-beroende mellan moduler. Medlaren fungerar som en mellanhand i kommunikationen mellan moduler, fungerar som ett kommunikationscenter och eliminerar behovet av att moduler uttryckligen hänvisar till varandra.

Som ett resultat ersätts interaktionen mellan moduler med varandra ("alla med alla") av interaktionen mellan moduler endast med en mellanhand ("en med alla"). Mediatorn sägs kapsla in interaktionen mellan flera moduler.

Meddelandebuss

Detta är den så kallade smarta mellanhanden . Det är där som utvecklare oftast börjar lägga till sina kryckor, vilket påverkar beteendet hos enskilda moduler genom att slå på/stänga av mottagning av vissa meddelanden.

Ett typiskt verkligt exempel är flygplatstrafikkontroll. Alla meddelanden från flygplan går till flygledarens kontrolltorn istället för att skickas direkt mellan flygplanen. Och flygledaren fattar redan beslut om vilka plan som kan lyfta eller landa, och skickar i sin tur meddelanden till planen.

Viktig! Moduler kan inte bara skicka enkla meddelanden till varandra utan också kommandoobjekt. Sådan interaktion beskrivs av kommandomallen . Summan av kardemumman är att kapsla in en begäran om att utföra en specifik åtgärd som ett separat objekt.

Faktum är att det här objektet innehåller en enda execute()- metod , som sedan låter dig skicka denna åtgärd till andra moduler för exekvering som en parameter och i allmänhet utföra alla operationer med kommandoobjektet som kan utföras på vanliga objekt.

Demeters lag

Demeterlagen förbjuder användningen av implicita beroenden: "Objekt A får inte ha direkt tillgång till objekt C om objekt A har tillgång till objekt B och objekt B har tillgång till objekt C."

Detta innebär att alla beroenden i koden måste vara "explicita" - klasser / moduler kan bara använda "sina beroenden" i sitt arbete och ska inte klättra genom dem till andra. Ett bra exempel är en treskiktsarkitektur. Gränssnittslagret ska fungera med logiklagret, men ska inte interagera direkt med databaslagret.

Kortfattat är denna princip också formulerad på detta sätt: "Interagera endast med omedelbara vänner, och inte med vänners vänner." Detta uppnår mindre koherens i koden, samt större synlighet och transparens i dess design.

Demeterlagen implementerar den redan nämnda ”principen om minimikunskap”, som är grunden för lös koppling och består i att ett objekt/modul ska känna till så få detaljer som möjligt om struktur och egenskaper hos andra objekt/moduler och allt i allmänhet, inklusive dess egna komponenter .

En analogi från livet: om du vill att hunden ska springa är det dumt att befalla sina tassar, det är bättre att ge kommandot till hunden, och hon kommer att ta itu med sina tassar själv.

Sammansättning istället för arv

Detta är ett mycket stort och intressant ämne och det förtjänar åtminstone en separat föreläsning. Många kopior bröts om detta ämne på Internet tills en konsensus nåddes - vi använder arv till ett minimum, sammansättning - till maximalt.

Poängen är att arv faktiskt ger den starkaste kopplingen mellan klasserna, så det bör undvikas. Det här ämnet är väl täckt i Herb Sutters artikel " Prefer Composition Over Inheritance" .

När du börjar lära dig designmönster kommer du att stöta på en hel massa mönster som styr skapandet av ett objekt eller dess interna struktur. Förresten, jag kan råda i detta sammanhang att vara uppmärksam på Delegat/Delegate- mönstret och Component -mönstret, som kom från spel .

Vi kommer att prata mer om mönster lite senare.