Van asbestadministratie naar flexibele werkprocessen

SGI Compliance wilde Werkplanner verder ontwikkelen met een vast technisch team. We maakten de applicatie geschikt voor bodem en sloop, bouwden configureerbare formulieren en verbeterden de PDF-verwerking. Zo groeide het product mee met de processen van de bedrijven die ermee werken.

Opdrachtgever

SGI Compliance
Branche
Milieu & gezondheid
Locatie
Rotterdam

Team

Adriaan
Dries
Martijn
Remco
Roland
Ewout

De uitdaging

Een vaste ontwikkelpartner voor Werkplanner

Bij asbestsanering begint de administratie al vóór het werk op locatie. Wat wordt er gesaneerd, volgens welk plan en met welke mensen en apparatuur? Tijdens de uitvoering komen daar registraties bij. Na afloop moet de uitgevoerde sanering worden gedocumenteerd. SGI Compliance biedt daarvoor Werkplanner aan.

De ontwikkeling lag bij verschillende freelancers. Bij een wisseling moest de opdrachtgever zelf vervanging en kennisoverdracht organiseren. SGI zocht een vaste partij met meerdere Ruby on Rails-developers die de applicatie kon onderhouden en verder ontwikkelen.

Developers aan het werk op het 10KB-kantoorOverzicht van het 10KB-kantoor in de Vasim

De applicatie leren kennen terwijl we doorbouwen

We namen Werkplanner geleidelijk over. De developer die de applicatie al jarenlang kende, bleef tijdens de overgang betrokken en beoordeelde onze Woordenboek · In het kortpull requestEen pull request is een voorstel om wijzigingen uit een branch te beoordelen en samen te voegen met een andere branch. Teamleden kunnen de code bespreken en controleren voordat deze wordt opgenomen.Lees meer. De geautomatiseerde tests die al aanwezig waren, hielpen ons bestaande functionaliteit te controleren. Zo leerden we de code en de processen kennen aan de hand van het werk dat moest gebeuren.

Werkplanner was ingericht voor asbestsanering. SGI wilde de applicatie ook voor bodem- en sloopprojecten gebruiken. Bovendien werken saneringsbedrijven niet allemaal op dezelfde manier. De applicatie moest daarom verschillende projecttypen, formulieren en werkprocessen ondersteunen.

Onze aanpak

Van vaste formulieren naar eigen werkprocessen

De formulieren in Werkplanner waren aanvankelijk hard-coded. Voor een multi-tenantapplicatie, waarin verschillende bedrijven ieder hun eigen omgeving gebruiken, werd dat te beperkt. De ene saneerder gebruikt andere checklists en registraties dan de andere.

We bouwden een form builder waarmee een beheerder zelf formulieren samenstelt. Tekstvelden, keuzelijsten, checklists en handtekeningvelden vormen de bouwblokken. Per veld kan de beheerder labels, keuzemogelijkheden en validaties instellen. Met drag-and-drop verandert de volgorde. Zo kan een bedrijf het formulier op de eigen werkwijze afstemmen.

Developers overleggen op het 10KB-kantoorDevelopers bekijken samen de software op een scherm

Van bezoekersregistratie naar projectdocument

Een praktisch voorbeeld is een bezoeker op de bouwplaats. De beheerder stelt een formulier samen met contactgegevens, veiligheidsverklaringen en een handtekeningveld. De voorman kan dat formulier op een tablet laten invullen. Na het indienen wordt de registratie als PDF bij het betreffende project opgeslagen.

Daarvoor hebben we de velden als generieke bouwblokken opgezet. Elk veld heeft zowel een kant voor de beheerder, die het formulier configureert, als een kant voor de gebruiker, die het invult. De configuratie bepaalt zo welk formulier op locatie verschijnt. Het bedrijf hoeft zich niet langer te beperken tot de formulieren die vooraf in de applicatie zijn geprogrammeerd.

Collega’s overleggen op kantoor

Hergebruiken wat projecttypen gemeen hebben

Ook voor de uitbreiding naar bodem en sloop maakten we onderdelen van de software herbruikbaar. We bekeken steeds wat projecttypen werkelijk gemeen hebben, wat specifiek is en welke bestaande asbestlogica voorlopig kon blijven zoals die was. We wilden niet alles maximaal generaliseren: een universele structuur voor willekeurige projecteigenschappen zou juist nieuwe complexiteit toevoegen.

De werkplannen kregen eveneens meer ruimte voor verschillen. Per bedrijf en projecttype kan worden ingesteld uit welke hoofdstukken een werkplan bestaat. Met een Word-template kan het document in de eigen huisstijl worden gegenereerd. Dat past bijvoorbeeld bij sloopprojecten, waar een werkplan een vrijere vorm kan hebben.

Wat dit oplevert

SGI kan met Werkplanner naast asbestsanering ook bodem- en sloopprojecten ondersteunen. Aangesloten bedrijven kunnen hun eigen formulieren configureren en hun werkplannen op hun processen afstemmen. Wat op locatie wordt ingevuld, krijgt een plek in de projectdocumentatie.

We hebben de bestaande applicatie geschikt gemaakt voor verschillende toepassingen en de verantwoordelijkheid voor ontwikkeling en kennisoverdracht binnen ons team ondergebracht.

Esther Radder, destijds productmanager Werkplanner bij SGI Compliance Nederland, verwoordde onze samenwerking zo:

Denken echt mee en ontwikkelen niet zomaar wat er gevraagd wordt.

Esther Radder

Techniek die het verschil maakt

PDF’s betrouwbaar genereren

Ingevulde formulieren worden als PDF bij het project opgeslagen. Daarvoor startten we vanuit background jobs headless Chrome. Die browser renderde de HTML en CSS en printte het resultaat naar PDF.

Dat werkte niet betrouwbaar genoeg. We kregen regelmatig meldingen dat een PDF nog niet tussen de documenten stond en moesten uitzoeken waar de conversie was blijven hangen. Bovendien gebruikte Chrome veel resources. Omdat de applicatie en background jobs dezelfde server deelden, kon de PDF-rendering de webapplicatie in de weg zitten.

Code op een beeldscherm in het 10KB-kantoor

De rendering buiten de applicatie plaatsen

We hebben de conversie verplaatst naar een externe HTML-to-PDF-dienst. Een background job stuurt de HTML naar de dienst en krijgt een PDF terug. Voor de gebruiker bleef de werkwijze gelijk; wij hoefden de browserprocessen voor het renderen niet meer zelf te onderhouden.

Daarmee verdween vrijwel al het onderhoud aan die browserinfrastructuur. Waar we eerder regelmatig vastgelopen conversies moesten onderzoeken, vraagt de huidige oplossing nog incidenteel om ingrijpen. Het genereren van documenten blijft wel een proces dat we moeten bewaken.

Een tweede provider als uitwijkmogelijkheid

Bij de keuze voor een provider speelden zowel betrouwbaarheid als kosten mee. Veel formulieren worden aan het begin van de werkdag verwerkt. Betalen per document zou bij dat gebruik kostbaar worden. We kozen daarom een dienst met een vast prijsmodel, maar die bleek niet altijd de betrouwbaarste optie. We voegden een tweede, duurdere provider toe als fallback.

De background jobs kunnen een mislukte conversie opnieuw proberen. Loopt de Woordenboek · In het kortmessage queueEen message queue is een wachtrij waarin een softwaresysteem berichten tijdelijk opslaat totdat een ander onderdeel ze verwerkt. De verzender hoeft daarbij niet te wachten tot de ontvanger klaar is.Lees meer te ver op, dan krijgen we een melding in Slack. We onderzoeken de oorzaak en kunnen bij een storing van de primaire provider via een Woordenboek · In het kortfeature flagEen feature flag is een instelling waarmee software een functie aan- of uitzet zonder dat daarvoor opnieuw code hoeft te worden uitgerold. De instelling kan gelden voor alle gebruikers of voor een bepaalde groep.Lees meer overschakelen naar de andere dienst.

Dat omschakelen hebben we bewust niet volledig geautomatiseerd. De situatie komt weinig voor, waardoor we weinig praktijkgegevens hebben om betrouwbare automatische beslisregels op te baseren. Vooralsnog kiezen we voor automatische retries en signalering, met een developer die de oorzaak beoordeelt en zo nodig ingrijpt.

Dit sluit aan op een bredere les uit Werkplanner: technische foutmeldingen vertellen niet het hele verhaal. We kijken ook naar wat het product doet, zoals hoeveel werkplannen worden aangemaakt en hoeveel jobs in de wachtrij staan. Een applicatie kan bereikbaar zijn terwijl een belangrijk proces stilstaat.

Continuïteit en doorontwikkeling

Wijzigingen afzonderlijk beoordelen en opleveren

Met meer developers en gelijktijdige wijzigingen begon één gedeelde stagingomgeving te knellen. Een grote feature die nog niet was goedgekeurd, kon kleinere, afgeronde wijzigingen tegenhouden. Woordenboek · In het kortreleaseEen release is een herkenbare versie van software die is klaargemaakt om beschikbaar te stellen aan gebruikers. Zo'n versie bundelt een of meer gecontroleerde wijzigingen.Lees meer werden daardoor steeds grotere pakketten.

We introduceerden Review Apps: een eigen Woordenboek · In het kortdeploymentEen deployment is het proces waarmee een gekozen versie van software in een doelomgeving wordt geïnstalleerd en gestart, zodat die daar getest of gebruikt kan worden.Lees meer per Woordenboek · In het kortbranchEen branch is een afzonderlijke ontwikkellijn binnen versiebeheer. Developers kunnen daarin wijzigingen maken en testen zonder de hoofdversie van de code direct aan te passen.Lees meer, met testgegevens, waarin een wijziging afzonderlijk kan worden beoordeeld. Na goedkeuring kan die verder naar productie. In onze CI-pipeline draaien tests en Woordenboek · In het kortlintingLinting is het automatisch controleren van broncode op mogelijke fouten en afwijkingen van afgesproken coderegels, zonder de applicatie uit te voeren. De tool die deze controle doet, heet een linter.Lees meer automatisch en voeren we de deployments uit. Zo kunnen we doorbouwen zonder voor iedere release te wachten op alles wat tegelijk in ontwikkeling is.

Een developer werkt aan software op het 10KB-kantoor

Reviewomgevingen die starten bij gebruik

Voor al die afzonderlijke omgevingen was ook een andere infrastructuur nodig. Meerdere Rails-applicaties permanent naast elkaar laten draaien vraagt veel geheugen, ook als niemand ze op dat moment bekijkt.

We richtten de Review Apps daarom in met Woordenboek · In het kortcontainerEen container is een afgeschermd applicatieproces met de bestanden en instellingen die het nodig heeft. Containers op dezelfde machine delen doorgaans de kernel van het besturingssysteem.Lees meer op Kubernetes en Knative. Een request naar de hostnaam kan de bijbehorende applicatie starten. Na een periode zonder gebruik schaalt die terug naar nul instanties. Zo houden we afzonderlijke reviewomgevingen beschikbaar zonder alle Rails-processen permanent actief te houden.

Review Apps nemen inhoudelijke afhankelijkheden tussen features niet weg. Ze voorkomen wel dat één gedeelde testomgeving de beoordeling van alle wijzigingen aan elkaar koppelt.

Dicht bij de Rails-standaarden blijven

Langdurig onderhoud vraagt ook om keuzes in de applicatie zelf. Voor de interactieve form builder gebruikten we destijds losse Woordenboek · In het kortcomponentEen component is een afgebakend onderdeel van software met een eigen taak en een duidelijke manier om met andere onderdelen samen te werken.Lees meer binnen Rails. Daarmee konden we de gewenste Woordenboek · In het kortuser experienceUser experience, vaak afgekort tot UX, is de totale ervaring die iemand heeft tijdens het gebruiken van een product, systeem of dienst.Lees meer bouwen; Rails bood daar toen voor ons nog geen passende standaardoplossing voor.

De losse frontendlaag brengt inmiddels extra onderhoud en migratiewerk mee. Daarom brengen we onderdelen stapsgewijs over naar Hotwire en Stimulus, dichter bij de huidige Rails-manier van werken. Die modernisering loopt nog. We kiezen bewust enigszins conservatief: bij software die we jarenlang onderhouden, willen we toekomstige upgrades kunnen volgen en het aantal los aangebouwde technische lagen beperken.

Collega’s stemmen hun werk af aan tafel

Kennis en verantwoordelijkheid bij het team

We zorgen dat meerdere developers Werkplanner kennen en dat een collega het werk bij afwezigheid kan overnemen. Een Dev Container legt de lokale ontwikkelomgeving vast, zodat iemand het project kan uitchecken en aan de slag kan. We werken nieuwe teamleden intern in en verdelen de kennis tijdens het bouwen.

In de wekelijkse afstemming met SGI sluiten onze developers zelf aan. We bespreken prioriteiten, werken tickets uit en adviseren over technische oplossingsrichtingen. Zo horen doorontwikkeling, onderhoud en technische keuzes bij dezelfde samenwerking.

Wat we meenemen

Wat we van Werkplanner leren

Werkplanner laat zien hoe productuitbreiding, beheer en technische keuzes elkaar beïnvloeden. Drie afwegingen die we meenemen naar volgende projecten.

  1. Hergebruik wat werkelijk gedeeld is

    Bij Werkplanner maakten we ruimte voor verschillende projecttypen en configureerbare formulieren. We maakten gedeelde onderdelen herbruikbaar en lieten specifieke logica bestaan waar die nodig was.

    Bij volgende projecten

    We onderzoeken welke verschillen bij het product horen en welke onderdelen een gedeelde basis kunnen krijgen. Zo bepalen we waar abstraheren helpt en waar het extra complexiteit toevoegt.

  2. Uitbesteden vraagt een uitwijkroute

    Externe PDF-rendering nam het browseronderhoud weg, maar bracht afhankelijkheid van een provider mee. We voegden een tweede provider toe, met automatische retries en een bewuste handmatige omschakeling.

    Bij volgende projecten

    We wegen bij een externe dienst ook de kosten, storingen en herstelmogelijkheden mee. Wat we automatiseren, hangt af van de praktijk en de gegevens waarop we een beslissing kunnen baseren.

  3. Neem onderhoud mee in de keuze

    Vue maakte de interactieve form builder mogelijk. Later bracht die afzonderlijke frontendlaag extra migratiewerk mee. We bewegen daarom met onderdelen terug naar de Rails-standaarden.

    Bij volgende projecten

    We kijken zowel naar wat een techniek nu mogelijk maakt als naar de aansluiting op het ecosysteem dat we jarenlang moeten onderhouden.

Ewout

Contactpersoon: Ewout

Samen verder bouwen?

Moet jouw software blijven draaien terwijl je verder bouwt? Vertel ons waar de ontwikkeling vastloopt en welke uitbreiding je wilt bereiken. We denken mee over de technische basis en een passende samenwerking.

CONTACT

Neem contact met ons op

Heb je een vraag of wil je sparren over je software? Laat je gegevens achter, dan nemen we snel contact met je op.