Software-ontwikkelingsprincipes zijn een set van specifieke regels en aanbevelingen die ingenieurs zouden moeten volgen tijdens de programma-implementatie als ze mooie, duidelijke en onderhoudbare code willen schrijven. Er is geen toverstokje dat een mengelmoes van variabelen, klassen en functies kan veranderen in perfecte code, maar er zijn wel een paar tips en hints die een ingenieur kunnen helpen bepalen of hij de juiste dingen doet.
Laten we eens kijken naar deze basisaanbevelingen. Sommige van de onderstaande principes zijn Python-specifiek, maar de meeste niet.
Met twee keer meten en één keer knippen
Ik denk dat dit het belangrijkste principe van allemaal is. Als je maar één principe leert van deze post, zou het deze moeten zijn. Wij, ontwikkelaars / architecten / managers mensen worstelen met gebrek aan aandacht, domme fouten en misdrukken, persoonlijke problemen, slechte stemmingen, en koude koffie. Niets van dit alles is relevant – het probleem moet worden opgelost. Voor mij als ingenieur betekent dit principe het kiezen van de juiste oplossing voor het probleem, het kiezen van de juiste aanpak van het probleem, het kiezen van het juiste gereedschap om het probleem op te lossen, vertrouwen in de gebouwde oplossing. Kiezen betekent hier nadenken, de nodige middelen vinden, het juiste team samenstellen, nadenken over het ontwerp, nadenken over de aanpak, taken vastleggen, het resultaat controleren en er verantwoordelijkheid voor dragen. Dit is “Engineering as is”. Ik denk dat ik zelf niet klaar ben om het met juiste woorden te beschrijven.
Don’t Repeat Yourself (DRY)
Het is een vrij eenvoudig maar zeer nuttig principe dat zegt dat het herhalen van hetzelfde op verschillende plaatsen een slecht idee is. Allereerst heeft het te maken met de noodzaak van verdere ondersteuning en aanpassing van de code. Als een of ander codefragment op verschillende plaatsen in een programma wordt gedupliceerd, is er een grote kans op twee catastrofale situaties:
- Wanneer u zelfs maar kleine wijzigingen in de broncode aanbrengt, moet u dezelfde code op verschillende plaatsen wijzigen. Dit kost extra tijd, moeite en aandacht (vaak is het niet gemakkelijk).
- Het eerste punt volgt op het tweede. U of een andere ontwikkelaar van uw team kan per ongeluk een van de wijzigingen over het hoofd zien (dit kan eenvoudig gebeuren door het samenvoegen van takken in vcs) en worden geconfronteerd met de daaropvolgende bugs in de applicatie. Deze bugs kunnen frustrerend voor je zijn omdat je gehoord hebt dat zo’n bug al verholpen is.
In dit verband is er een aanbeveling – als een code meer dan twee keer in de listing voorkomt, moet deze apart geplaatst worden. Dit is een algemene aanbeveling. In feite zou je moeten nadenken over het maken van een aparte methode, zelfs als je een herhaling een tweede keer tegenkomt.
Occam’s Razor
Het is een heel algemeen idee, dat uit de filosofie naar het programmeren is gekomen. Het principe kreeg zijn naam van de Engelse monnik William of Oakham. Dit principe zegt: “Entiteiten mogen niet zonder noodzaak worden vermenigvuldigd”. In de techniek wordt dit principe als volgt geïnterpreteerd: het is niet nodig om onnodige entiteiten zonder noodzaak te creëren. Het is dus altijd een goed idee om eerst na te denken over de voordelen van het toevoegen van nog een methode/klasse/tool/proces, enz. Immers, als je nog een methode/klasse/tool/proces etc. toevoegt en je krijgt geen andere voordelen dan toegenomen complexiteit, wat is dan het nut?
Keep It Simple Stupid (KISS)
Dit principe lijkt erg op het bovenstaande, maar het heeft een iets andere betekenis. Dit principe zegt dat de code zo eenvoudig mogelijk moet zijn, zonder ingewikkelde structuren, omdat het anders het debuggen en het onderhoud van de code zal bemoeilijken. Bovendien zal het voor een andere programmeur moeilijker zijn om de logica van de code te begrijpen, wat op zijn beurt ook weer extra tijd en moeite zal kosten. Daarom moet je altijd proberen om eenvoudige constructies te gebruiken die het probleem zo goed mogelijk oplossen, zonder talrijke vertakkingen, diepe nesting en overdreven overbelaste klassestructuren. Door dit te doen, maak je het leven gemakkelijker voor jezelf en je collega’s, want complexiteit genereert bugs. Onthoud wat Peter Hintiens zei: “Eenvoud is altijd beter dan functionaliteit”.
You Aren’t Gonna Need It (YAGNI)
Een probleem waar veel programmeurs last van hebben. De wens om in één keer alle noodzakelijke (en soms zelfs onnodige) functionaliteit vanaf het allereerste begin van het project te implementeren. Dat wil zeggen, wanneer een ontwikkelaar vanaf het allereerste begin alle mogelijke methoden aan de klasse toevoegt en ze implementeert, en ze in de toekomst misschien wel nooit zal gebruiken. Dus, volgens deze aanbeveling, implementeer eerst alleen wat je nodig hebt, en breid later, indien nodig, de functionaliteit uit. Op deze manier bespaart u moeite, tijd en zenuwen voor het debuggen van code die niet echt nodig is.
Big Design Up Front
Voordat u begint met het ontwikkelen van functionaliteit, moet u eerst nadenken over de applicatie-architectuur en het gehele systeem ontwerpen tot voldoende kleine details, en pas daarna overgaan tot implementatie volgens een vooraf vastgesteld plan. Principe heeft bestaansrecht, maar de laatste tijd is er nogal wat kritiek op. Deze houdt in de eerste plaats verband met de veroudering van het plan tijdens het ontwerpen en uitwerken. In dit verband is het noodzakelijk de latere wijzigingen alsnog aan te brengen. Maar het heeft ook onbetwistbare voordelen, bij een correct ontwerp is het mogelijk de kosten van verdere debugging en correctie van fouten aanzienlijk te verminderen. Bovendien zijn dergelijke informatiesystemen in de regel laconieker en architectonisch correcter.
Vermijd voortijdige optimalisatie
“Voortijdige optimalisatie is de wortel van alle kwaad (of in ieder geval het meeste ervan) in programmeren” – Donald Knuth
Optimalisatie is een zeer juist en noodzakelijk proces om het programma te versnellen en het verbruik van systeembronnen te verminderen. Maar alles heeft zijn eigen tijd. Als optimalisatie in een vroeg stadium van de ontwikkeling wordt uitgevoerd, kan het meer kwaad dan goed doen. Ten eerste heeft dit te maken met het feit dat de ontwikkeling van een geoptimaliseerde code meer tijd en moeite vergt voor ontwikkeling en ondersteuning. In dit geval moet men vaak eerst de juistheid van de gekozen ontwikkelingsaanpak controleren. Daarom is het in het begin rendabeler om een eenvoudige maar niet de meest optimale aanpak te gebruiken. En in een later stadium, wanneer wordt ingeschat hoezeer deze aanpak het werk van een applicatie vertraagt, over te stappen op een sneller of minder resource-intensief algoritme. Bovendien kunnen, zolang u aanvankelijk het meest optimale algoritme implementeert, de vereisten veranderen en de code naar de vuilnisbak gaan. Het is dus niet nodig om tijd te verspillen aan voortijdige optimalisatie.
Principle Of Least Astonishment
Dit principe houdt in dat je code intuïtief en voor de hand liggend moet zijn, en een andere ontwikkelaar niet mag verrassen bij het reviewen van de code. Bijvoorbeeld, als de methode heet “koekjes maken” maar je krijgt aardappelen als resultaat, dan is die code (uiteraard) slecht. Bovendien moet je neveneffecten proberen te vermijden en documenteren als je ze niet kunt vermijden.
S.O.L.I.D.
“SOLID” is eigenlijk een groep van objectgeoriënteerde ontwerpprincipes. Elke letter in “SOLID” staat voor een van de principes, die zijn:
- Enkelvoudige verantwoordelijkheid stelt dat elke module of klasse verantwoordelijk moet zijn voor een enkel deel van de functionaliteit die door de software wordt geleverd en dat die verantwoordelijkheid volledig moet worden ingekapseld door de klasse;
- Open-gesloten stelt dat software-entiteiten (klassen, modules, functies, enz.) open moeten zijn voor uitbreiding, maar gesloten voor wijziging;
- Liskov-substitutie stelt dat de geërfde klasse het gedrag van de basisklasse moet aanvullen, niet vervangen;
- Interface segregation stelt dat geen enkele client gedwongen mag worden afhankelijk te zijn van methoden die hij niet gebruikt;
- Dependency inversion zegt dat de programmeur op het interfaceniveau moet werken en niet op het implementatieniveau.
Wanneer deze principes samen worden toegepast, helpen ze een ontwikkelaar code te maken die gemakkelijk te onderhouden en uit te breiden is in de tijd.
Wet van Demeter
Het basisidee van dit principe is om de verantwoordelijkheidsgebieden te verdelen tussen klassen en de logica in te kapselen binnen een klasse, methode of structuur. Uit dit principe kunnen verschillende aanbevelingen worden onderscheiden:
- De klassen of entiteiten moeten onafhankelijk zijn
- U moet proberen het aantal verbindingen tussen verschillende klassen te beperken (de zogenaamde koppeling).
- De gekoppelde klassen moeten in één module/pakket/directory zitten (ook wel cohesie genoemd.
Als je deze principes volgt, wordt de applicatie flexibeler, begrijpelijker en makkelijker te onderhouden.
Conclusie
Mede-ontwikkelaars, laten we ingenieurs zijn! Laten we nadenken over ontwerp en bouwen aan robuuste en goed geïmplementeerde systemen, in plaats van organische monsters te kweken. Opgesomde principes zijn sterk gecorreleerd en in hun essentie met elkaar verbonden. Natuurlijk heb ik ze niet bedacht, maar een kleine herinnering kan geen kwaad, mijn geheugen is in ieder geval niet perfect.
Aanbevolen boeken
- Clean Code door Robert C. Martin
- Clean Architecture door Robert C. Martin