Koppeling buiten code om
Koppeling is: wanneer een wijziging in het ene (sub)systeem een wijziging in het andere (sub)systeem noodzakelijk maakt.1 Wanneer softwareontwikkelaars het over koppeling hebben, dan bedoelen we meestal: in code aan elkaar gekoppelde (sub)systemen.
Vlad Khononov beschrijft in Balancing Coupling in Software Design verschillende manieren waarop systemen aan elkaar gekoppeld kunnen zijn. Met name zijn taxonomie van integratiesterkte (zie ook deze blog) is de moeite van het bestuderen waard. Koppeling is geen kwestie van alles of niets. Systemen kunnen in sterke en minder sterke mate van elkaar afhankelijk zijn.
Systeem A en B kunnen aan elkaar gekoppeld zijn omdat B gebruik maakt van implementatiedetails van A waar de buitenwereld nooit weet van had mogen hebben. Maar B kan ook gebruik maken van het interne model van A, of van een naar de buitenwereld toe afgesproken integratiecontract. De eerste soort koppeling is sterker dan de tweede, en de tweede is sterker dan de derde. Koppeling beslaat een spectrum van intrusief naar functioneel naar contractmatig.
Functioneel
Wat impliciet blijft in deze bespreking is het gegeven dat al deze voorbeelden uitgaan van aan elkaar gekoppelde code. Maar Khononov wijst erop – en dat is wat in de discussie rondom koppeling vaak over het hoofd wordt gezien – dat twee (sub)systemen ook zuiver functioneel aan elkaar gekoppeld kunnen zijn, zonder ook maar één regel code te hoeven delen.
Als systemen, onafhankelijk van elkaar, dezelfde businesslogica implementeren, dan zijn ze aan elkaar gekoppeld. Immers, wil het systeem als geheel – de totaliteit van met elkaar communicerende systemen – blijven werken, dan moeten alle relevante (sub)systemen dezelfde regels hanteren.
Laten we als voorbeeld twee microservices nemen, OrderService
en BillingService
. Als de OrderService
meent dat een klant korting krijgt bij besteding van €50,-, maar de BillingService
meent dat dat pas vanaf €75,- geldt, dan is de logica van het systeem geheel inconsistent. Beide systemen werken individueel “correct”, maar in hun samenwerking manifesteert zich een bug. De gebruiker van de microservices weet niet waar deze aan toe is.
Communicatiesystemen
Die observatie vertelt ons iets over de aard van koppeling. Koppeling is geen codeprobleem maar een communicatieprobleem. Problemen in communicatie kunnen niet alleen ontstaan in de inhoud van de berichten die systemen over en weer sturen, maar ook in de context waarin die berichten begrepen worden. De Order
- en de BillingService
zijn het er beide over eens dat er een bestelling is geplaatst voor €50,- – maar de eerste begrijpt dat in een context waarbinnen dat bedrag korting impliceert, en de tweede niet.
En dat vertelt op zijn beurt weer iets over de aard van het werk van een softwareontwikkelaar. Het is niet de taak van een ontwikkelaar om code te schrijven en te begrijpen, maar om systemen te ontwikkelen en te begrijpen. Natuurlijk, die systemen worden door ons gecodeerd – maar wie de code aanziet voor het systeem, ziet de kaart aan voor het landschap.
Bovendien, de systemen die we coderen zijn slechts een onderdeel van de bredere (organisatorische) systemen waarbinnen ze functioneren. Het feit dat software door mensen gebruikt worden om bepaalde doelen te bereiken is net zo belangrijk om haar te kunnen duiden als het begrip van de systemen (c.q. code) zelf. – En zo loopt koppeling naadloos over in systeemdenken.2
Deze definitie, ontleend aan Kent Becks Tidy First?, legt nadruk op de veranderlijke aard van software, en beziet het fenomeen vanuit dat gegeven. Er zijn ook “statische” definities mogelijk, waarbij de nadruk veel meer komt te liggen op het feit dat systemen met elkaar communiceren. Wat mij bevalt aan Becks definitie is dat het onderkent dat softwaresystemen dynamische, veranderende entiteiten zijn (zie ook deze blog). ↩︎
Op het moment van schrijven lees ik Diana Montalions Learning Systems Thinking – ook al een aanrader! ↩︎
aannames · boeken · communicatie · koppeling · microservices · software ontwikkelaar (rol)