Blog #250!

Jeetje, ik blog alweer een tijdje! Er zijn 767 dagen voorbij gegaan sinds ik mijn honderdste blog schreef. Dus: feest! Vandaag blik ik terug op de laatste 150 blogs.

Ontwerp

De laatste tijd ben ik me op ontwerpintuïties aan het richten. Het zijn reflecties op het nut en de schoonheid van verschillende manieren om code te structureren. De manier waarop we onze Controllers dom hielden en houden onderzocht ik als case study, het is een synthese van enkele van de inzichten die ik in de jaren op heb gedaan over ontwerp.

Een centraal idee achter dit thema is dat we als vakmensen geen genoegen hoeven te nemen met moeilijke, lelijke code. – Nee, we mogen er geen genoegen mee nemen. Daarom is het belangrijk om in de verschillen tussen overerving en compositie met dependency injection te duiken, en te mijmeren over de schoonheid van symmetrische tegenover asymmetrische overerving

De kwaliteit (gebruiksgemak, schoonheid – eenvoud, onderhoudbaarheid etc.) van onze code is onze verantwoordelijkheid. En die verantwoordelijkheid kunnen we alleen nemen als we onze ontwerpintuïties kunnen expliciteren, als we een ander uit kunnen leggen wat de voor- en nadelen van het ene ontwerp zijn tegenover het andere. Want alleen zo kan die ander onze ontwerpen kritisch bejegenen en verbeteren.

Functioneel programmeren

Ik schuwde daarbij niet om over de grenzen van het objectgeoriënteerde paradigma te kijken. Functioneel programmeren was voor mij de openbaring van het afgelopen jaar. Ik schreef over functors en monaden (waaronder Options), het verschil tussen .Select en .ForEach en ook over .Aggregate, over eerlijke functies (en modellen) en callback hell.

Functioneel programmeren heeft mijn code eenvoudiger gemaakt, robuuster, descriptiever en eleganter. De vragen die ik me tegenwoordig stel als ik een stuk code voor mijn neus krijg, zijn niet meer dezelfde als vroeger. – Ik ben gegroeid als ontwikkelaar (al kun je er natuurlijk altijd over twisten of het de juiste kant op was).

Boven alles ben ik Enrico Buonanno dank verschuldigd, zijn Functional Programming in C# (mijn favoriete boek van 2022) heeft mijn manier van code schrijven voorgoed veranderd. (Simon Painters Functional Programming with C# is ook leuk!) Ik pak het boek nog regelmatig uit de kast als ik mijn functionele vaardigheden wil slijpen.

Testen

Maar codekwaliteit houdt niet op bij de grenzen van de code zelf, in welke stijl die ook geschreven is. Dat wat om de code (“dé code”) heen gebeurt is net zo belangrijk. – Collega’s van me weten dat als ik zulke dingen zeg, het niet lang kan duren voordat ik over geautomatiseerd testen begin te oreren.

Want oreren deed ik. Mijn honderdenéénste blog ging over Test-Driven Development, en er volgden er nog velen. TDD is een idee dat tegelijkertijd simpel en diep is. De basis leer je in vijf minuten, maar er meester in worden duurt jaren.

Ook voor de rol en inhoud van mijn tests was er uitgebreide aandacht. Ik schreef over tests als documentatie, vangnet en ontwerpmiddel; testscope (ook hier en hier), de unit in unit tests, testpiramides en -diamanten, het structureren van testclasses, codeduplicatie in tests, het gebruik van productiedata – de lijst gaat maar door en door.

Een deel van die inzichten bundelde ik in Altijd up to date documentatie met maximaal descriptieve tests, een presentatie die ik met veel plezier op verschillende gelegenheden heb mogen geven. De tijd is mijn grootste vijand bij dit praatje – er is genoeg materiaal om een collegereeks mee te vullen.

Code review

De noodzaak van al dat gezwam over tests bleek toen enkele van mijn collega’s die praktijk lieten vallen en ze de waardevolle les leerden dat het niet jouw verantwoordelijkheid is een onmogelijke deadline te halen. (En al helemaal niet door op kwaliteit te bezuinigen!)

Het deed me mijn blik op pull requests (PR’s) en code reviews richten. We maakten onze tester een verplichte reviewer en dat deed me denken aan mijn eigen eerste code review. Het wierp vragen op over hoe je PR’s – en dus code – eigenlijk leest (ook in deze en deze blog). Ook over PR’s en de noodzaak van het reviewen van testcode sprak ik op diverse gelegenheden.

Goed ontworpen code kan alleen gedijen in een goedaardige omgeving. Tests en (continue) code reviews zijn noodzakelijke voorwaarden voor het creëren van zo’n omgeving.

Refactoren

Daarbij is het belangrijk om je te realiseren dat goed ontworpen code nooit – ineens opduikt, ook niet in een ideale omgeving. Softwareontwikkeling is een empirische discipline: je probeert iets, inspecteert het resultaat, en past je code daarop aan. Die aanpassing kan een wijziging in het ontwerp inhouden – vaak is zo’n wijziging noodzakelijk om de kwaliteit van de code te kunnen blijven waarborgen.

Ik heb op refactoren gereflecteerd aan de hand van afwas, Tolstoj en chirurgie. Ik onderscheidde twee stijlen van refactoren, dupliceerde methods (tijdelijk!) en scheidde data ophalen van data manipuleren. Het nauwgezet bekijken van je eigen refactorslagen zet je eigen verhouding tot je code op scherp.

Mijn mening over de essentie van refactoren, dat wat refactoren is, is in de loop der jaren veranderd. Vroeger zag ik het als het moment waarop je de ontwikkeling van nieuwe features officieel stilzette om je code grootscheeps onder handen te nemen. Tegenwoordig wordt elke wijziging die ik in een codebase doe, omkranst door kleine refactorslagen: het herstructureren van een class of method voordat ik nieuwe functionaliteit toevoeg, het opruimen van de rommel die ik noodzakelijkerwijs maak wanneer die nieuwe functionaliteit vorm krijgt. Het leidde tot een herwaardering van Martin Fowlers klassieke werk over het onderwerp, Refactoring: Improving the Design of Existing Code.

Filosofie

Er werd ook filosofisch op ontwerp gereflecteerd. Ik begon mijn honderste blog met wat gedachten over Domain-Driven Design en Ludwig Wittgenstein. Het lijkt me passend om dit overzicht van de afgelopen 150 blogs af te sluiten in diezelfde hoek.

De Wittgensteinbibliotheek is sindsdien aangevuld met pseudofilosfische onderzoekingen en een logisch-filosofische Abhandlung. Ik schreef daarnaast over het werk van (de vorige week helaas overleden) Daniel Dennett over evolutie. In die kruisbestuiving schreef ik over evolutionair programmeren en luchthaken en hijskranen. Ik weet niet zeker of het overal filosofisch hout snijdt, maar het was een leuke intellectuele oefening.

Ook vakinhoudelijk was er ruimte voor fundamentele reflectie. Van Anjana Vakil leerde ik dat objectgeoriënteerde code niet om objecten draait. Denk daar maar eens over na!

Het goed doen

Code ontwerpen, testen, beoordelen, schrijven en herschrijven (maar niet per se in die volgorde) en daar dan weer op reflecteren (en soms een nummer van Bob Dylan uitprogrammeren) – het zijn de hoofdingrediënten van de afgelopen twee jaar dotkarl.

Ik heb me in die tijd wel eens afgevraagd wat het is wat me drijft al die woorden aan elkaar te rijgen. Een antwoord waar ik mee kon leven was: “Om antwoord te krijgen op de vraag: hoe doe ik het goed?” Mijn gevoel zegt me dat ik de afgelopen jaren iets dichter bij dat doel ben gekomen.

– Dus: op naar #500!

code reviews · dotkarl · filosofie · functioneel programmeren · intentie van code · refactoren · testen