Origineel: Cheating faster development by doing everything wrong
Een praktijkvoorbeeld van een team dat testen, releaseplanningen en code reviews oversloeg, maar toch succesvolle producten leverde door snelle iteraties en nauwe samenwerking met gebruikers.
De meeste softwareteams waar ik mee heb gewerkt beweren een of andere agile methodologie te volgen. Deze methodologieën richten zich meestal op twee dingen: kwaliteitsborging en planning. Hoewel deze praktijken tot robuuste systemen kunnen leiden, kosten ze veel tijd en middelen. Dat zijn luxes die kleine teams en startups vaak niet hebben. Toch is er een ongebruikelijk pad dat verrassend goed kan werken.
Ik werkte met een klein team dat de meeste traditionele methodologieën negeerde en toch succesvolle producten opleverde. Ze deden vrijwel geen testen, geen releaseplanningen, geen featureplanningen, en geen samenwerking. Elk van deze punten klinkt onprofessioneel, maar het stelde het team in staat om een product te leveren dat goed ontvangen werd door hun gebruikers en het bedrijf hielp groeien.
Dit team besteedde nauwelijks middelen aan testen. Er waren wat unit tests voor de meer abstracte delen van de code, maar er waren geen integratietests, geen acceptatietests, en geen end-to-end tests. Er was zelfs geen testomgeving buiten de laptops van de ontwikkelaars. Als een feature of bugfix werkte op de machine van de ontwikkelaar, werd er niet verder getest.
Als ontwikkelaars testen overslaan, worden je gebruikers je testers. Dit vereist een manier voor gebruikers om snel en gemakkelijk feedback te geven. De ontwikkelaars moeten direct op deze feedback kunnen reageren.
Dit werkt het beste als de gebruikers geen betalende klanten zijn, aangezien gebruikers tijd moeten vrijmaken om feedback te geven. In dit team waren de gebruikers medewerkers van het bedrijf, en van hen werd verwacht dat ze feedback gaven op de software die ze gebruikten. Ze deelden een kantoor met hun ontwikkelaars, dus ze konden direct feedback geven of om hulp vragen. Gebruikers raakten typisch diep betrokken bij het ontwikkelproces en hadden een gevoel van eigenaarschap over het product waar ze op vertrouwden.
In scrum zijn cycli van meerdere weken de norm, wat vaak de minimale iteratietijd dicteert. Dit team richtte zich op snelle iteratie. Ze brachten nieuwe features uit zodra ze klaar waren, en ze losten bugs op zodra ze gemeld werden. Dit betekende soms dat ze meerdere keren per dag konden itereren.
Om dit te bereiken sprak het team af om zo snel mogelijk naar een minimum viable product te werken, en dan een productierelease te doen. Dit betekende dat ze releaseden zodra hun werk enige waarde bood aan de gebruiker. Op die manier kon het verdere polijsten van die feature rekening houden met de feedback van gebruikers.
Een klein team moet featureverzoeken kunnen afwijzen, anders zouden ze vastlopen in grote featureverzoeken die misschien niet zoveel waarde opleveren als meerdere kleinere features samen. Wanneer een featureverzoek werd afgewezen, hielp het team de gebruiker om een workaround te vinden. Vaak hielp het ontwikkelteam mee met brainstormen over manieren om bedrijfsprocessen aan te passen. Ze traden op als bedrijfsconsultants bovenop hun rol als ontwikkelaar.
Veel traditionele methodologieën gebruiken een backlog voor langetermijnplanning, maar dit team deed dat niet. Ze begonnen gewoon te werken aan welke feature het bedrijf op dat moment nodig had. De teamleider besprak regelmatig met de bedrijfseigenaren wat volgens hen de meeste waarde zou opleveren. In dit gesprek schatte de teamleider de hoeveelheid werk en het risico in. Daarna kwamen de teamleider en bedrijfseigenaren tot overeenstemming over een goede balans tussen inspanning, risico, en waarde.
Featureverzoeken waar niet actief aan gewerkt werd, werden niet bijgehouden. De gebruikers hadden een soort wensenlijstje dat ze aan de bedrijfseigenaren communiceerden.
Dit team werkte niet veel samen aan features. Ze werkten gewoon aan hun eigen feature, mergeden hun code, en deployen dan. Ze deden niet aan pair programming, ze deden geen code reviews, en ze deden geen sprintplanning. Hoewel er een wekelijkse vergadering was om voortgang te bespreken, was die vergadering vooral een sociaal gebeuren. Er werd weinig echt werk in die vergadering gedaan.
Dat wil niet zeggen dat ze niet communiceerden. Ze vroegen elkaar vaak om hulp, en ze bespraken vaak de beste manier om een feature te implementeren. Ze vroegen features van elkaar aan op basis van hun expertise, en ze hielpen elkaar vaak als ze vastzaten. Maar uiteindelijk nam elke ontwikkelaar verantwoordelijkheid voor zijn eigen werk, en droeg het van ticket tot uiteindelijke deployment.
Natuurlijk komt deze manier van werken niet gratis. Om dit te laten werken moeten een paar randvoorwaarden aanwezig zijn.
Het team moet goed kunnen communiceren, zowel intern als met gebruikers. Teamleden moeten zelfstandig kunnen werken, maar ze moeten ook om hulp kunnen vragen wanneer dat nodig is. Bovenal moeten de teamleden goed met kritiek kunnen omgaan, want deze manier van werken leidt vaak tot veel negatieve feedback.
Dit team was geen team van “rocksterren”. Behalve de teamleider begonnen alle ontwikkelaars als juniors, terwijl ze nog op de universiteit zaten. Junior ontwikkelaars kregen dezelfde soort taken als meer ervaren ontwikkelaars (behalve tijdens het inwerken), en van hen werd verwacht dat ze dezelfde kwaliteit werk leverden. Dit gaf hen de kans om hun vaardigheden snel te ontwikkelen. Hoewel ze als juniors begonnen, groeiden alle ontwikkelaars in relatief korte tijd voorbij het juniorniveau.
De teamleider was een zeer ervaren ontwikkelaar, met meer dan 20 jaar ervaring in verschillende IT-rollen. Zijn rol was vooral om het team te faciliteren en ervoor te zorgen dat het team kon blijven doorwerken. Hij pakte ook bijzonder uitdagende, gevoelige of urgente features op, hij refactorde vaak code om deze beter onderhoudbaar te maken, en hij zorgde ervoor dat hij zoveel mogelijk obstakels uit de weg ruimde.
Deze manier van werken leidt tot veel technische schuld. Een startup kan de technische schuld uitstellen tot er VC-geld binnenkomt, maar andere teams zullen dit regelmatig moeten aanpakken. In dit team werd technische schuld vooral door de teamleider aangepakt. Hij refactorde vaak code en ruimde code op die niet meer gebruikt werd. Veelvoorkomende patronen werden gerefactord naar library-functies, en die kregen unit tests. Op die manier was er een sterke kernbibliotheek waar het team op kon bouwen.
Snel itereren vereist snelle deployments. Dit team had een continuous integration pipeline. Een merge request stond binnen ongeveer 5 minuten in productie. De daadwerkelijke deployment naar productie was handmatig, maar gemakkelijk en snel. Dit stelde ontwikkelaars in staat om meerdere iteraties op een dag te doen, en gaf gebruikers het vertrouwen dat problemen die hun werkstroom blokkeerden snel genoeg opgelost konden worden om op te wachten.
De CI bestond vooral uit static analysis tools, en de editors van de teamleden waren meestal geconfigureerd om dezelfde statische analyse te doen. Hoewel statische analyse geen alternatief is voor testen, kan het helpen om problemen vroeg te ontdekken.
Gebruikers waren meestal pas de tweede bron van feedback. Tegen de tijd dat de gebruiker had uitgezocht dat de feature niet werkte zoals verwacht, had de ontwikkelaar dit waarschijnlijk al in de rapportages gezien. Dit team gebruikte Sentry en Prometheus om hun applicaties te monitoren. Ze kregen alerts wanneer er iets misging, en ze konden snel op problemen reageren.
De code bevatte behoorlijk wat logging, metrics, en assertions. Op deze manier konden de ontwikkelaars snel zien wat er aan de hand was, en konden ze problemen snel oplossen.
Deze snelle iteraties hebben een aanzienlijke impact op de agenda van de gebruiker. Ze moeten een niet-triviale hoeveelheid tijd reserveren om de feedback te geven die de ontwikkelcyclus aandrijft. Het hielp enorm dat gebruikers en ontwikkelaars een kantoor deelden. De gebruikers konden gewoon naar de ontwikkelaars lopen om een feature te bespreken, en de ontwikkelaars konden gewoon naar de gebruikers lopen om feedback te vragen.
Frequente backups en goede tools om die te benaderen zijn cruciaal, vanwege het verhoogde risico op bugs die dataverlies veroorzaken. Een backupprocedure die langdurige diff-reconstructie vereist is echt niet geschikt. Hoewel backups niet zo vaak geraadpleegd werden, maakte hun handige formaat (SQL dumps en gewone bestandskopieën) het mogelijk voor een ontwikkelaar om snel dataverlies te herstellen dat door bugs was veroorzaakt.
Natuurlijk heeft het breken van alle regels zijn nadelen. Deze manier van werken is niet voor iedereen, en heeft een aantal significante keerzijdes.
De snelle releasecyclus betekende dat ontwikkelaars snel en vaak van taak moesten wisselen. Niet iedereen is comfortabel met het frequente taakwisselen dat bij deze werkstijl hoort. Het bedrijf en de teamleider zorgden ervoor dat andere bronnen van stress (zoals werkomgeving en deadlines) geminimaliseerd werden.
Deze manier van werken heeft een diepgaande impact op het bedrijf. Het bedrijf moet niet alleen gebruikerstijd kunnen vrijmaken voor feedback, maar ze moeten ook downtime kunnen accepteren. De bedrijfseigenaren vonden dit acceptabel, omdat ze vonden dat de voordelen van het snelle ontwikkeltempo opwogen tegen de andere kosten. De aard van het bedrijf stond een uptime van onder de 99% toe, veel minder dan veel andere bedrijven zouden accepteren. Dit bedrijf had geen speciale certificeringen waar ze aan moesten voldoen, dus ze konden zich dit risico veroorloven.
Deze manier van werken is erg gericht op de korte termijn. Het team was niet in staat om features te leveren die meer dan een paar maanden werk zouden kosten voordat ze waarde opleverden. Dit betekende dat ze erg voorzichtig moesten zijn met grote features, en vaak zochten naar omwegen in de ontwikkelcyclus om gebruikers eerder te betrekken.
De code die met deze ontwikkelmethode geproduceerd wordt bevat waarschijnlijk meer beveiligingsproblemen, wat het minder geschikt maakt voor code die aan het internet wordt blootgesteld. Dit risico kan verminderd worden door frameworks te gebruiken die veelvoorkomende beveiligingsproblemen voorkomen, een heuristische web application firewall, en een “riem-en-bretels” ontwikkelhouding. In dit team had de lead developer aanzienlijke cybersecurity-expertise, waardoor hij defensieve maatregelen kon inbouwen in de kern van de applicatie. Een enkele kwetsbaarheid was daardoor normaal niet genoeg om de hele applicatie te exploiteren.
Dit artikel beschreef eigenlijk gewoon lean development. Maar dit lezen in een boek is heel anders dan het doen. Ik heb bedrijven gezien die op papier aan lean development doen, maar in dit team zag ik het daadwerkelijk in de praktijk.
Lean software development is niet voor iedereen. Het past alleen bij een bedrijf waar de gebruikers en de ontwikkelaars nauw contact hebben, en waar het bedrijf het snelle ontwikkeltempo kan ondersteunen, inclusief het vallen en opstaan. Maar als je het kunt laten werken, kan het een zeer effectieve manier van werken zijn, en zal het je ontwikkelsnelheid aanzienlijk versnellen.
Terug naar overzicht