Vincent van Beek Hoofd Software Engineering en Distinguished Engineer
29 mei 2024

Software ontwikkelen voor infrastructuur

Het idee over hoe je software ontwikkelt, is in de loop der tijd erg veranderd. Voorheen ging dit volgens de watervalmethodiek, waarbij trapsgewijs van de ene fase naar de andere fase werd gegaan. Daarbij startte ontwikkelaars vanuit een heel uitgebreid ontwerp waarbij pas aan het einde werd gestart met testen. Op een gegeven moment ontdekte men echter dat deze manier van software ontwikkelen nooit leidde tot iets wat een eindklant echt wilde hebben. Bovendien duurden die processen eindeloos lang.

Hieruit is de agile beweging ontstaan. Door te proberen de scope zo klein mogelijk te houden en te bedenken wat een eindklant echt wil, kan eerst een klein gedeelte gebouwd worden en daarop worden voortgebouwd. Zo ontwikkelen we tegenwoordig vanuit een eerste bouwsteen steeds complexere software. Daarbij zijn twee technieken essentieel om goed werkende software te maken. Test Driven Development (TDD) – waarbij de ontwikkelaars starten met het ontwikkelen van kleine units software – en de Behaviour Driven Development (BDD)-aanpak. Bij Behaviour Driven Development start het bij het vastleggen van de requirements in een voor stakeholders leesbare taal.

En dat is best een grote uitdaging. Als je software ontwikkelt, schrijf je dat namelijk op als logica. Alles wordt een expliciete keuze. Waar iets op het scherm moet komen te staan of waar en welke waardes in een veld ingevuld mogen worden. Door dit van tevoren duidelijk vast te stellen maakt de BDD-aanpak een betere samenwerking en communicatie mogelijk tussen alle belanghebbenden van een project.

“Het zorgt voor meer automatisering, waarbij kwaliteitsborging zoveel mogelijk naar voren wordt gehaald”

Shift-Left

De BDD-aanpak heeft ook veel impact gehad op hoe het testproces eruitziet. De ontwikkelcycli zijn korter waardoor nieuwe handvatten nodig waren om de kwaliteit te borgen. En testen is essentieel om ervoor te zorgen dat de software klopt. Want hoewel wij meer complexe software ontwikkelen voor complexe problemen, zoals het automatiseren van processen in de IT-infrastructuur, hebben mensen hetzelfde verwachtingspatroon als bij reguliere applicaties: dat het gewoon altijd werkt. Maar dat is in een complexe omgeving vaak wel wat ingewikkelder. Het blijft gewoon mensenwerk.

De BDD-aanpak maakt het mogelijk om het testproces effectief naar links te schuiven, shift-left testen. Bij deze benadering begint testen eerder in de levenscyclus van productontwikkeling. Het zorgt voor meer automatisering, waarbij kwaliteitsborging zoveel mogelijk naar voren wordt gehaald. Hierdoor worden defecten in een vroeger stadium ontdekt en verholpen door parallel met het ontwikkelingsteam te werken. Het voorkomt bovendien dataverlies en haalt ook de security en compliance naar voren. En dat is goed nieuws want hoe later in het proces er rework nodig is of er incidenten zijn, hoe duurder een traject wordt.   

Testen vindt dus niet alleen plaats aan het eind van het ontwikkelproces (unit test), maar ook tijdens het schrijven van code (code review) en op vele andere momenten in het leveringsproces. Zo zijn er onder andere integratietesten, loadtesten, acceptatietesten, testen voor specifieke gebruikersgroepen of securitytesten. Al onze code wordt bijvoorbeeld getest door Securify. Zij checken de code op security aspecten en analyseren welk stukje code het grootste risico met zich meebrengt bij een wijziging.

Taal

Het belangrijkste is dat BDD gebruikmaakt van een gemeenschappelijke taal, gebaseerd op eenvoudige en gestructureerde zinnen. Voor testen betekent dit dat zij beschrijven wat je wilt dat er als output komt, als je weet wat je er als input in stopt. Onze stakeholders zijn meestal IT-architecten. Als er een feature wordt bedacht, moeten zij snappen hoe dat getest gaat worden. Als zij die test kunnen lezen en begrijpen, kunnen zij meedenken en aangeven of dit inderdaad is wat zij willen hebben.

Daarvoor doorlopen wij heel gestructureerd verschillende stappen in projecten. Voor een klant bouwen wij bijvoorbeeld een private cloudplatform, waar twee verschillende organisatieonderdelen op dezelfde hardware in het datacenter draaien, maar virtueel strikt gescheiden moeten zijn. Om deze omgeving voor de klant te ontsluiten is een serviceportaal ontwikkeld met een standaardproduct van VMware, wat is uitgebreid met verschillende andere functionaliteiten van andere leveranciers. Via software van ons kunnen deze applicaties berichten met elkaar uitwisselen.

Om daar grip op te krijgen en om dit te kunnen testen, moet je eerst heel goed weten hoe je requirements op moet schrijven. Deze worden geschreven in een framework, want je hebt harde kaders nodig, waarin drie fases te onderscheiden zijn: business value, acceptance criteria en non functional requirements. Het opstellen van de functionele requirements start met het uitsplitsen van drie belangrijke componenten. Waarom bouw je iets, wat is de waarde en context, waarvoor bouw je iets (wat moet het doen?) en voor wie? Dat ziet er als volgt uit: Als een [functienaam], wil ik [deze feature], zodat [benefit]. 

"Want achter de functionele wereld gaat nog een hele wereld schuil"

Testen

In de volgende fase stellen we vervolgens acceptatiecriteria op hoe elke stap moet worden doorlopen. Gegeven deze situatie wil ik dat als dit gebeurt, er deze uitkomst uitkomt. Naast functionele requirements zijn er bovendien ook non-functionele requirements. Want achter de functionele wereld gaat nog een hele wereld schuil. We kijken dus heel concreet naar hoeveel impact bepaalde gebeurtenissen hebben op de performance, of er schalingsproblemen te verwachten zijn en wat een klant van ons verwacht.

Pas daarna kunnen we gaan testen. Daarin zijn in deze casus vier lagen te onderscheiden: unit tests, integratietesten, systeemtesten en endto-end testen. Gestart wordt met het testen op functieniveau, daarna kom je uit op integratieniveau want alle kleine stukjes software samen, moeten ook functioneren. Dit gaat uiteraard volledig geautomatiseerd. Na de systeemtesten komen we dan uiteindelijk uit bij de endtoend testen. En dat is waar het bij Behaviour Driven Design uiteindelijk om draait. Als je alles bij elkaar zet en met elkaar verbindt, wat moet het dan doen voor de klant?  

Naast dat je alle testen runt, moeten er nog wel meer dingen gebeuren, voordat je kunt zeggen dat een stuk functionaliteit echt af is. Daarvoor gebruiken we de Definition of Done checklist. 

Resultaat

Het voordeel van deze werkwijze ten opzichte van alleen geschreven documentatie is dat je door de tests uit te voeren, kunt checken of je documentatie klopt. Bovendien kunnen wij een stuk dashboarding en reporting teruggeven aan de klant. Als wij die hele testsuite uitrollen kunnen zij zien waar eventueel een bug is geïdentificeerd of hoe lang tests hebben geduurd. Het zorgt voor transparantie, want de essentie van testen is dat wij moeten én willen bewijzen dat wat wij hebben ontwikkeld, doet wat in de requirements staat.

Alle voorgaande stappen hebben invloed op het daadwerkelijk op te leveren eindproduct. De sleutel tot succes daarbij is dat je bij het maken en testen van software van tevoren goed checkt of je wel dezelfde taal spreekt.

Meld je aan voor de Solvinity Nieuwsbrief

Ontvang het laatste nieuws, blogs, artikelen en events.

Lees ook

Meer