Efficiëntie

Ervaren programmeurs kunnen gemakkelijk een goede architectuur van een slechte onderscheiden, maar als hen wordt gevraagd om het in een paar woorden te beschrijven, zullen ze dat waarschijnlijk niet kunnen. Er is niet één criterium voor goede architectuur en geen eenduidige definitie.

Als je er echter over nadenkt, kun je een aantal criteria opschrijven waaraan een goede architectuur zou moeten voldoen. Een goede architectuur is in de eerste plaats een logische architectuur die het proces van het ontwikkelen en onderhouden van een programma eenvoudiger en efficiënter maakt.

Als een programma een goede architectuur heeft, is het altijd gemakkelijk genoeg om te begrijpen hoe het werkt en waar code moet worden geschreven. Een goed ontworpen programma is gemakkelijker te wijzigen, testen, debuggen en ontwikkelen. Slimme mensen hebben de volgende criteria voor goede architectuur geformuleerd:

  • efficiëntie;
  • Flexibiliteit;
  • Uitbreidbaarheid;
  • Schaalbaarheid;
  • testbaarheid;
  • Code onderhoudbaarheid.

Systeem efficiëntie. Het programma moet natuurlijk de toegewezen taken oplossen en zijn functies goed uitvoeren, en onder verschillende omstandigheden. Het lijkt erop dat elk programma doet wat het moet doen (als het geschreven is), maar vaak is dat helemaal niet het geval.

Je zult constant programma's tegenkomen die niet doen wat ze beweren te doen.

  • Libre Office is een volledige vervanging voor Microsoft Office (niet echt);
  • De Edge-browser ondersteunt alle webstandaarden (niet echt);
  • De bank geeft om de veiligheid van de persoonsgegevens van haar gebruikers (eigenlijk niet).

En dan hebben we het nog niet gehad over prestaties, betrouwbaarheid, tijdige bugfixes of het publiceren van informatie over bekende kwetsbaarheden.

Het is duidelijk dat niemand perfect is, maar het programma moet zijn primaire taken oplossen. Daarom, zonder efficiëntie, nergens.

Flexibiliteit

Het enige dat belangrijker is dan efficiëntie is naar mijn mening flexibiliteit. Elke toepassing moet in de loop van de tijd veranderen, naarmate de vereisten veranderen, komen er nieuwe bij. Hoe sneller en handiger het is om wijzigingen aan te brengen in de bestaande functionaliteit, hoe minder problemen en fouten het veroorzaakt, hoe flexibeler de systeemarchitectuur.

Heel vaak denken beginnende programmeurs/architecten dat ze een ideale architectuur nodig hebben voor de huidige taken. Nee. Je hebt een ideale architectuur nodig voor de taken die je over een jaar worden aangekondigd. Jij, die nu al de toekomstige taken niet kent, zou moeten weten wat ze zullen zijn.

Het heeft geen zin om te proberen ze te voorspellen, want er zal altijd iets onverwachts zijn. Maar u moet er rekening mee houden dat dergelijke taken zullen verschijnen. Probeer daarom tijdens het ontwikkelingsproces te evalueren wat er wordt verkregen in termen van hoe het moet worden gewijzigd.

Stel uzelf de vraag: "Wat gebeurt er als de huidige architectuurbeslissing verkeerd blijkt te zijn?", "Hoeveel code wordt er gewijzigd?". Het wijzigen van een fragment van het systeem zou geen invloed moeten hebben op de andere fragmenten.

Bouwkundige beslissingen moeten waar mogelijk niet in steen gebeiteld worden en de gevolgen van bouwkundige fouten moeten redelijkerwijs beperkt blijven. "Met een goede architectuur kunt u belangrijke beslissingen UITSTELLEN" (Bob Martin) en minimaliseert u de "kosten" van fouten.

Een van deze benaderingen is het opsplitsen van de applicatie in microservices: het is gemakkelijk om de reeds bestaande logica op te splitsen in afzonderlijke delen. Maar het grootste probleem is om toekomstige wijzigingen in een dozijn services tegelijk aan te brengen om één kleine functie te implementeren.

Schaalbaarheid

Schaalbaarheid is de mogelijkheid om de ontwikkelingstijd te verkorten door nieuwe mensen aan het project toe te voegen. De architectuur moet het mogelijk maken om het ontwikkelproces parallel te laten verlopen, zodat veel mensen tegelijkertijd aan het programma kunnen werken.

Het lijkt erop dat deze regel op zichzelf wordt uitgevoerd, maar in de praktijk is alles precies het tegenovergestelde. Er is zelfs een superpopulair boek, The Mythical Man-Month , waarin wordt uitgelegd waarom wanneer nieuwe mensen aan een project worden toegevoegd, de ontwikkelingstijd toeneemt.

Uitbreidbaarheid

Uitbreidbaarheid is de mogelijkheid om nieuwe functies en entiteiten aan een systeem toe te voegen zonder de kernstructuur te doorbreken. In de beginfase is het logisch om alleen de basis en meest noodzakelijke functionaliteit in het systeem te stoppen.

Dit is het zogenaamde YAGNI-principe - je hebt het niet nodig , "je hebt het niet nodig". Tegelijkertijd moet de architectuur u in staat stellen om indien nodig eenvoudig extra functionaliteit toe te voegen. En zodat de invoering van de meest waarschijnlijke wijzigingen de minste inspanning kostte.

De vereiste dat de architectuur van het systeem flexibel en uitbreidbaar moet zijn (dat wil zeggen, in staat moet zijn tot verandering en evolutie) is zo belangrijk dat het zelfs als een apart principe is geformuleerd - het "Open/Closed Principle " . Het Open-Closed-principe is het tweede van de vijf SOLID-principes: software-entiteiten (klassen, modules, functies) moeten open zijn voor uitbreiding, maar gesloten voor wijziging .

Met andere woorden: het moet mogelijk zijn om het gedrag van het systeem te veranderen en uit te breiden zonder bestaande delen van het systeem te herschrijven .

Dit betekent dat de applicatie zo moet worden ontworpen dat het veranderen van het gedrag en het toevoegen van nieuwe functionaliteit wordt bereikt door het schrijven van nieuwe code (extensies), zonder bestaande code te hoeven wijzigen.

In dit geval zal de opkomst van nieuwe vereisten geen wijziging van de bestaande logica met zich meebrengen, maar kan deze primair worden geïmplementeerd door deze uit te breiden. Dit principe is de basis van "plug-in architectuur" (Plugin Architecture). De technieken waarmee dit kan worden bereikt, zullen later worden besproken.

Herinner je je servlets en filters nog? Waarom waren er filters nodig, en zelfs met afzonderlijke interfaces, als in feite dezelfde logica kon worden geïmplementeerd met behulp van servlets?

Het was de uitvinding van het concept van filters (serviceservlets) die het mogelijk maakten om verschillende servicefuncties naar een aparte laag te verplaatsen. En in de toekomst, bij het veranderen van het gedrag van filters, was het niet nodig om de servlets te veranderen.

Vóór de uitvinding van filters bevond alle servicelogica die verantwoordelijk was voor het omleiden van verzoeken zich in de servlets zelf. En vaak zou een kleine wijziging in de logica leiden tot de noodzaak om alle servlets te doorlopen en verschillende wijzigingen aan te brengen.

Testbaarheid

Als u een Java Backend-ontwikkelaar bent, stellen uw servertoepassingen vaak een reeks methoden bloot als een REST API. En om te controleren of al uw methoden werken zoals bedoeld, moeten ze worden bedekt met tests.

Over het algemeen is API-testdekking een goede stijl. Hiermee kunt u ervoor zorgen dat uw API echt doet waarvoor het bedoeld was. En wat nog belangrijker is, u kunt wijzigingen aanbrengen in de serverlogica en eenvoudig controleren of u niet per ongeluk iets hebt verbroken .

Zodra je begint met het schrijven van tests, realiseer je je dat de meeste code helemaal niet kan worden getest: privémethoden, sterke koppeling, statische klassen en variabelen.

“Waarom hebben we tests nodig als de code werkt?”, zal de beginner vragen.

“Waarom hebben we werkende code nodig als deze niet getest kan worden?”, zal de professional vragen.

Code die eenvoudig te testen is, bevat minder bugs en is betrouwbaarder. Maar tests verbeteren niet alleen de codekwaliteit. Vrijwel alle ontwikkelaars komen uiteindelijk tot de conclusie dat de eis van “goede testbaarheid” ook een leidraad is die automatisch leidt tot een goed ontwerp.

Hier is een citaat uit het boek Ideal Architecture: "Gebruik het principe van "testbaarheid" van een klasse als een "lakmoesproef" van goed klasseontwerp. Zelfs als u geen enkele regel testcode schrijft, beantwoordt u deze vraag in 90 % van de gevallen zal helpen om te begrijpen hoe alles goed" of "slecht" is met zijn ontwerp."

Er is een hele methodiek voor het ontwikkelen van programma's op basis van tests, die Test Driven Development (TDD) wordt genoemd. Dit is natuurlijk het andere uiterste: schrijf code voordat je code schrijft.

Code onderhoudbaarheid

In de regel werken veel mensen aan het programma - sommigen vertrekken, nieuwe komen. De gemiddelde werktijd van een programmeur in een IT-bedrijf is anderhalf jaar. Dus als je bij een project komt dat 5 jaar oud is, dan heeft slechts 20% van je collega's er vanaf het begin aan meegewerkt.

Het onderhouden en ontwikkelen van een programma dat anderen hebben geschreven is erg moeilijk. Ook als het programma al geschreven is, is het vaak nodig om het te blijven onderhouden: fouten herstellen en kleine correcties aanbrengen. En vaak moet dit worden gedaan door mensen die niet hebben deelgenomen aan het schrijven ervan.

Daarom moet een goede architectuur het voor nieuwe mensen relatief gemakkelijk en snel maken om het systeem te begrijpen . Het project moet zijn:

  • Goed gestructureerd.
  • Bevat geen duplicatie.
  • Zorg voor goed opgemaakte code.
  • Het is wenselijk om documentatie mee te sturen.
  • Het is noodzakelijk om standaard en bekende oplossingen voor programmeurs toe te passen.

U kunt het project waaraan u werkt eenvoudig beoordelen op een 5-puntensysteem . Tel gewoon twee punten voor elk van deze vereisten . En als je er 5 of meer krijgt, dan heb je geluk.

Programmeurs hebben zelfs het principe van de minste verrassing : hoe exotischer het systeem, hoe moeilijker het voor anderen te begrijpen is. Meestal wordt het gebruikt in relatie tot de gebruikersinterface, maar het is ook van toepassing op het schrijven van code.