8.1 Ontleding is alles

Voor de duidelijkheid een afbeelding uit een goed artikel "Decoupling of Object-Oriented Systems", die de belangrijkste punten illustreert die zullen worden besproken.

Ontleding

Denk je nog steeds dat het ontwerpen van een applicatie-architectuur eenvoudig is?

8.2 Interfaces, implementatie verbergen

De belangrijkste principes voor het verminderen van de koppeling van het systeem zijn de principes van OOP en het principe van inkapseling + abstractie + polymorfisme erachter.

Dat is de reden:

  • Modules zouden "black boxes" voor elkaar moeten zijn (inkapseling) . Dit betekent dat de ene module niet in een andere module moet "klimmen" en iets moet weten over de interne structuur ervan. Objecten in het ene subsysteem mogen niet rechtstreeks toegang hebben tot objecten in een ander subsysteem.
  • Modules/subsystemen zouden alleen met elkaar moeten communiceren via interfaces (dat wil zeggen, abstracties die niet afhankelijk zijn van implementatiedetails). Dienovereenkomstig moet elke module een goed gedefinieerde interface of interfaces hebben voor interactie met andere modules.

Het principe van "black box" (inkapseling) stelt ons in staat om de structuur van elk subsysteem onafhankelijk van andere subsystemen te beschouwen. De module, die een "black box" is, kan relatief vrij worden gewijzigd. Problemen kunnen alleen ontstaan ​​op het knooppunt van verschillende modules (of een module en een omgeving).

En die interactie moet beschreven worden in de meest algemene (abstracte) vorm, namelijk in de vorm van een interface. In dit geval werkt de code hetzelfde met elke implementatie die voldoet aan het interfacecontract. Het is deze mogelijkheid om met verschillende implementaties (modules of objecten) te werken via een uniforme interface die polymorfisme wordt genoemd.

Daarom is Servlet een interface : de webcontainer weet niets van servlets, want dit zijn enkele objecten die de Servlet-interface implementeren en dat is alles. Servlets weten ook iets over de structuur van de container. De Servlet-interface is dat contract, die standaard, die minimale interactie die nodig is om Java-webapplicaties de wereld te laten overnemen.

Polymorfisme is helemaal niet het overschrijven van methoden, zoals soms ten onrechte wordt aangenomen, maar in de eerste plaats de uitwisselbaarheid van modules/objecten met dezelfde interface of “één interface, veel implementaties”. Om polymorfisme te implementeren, is het overervingsmechanisme helemaal niet nodig. Dit is belangrijk om te begrijpen, omdat overerving in het algemeen zoveel mogelijk moet worden vermeden .

Dankzij interfaces en polymorfisme wordt juist de mogelijkheid bereikt om de code aan te passen en uit te breiden zonder te veranderen wat al geschreven is (Open-Closed Principle).

Zolang de interactie van modules uitsluitend wordt beschreven in de vorm van interfaces en niet gebonden is aan specifieke implementaties, heeft u de mogelijkheid om absoluut "pijnloos" voor het systeem de ene module te vervangen door een andere die dezelfde interface implementeert, evenals voeg een nieuwe toe en breid daarmee de functionaliteit uit.

Het is net als in de LEGO constructor - de interface standaardiseert de interactie en dient als een soort connector waar elke module met een geschikte connector kan worden aangesloten.

De flexibiliteit van de ontwerper wordt verzekerd door het feit dat we eenvoudig een module of onderdeel kunnen vervangen door een andere met dezelfde connectoren (met dezelfde interface), en zoveel nieuwe onderdelen kunnen toevoegen als we willen (tegelijkertijd bestaande onderdelen worden op geen enkele manier veranderd of veranderd).

Met interfaces kunt u een eenvoudiger systeem bouwen, waarbij u elk subsysteem als een geheel beschouwt en de interne structuur negeert. Ze zorgen ervoor dat modules op elkaar inwerken en tegelijkertijd niets weten over de interne structuur van elkaar, waardoor het principe van minimale kennis, wat de basis is van losse koppeling, volledig wordt geïmplementeerd.

Hoe algemener/abstracter de interfaces zijn gedefinieerd en hoe minder beperkingen ze opleggen aan de interactie, hoe flexibeler het systeem. Vanaf hier volgt nog een van de principes van SOLID eigenlijk - het Interface Segregation Principle , dat zich verzet tegen "dikke interfaces".

Hij zegt dat grote, omvangrijke interfaces moeten worden opgesplitst in kleinere, meer specifieke interfaces, zodat klanten van kleine interfaces (afhankelijke modules) alleen weten met welke methoden ze moeten werken.

Dit principe is als volgt geformuleerd: “Klanten zouden niet afhankelijk moeten zijn van methoden (wees zich bewust van methoden) die ze niet gebruiken” of “Veel gespecialiseerde interfaces zijn beter dan één universele”.

Het blijkt dat zwakke connectiviteit alleen wordt geboden wanneer de interactie en afhankelijkheden van modules alleen worden beschreven met behulp van interfaces, dat wil zeggen abstracties, zonder gebruik te maken van kennis over hun interne structuur en structuur.En in feite wordt op deze manier inkapseling geïmplementeerd. Bovendien hebben we de mogelijkheid om het gedrag van het systeem uit te breiden / te veranderen door verschillende implementaties toe te voegen en te gebruiken, dat wil zeggen vanwege polymorfisme. Ja, we kwamen weer bij OOP - Encapsulation, Abstraction, Polymorphism.

8.3 Gevel: module-interface

Hier zal een ervaren programmeur vragen: als het ontwerp niet op het niveau van objecten is die zelf de bijbehorende interfaces implementeren, maar op het niveau van modules, wat is dan de implementatie van de module-interface?

Antwoord: sprekend in de taal van ontwerppatronen, kan een speciaal object verantwoordelijk zijn voor de implementatie van de module-interface - Facade . Als je methodes aanroept op een object dat het Gateway-achtervoegsel bevat (bijvoorbeeld MobileApiGateway), dan is het hoogstwaarschijnlijk een façade.

Een façade is een interface-object dat een reeks bewerkingen op hoog niveau verzamelt voor het werken met een bepaald subsysteem, waarbij de interne structuur en ware complexiteit erachter worden verborgen . Biedt bescherming tegen wijzigingen in de implementatie van het subsysteem. Dient als een enkel toegangspunt - "je schopt tegen de façade en hij weet wie er in dit subsysteem moet worden getrapt om te krijgen wat hij nodig heeft."

U hebt zojuist kennis gemaakt met een van de belangrijkste ontwerppatronen waarmee u het concept van interfaces kunt gebruiken bij het ontwerpen van modules en ze daardoor kunt ontkoppelen: "Gevel".

Bovendien maakt "Facade" het mogelijk om op dezelfde manier met modules te werken als met gewone objecten en alle nuttige principes en technieken toe te passen die worden gebruikt bij het ontwerpen van klassen bij het ontwerpen van modules.

Gevel: module-interface

Opmerking : hoewel de meeste programmeurs het belang van interfaces begrijpen bij het ontwerpen van klassen (objecten), lijkt het erop dat velen het idee ontdekken om ook interfaces op moduleniveau te gebruiken.