# Shoprockets weg naar microservices, deel 1: wat ik fout deed bij het opknippen van de monoliet

> Een engineeringpost uit de beginjaren van Shoprocket over de eerste poging om een service uit een PHP-monoliet te halen. Waarom ik de verkeerde eerste service koos, wat sterke koppeling me leerde en het advies van Newman dat ik eerder had moeten opvolgen.

Winston Berty  - 17 maart 2016 - 5 min leestijd

Een paar maanden na mijn start bij Shoprocket begon ik gefrustreerd te raken. We hadden een PHP-applicatie waaraan een klein team scherpe developers verspreid over de hele wereld werkte, en mij leek het dat bugfixes nieuwe bugs opleverden, nieuwe features integreren niet zo simpel was als het hoorde te zijn en deployments zeldzaam en stressvol waren. De oorzaak: sterk gekoppelde code.

We hadden een monolithische applicatie, bijna helemaal in één GitHub-repository. Updates of fixes voor één feature vroegen vaak om wijzigingen op meerdere plekken. Voor het testen hadden we een peer-reviewproces waarbij minstens twee andere developers een branch moesten goedkeuren voordat die in master werd gemerged en uitgerold. Het gevolg was dat het vaak lastig was om de brekende wijziging te vinden als er een bug doorheen glipte. Zodra we hem hadden, doorliep de fix hetzelfde proces en moest de hele applicatie opnieuw worden uitgerold.

Als enthousiaste jonge developer die altijd op zoek is naar het nieuwste, dacht ik bij het ontdekken van microservices dat dit al onze problemen ging oplossen.

## Wat ik dacht dat microservices waren

Er bestaat geen formele definitie van microservices, maar uit mijn onderzoek haalde ik dat een microservice-architectuur een manier is om software te ontwerpen als een gedistribueerd systeem van onafhankelijke services, elk sterk gespecialiseerd en met een eigen levenscyclus. Voor een uitgebreide introductie is het [artikel](https://martinfowler.com/articles/microservices.html) van Martin Fowler uitstekend.

Twee aspecten wonnen me voor het idee. Ten eerste het opdelen van de applicatie in services met strikte grenzen. Dat verkleint de kans dat logica die bij één bedrijfscontext hoort naar andere componenten lekt, omdat de interfaces tussen die grenzen zorgvuldig moeten worden uitgedacht. Het is niet zo simpel als lokale functieaanroepen doen. Ten tweede kan elk component een eigen, onafhankelijke levenscyclus hebben. Teams kunnen hun code bezitten en een stack gebruiken die het best bij de service past, en wijzigingen kunnen per service worden uitgerold en teruggedraaid zonder de rest te raken.

Ik was om. Shoprocket ging de monoliet opknippen. Dit is deel 1 van een korte serie over die reis. Mijn hoop is dat lezers die een vergelijkbare overgang plannen of doormaken leren van onze successen en fouten.

## De eerste uitdaging was menselijk, niet technisch

Ik moest het idee verkopen aan de rest van het team. Ze waren nieuwsgierig maar deelden mijn enthousiasme niet, en ze wilden in dit vroege stadium van het product niet graag ontwikkeluren opgeven. Gelukkig wilde de CTO dat ik naar ons sessiebeheer keek, dus greep ik mijn kans: ik overtuigde hem dat ik een sessieservice kon afsplitsen.

Achteraf was dit een slechte keuze voor een eerste service. Ons product bevat een JavaScript-widget die [ecommerce mogelijk maakt op elke website](https://v3.shoprocket.io/nl/functies/verkopen-op-elke-website.md). We behandelen sessies als een resource en bewaren sessiegegevens in de database om verlaten winkelwagens en andere KPI's te analyseren. Maar die resource is minder tastbaar dan bijvoorbeeld bestellingen of orderregels, en we gebruikten sessies bij bijna elke wijziging van de applicatiestatus. Dat betekende dat de service onvermijdelijk veel zou praten met de rest van de applicatie, iets wat ik niet voorzag en wat mijn taak zwaarder maakte.

## Wat ik leerde van het echt bouwen

Ik verdiepte me verder. Naast Fowler bleek **Building Microservices** van Sam Newman een onmisbare bron.

Newmans advies was, achteraf gezien, het advies dat ik had moeten opvolgen: herstructureer eerst de bestaande applicatie in modules die de bounded contexts van het domein weerspiegelen. Zijn de developers tevreden over de grenzen, splits de modules *dan* af in eigen services. De reden is dat het veel makkelijker is om modules met slechte grenzen op te knippen en te herschrijven dan hele services met alle extra infrastructuurcode en persistente resources.

Dat advies volgde ik niet. Gretig om een eigen component te bouwen ging ik door met de sessieservice.

Ik koos een stack die maar licht afweek van die van de monoliet en begon te bouwen. De service zelf was snel klaar: in een paar weken had ik een zelfstandige applicatie met een REST-API. Daar zat het moeilijke deel niet. Het moeilijke was de service laten praten met de monoliet.

Sessiebeheer bleek sterk verweven met de rest van de codebase. Functieaanroepen vervangen door API-aanroepen was traag werk. Omdat de sessieservice en de monoliet aparte databaseschema's hadden, moest ik alle logica in de monoliet die sessieresources uit de oude database gebruikte herschrijven en de data aan de applicatiegrens herstructureren, zodat clients zoals onze JavaScript-widget compatibel bleven.

Integreren duurde langer dan bouwen. En dat was nog zonder het grootste deel van de overhead die microservices normaal meebrengen: service discovery, logging, monitoring, distributed tracing. Erger nog, door de sterke koppeling verspreidden wijzigingen zich over veel delen van de code. Omdat het team in die tijd parallel was doorgegaan, zou het mergen en in productie nemen van de sessieservice veel meer afstemming vragen dan ik had ingeschat.

## De eerlijke balans

De service gaat misschien binnenkort in productie. Maar ik vind nu dat ik Newmans advies had moeten opvolgen en mijn energie eerst had moeten steken in het modulariseren van de bestaande applicatie. Het voordeel van één service die op zichzelf staat is marginaal. Het echte voordeel komt van het opknippen van het geheel, minstens in grofmazige services die zo min mogelijk met elkaar praten. Daarvoor heb je goed doordachte componentgrenzen nodig, en daar waren we nog niet.

Ik geloof nog steeds in microservices als idee. Ik zie mijn poging als een nuttig experiment. Ik leerde enorm veel over applicatiearchitectuur, domeinmodellering en REST-principes, en die lessen hadden doorwerking in andere delen van onze code.

Voor iedereen die een vergelijkbare overgang overweegt, mijn eerlijke aanbevelingen:

- Lees zoveel mogelijk over het onderwerp voordat je je vastlegt
- Stel het werk uit tot je echt vertrouwd bent met je bestaande codebase en je domeinmodel
- Bedenk dat er andere manieren zijn om stabiliteit en veerkracht in een monoliet te brengen. Geautomatiseerde unit- en functionele tests helpen enorm. Test-driven development vermindert regressies. Horizontaal schalen maakt deployments minder pijnlijk
- Begin met het modulariseren van je monoliet voordat je services afsplitst

Shoprocket gaat door op zijn reis. In deel 2 wordt het interessanter.

---

*Oorspronkelijk gepubliceerd als eerste in een korte serie die de vroege migratie van Shoprocket weg van een PHP-monoliet beschrijft. De hele reis, inclusief de fouten die in latere iteraties zijn hersteld, is sindsdien doorgegaan met elke grote herschrijving van het platform.*

---

- HTML version: https://v3.shoprocket.io/nl/blog/shoprocket-microservices-deel-1-monoliet-opknippen
- Language: Nederlands (nl)
- Also in: [العربية](https://v3.shoprocket.io/ar/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Deutsch](https://v3.shoprocket.io/de/blog/shoprocket-microservices-teil-1-monolith-zerlegen-fehler.md), [Ελληνικά](https://v3.shoprocket.io/el/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [English](https://v3.shoprocket.io/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Español](https://v3.shoprocket.io/es/blog/shoprocket-microservicios-parte-1-lo-que-hice-mal-monolito.md), [Français](https://v3.shoprocket.io/fr/blog/shoprocket-vers-les-microservices-partie-1-decouper-le-monolithe.md), [עברית](https://v3.shoprocket.io/he/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [हिन्दी](https://v3.shoprocket.io/hi/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Bahasa Indonesia](https://v3.shoprocket.io/id/blog/perjalanan-shoprocket-menuju-microservices-bagian-1-salah-memecah-monolit.md), [Italiano](https://v3.shoprocket.io/it/blog/viaggio-di-shoprocket-verso-i-microservizi-parte-1-cosa-ho-sbagliato-sul-monolite.md), [日本語](https://v3.shoprocket.io/ja/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Lietuvių](https://v3.shoprocket.io/lt/tinklarastis/shoprocket-kelione-i-mikropaslaugas-1-dalis.md), [Norsk](https://v3.shoprocket.io/nb/blogg/shoprockets-vei-mot-mikrotjenester-del-1-hva-jeg-tok-feil-av.md), [Polski](https://v3.shoprocket.io/pl/blog/droga-shoprocket-do-mikroserwisow-czesc-1-rozbijanie-monolitu.md), [Português](https://v3.shoprocket.io/pt/blog/jornada-do-shoprocket-para-microsservicos-parte-1-o-que-errei-ao-quebrar-o-monolito.md), [Română](https://v3.shoprocket.io/ro/blog/drumul-shoprocket-spre-microservicii-partea-1-ce-am-gresit-cu-monolitul.md), [Русский](https://v3.shoprocket.io/ru/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [ไทย](https://v3.shoprocket.io/th/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Türkçe](https://v3.shoprocket.io/tr/blog/shoprocket-mikroservis-yolculugu-1-monoliti-parcalarken-yanlis-yaptiklarim.md), [中文](https://v3.shoprocket.io/zh/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md)
