Het artikel analyseert de cognitieve dissonantie rondom het concept 'abstractie' in de informatica door een essentieel onderscheid te maken tussen twee vormen:
- Modulaire abstractie: Deze vorm is gericht op inkapseling en het verbergen van interne details via interfaces en API's. Het doel is om complexiteit te maskeren en operaties atomair te presenteren, waardoor concurrency vaak wordt verborgen.
- Modelleringsabstractie: Deze vorm, veelgebruikt door wiskundigen en in formele methoden zoals TLA+, richt zich op het reduceren van een systeem tot het minimale gedragsskelet dat relevant is voor een specifieke eigenschap. In tegenstelling tot modulaire abstractie, stelt dit juist concurrency bloot om de veiligheid van interleavings te kunnen bewijzen.
De auteur illustreert modelleringsabstractie aan de hand van voorbeelden uit gedistribueerde systemen, zoals Lamport logische klokken, Consensus (Paxos), Lineariseerbaarheid en MapReduce. Hoewel beide vormen van abstractie soms in één goed ontworpen artefact samenkomen, blijven hun doelen — verbergen versus reduceren — fundamenteel verschillend.
De twee abstracties van systeemontwerp: verbergen of reduceren
Maar er is een tegenstrijdigheid die me dwarszit. Wordt er van mensen in de informatica (CS) niet al verwacht dat ze goed zijn in abstractie? Zou abstractie niet de kern moeten vormen van besturingssystemen, netwerken en software engineering? Abstracte Datatypen (ADTs) zijn een vast onderdeel van elk CS-curriculum. Waarom zie ik (en elke andere expert op het gebied van formele methoden/modellering) dan zo'n groot gat in de vaardigheden op het gebied van abstractie, en waarom markeren we dit als de cruciale, doorslaggevende vaardigheid voor modellering?
Ik denk dat ik eindelijk de kern van deze cognitieve dissonantie heb gevonden. Er zijn twee soorten "abstractie" die onder dezelfde verzamelterm worden geschaard.
- Modulaire abstractie: Dit is de traditionele abstractie die in CS-curricula wordt onderwezen als ADTs, API's, gelaagd ontwerp, enzovoort. Het draait volledig om inkapseling, het trekken van grenzen en het verbergen van interne details.
- Modelleringsabstractie: Dit is waar ik over spreek in de context van modellering. Dit is dezelfde vorm van abstractie die wiskundigen en natuurkundigen gebruiken bij het bouwen van modellen voor denken en redeneren. Het doel is om de minimale en meest elegante beschrijving te vinden die de eigenschap waar je om geeft, behoudt. Het draait om het wegsnijden van alles wat orthogonaal staat aan de essentie van die eigenschap.
Deze twee kunnen qua doel niet verder uit elkaar liggen.
Modulaire abstractie verbergt, modelleringsabstractie reduceert
Modulaire abstractie draait om interfaces die interne details verbergen. Modelleringsabstractie draait om gedragingen, en om het reduceren van een systeem tot het minimale gedragsskelet voor de eigenschap die relevant is.
Modulaire abstractie kapselt in, trekt een verticale grens en verbergt de laag daaronder. Modelleringsabstractie is dwarsdoorsnijdend: het snijdt het systeem langs een gedragsvlak en behoudt alleen wat absoluut relevant is voor de onderzochte eigenschap, en zelfs dan in de vorm van "wat", niet "hoe". Deze doorsnede lijkt meestal in niets op de organisatie van het systeem.
Modulaire abstractie verbergt concurrency, modelleringsabstractie stelt het bloot
Modulaire abstractie is gericht op het dichten van lekken, vandaar het beroemde bericht van Joel Spolsky waarin hij klaagt dat "alle abstracties lekken" (all abstractions are leaky). Let op dat zijn lijst volledig gaat over modulaire abstractie: TCP (verbergt IP), string-bibliotheken (verbergen character arrays), bestandssystemen (verbergen draaiende schijven), virtueel geheugen / vlakke adresruimte (verbergen MMU en paging), SQL (verbergt queryplannen), NFS / SMB (verbergen het netwerk), C++ string-klassen (verbergen char*). Modulaire abstractie streeft ernaar om interleavings (onderlinge vermenging van processen) te verbergen en operaties te presenteren alsof ze atomair zijn. Het doel is om de module gemakkelijk bruikbaar te maken, maar daarmee wordt het opgeven van concurrency- of efficiëntiemogelijkheden in koop.
In scherp contrast hiermee gaat modelleringsabstractie juist over het identificeren van wat moet lekken en daar gebruik van maken. Het stelt de fijnmazige acties en volgordes bloot, en bewijst dat invarianten behouden blijven ondanks de interleavings. De beloning voor dit werk is dat men de maximale veilige concurrency uit het systeem kan halen.
Voorbeelden van modelleringsabstractie
Er is een overvloed aan modelleringsabstractie in het veld van gedistribueerde systemen. Het voelt alsof bijna alle protocollen op deze manier zijn ontworpen:
- Lamport logische klokken: gooi de kloktijd (wall-clock time) weg, behoud de happens-before relatie.
- Hybride logische klokken: behoud kloktijd en causaliteit, gooi de rest weg.
- TrueTime: tijd als een interval van begrensde onzekerheid.
- Consensus: het eens worden over één beslissing. De manier waarop Lamport Paxos heeft ontworpen is een meesterklasse in abstractie; van Consensus, via Stemmen, naar het uiteindelijke protocol.
- Lineariseerbaarheid (en in feite alle consistentiemodellen): gooi replicatie, caching en retries weg.
- Het idee dat het logboek de database is: gooi gematerialiseerde status als bron van waarheid weg; behoud alleen de geordende, append-only reeks gebeurtenissen.
- MapReduce/Spark: gooi orchestratie, parallellisme, scheduling en fouttolerantie weg. Behoud een DAG van deterministische transformaties over gepartitioneerde data — en laat het framework de rest reconstrueren vanuit dat skelet.
Soms lijkt het alsof de twee definities overlappen (bijv. lineariseerbaarheid, consensus, log-as-database, map-reduce). Maar dit is in feite een hergebruik in plaats van een overlap. Een echt goed ontworpen artefact kan gelijktijdig dienen als een specificatie om tegen te verfijnen (modulair) en als een skelet om vanuit te redeneren (modellering). Dit betekent simpelweg dat de twee toevallig samenvielen in één artefact, maar de abstractierollen blijven verschillend.
De twee abstracties van systeemontwerp: verbergen of reduceren
Maar er is een tegenstrijdigheid die me dwarszit. Wordt er van mensen in de informatica (CS) niet al verwacht dat ze goed zijn in abstractie? Zou abstractie niet de kern moeten vormen van besturingssystemen, netwerken en software engineering? Abstracte Datatypen (ADTs) zijn een vast onderdeel van elk CS-curriculum. Waarom zie ik (en elke andere expert op het gebied van formele methoden/modellering) dan zo'n groot gat in de vaardigheden op het gebied van abstractie, en waarom markeren we dit als de cruciale, doorslaggevende vaardigheid voor modellering?
Ik denk dat ik eindelijk de kern van deze cognitieve dissonantie heb gevonden. Er zijn twee soorten "abstractie" die onder dezelfde verzamelterm worden geschaard.
- Modulaire abstractie: Dit is de traditionele abstractie die in CS-curricula wordt onderwezen als ADTs, API's, gelaagd ontwerp, enzovoort. Het draait volledig om inkapseling, het trekken van grenzen en het verbergen van interne details.
- Modelleringsabstractie: Dit is waar ik over spreek in de context van modellering. Dit is dezelfde vorm van abstractie die wiskundigen en natuurkundigen gebruiken bij het bouwen van modellen voor denken en redeneren. Het doel is om de minimale en meest elegante beschrijving te vinden die de eigenschap waar je om geeft, behoudt. Het draait om het wegsnijden van alles wat orthogonaal staat aan de essentie van die eigenschap.
Deze twee kunnen qua doel niet verder uit elkaar liggen.
Modulaire abstractie verbergt, modelleringsabstractie reduceert
Modulaire abstractie draait om interfaces die interne details verbergen. Modelleringsabstractie draait om gedragingen, en om het reduceren van een systeem tot het minimale gedragsskelet voor de eigenschap die relevant is.
Modulaire abstractie kapselt in, trekt een verticale grens en verbergt de laag daaronder. Modelleringsabstractie is dwarsdoorsnijdend: het snijdt het systeem langs een gedragsvlak en behoudt alleen wat absoluut relevant is voor de onderzochte eigenschap, en zelfs dan in de vorm van "wat", niet "hoe". Deze doorsnede lijkt meestal in niets op de organisatie van het systeem.
Modulaire abstractie verbergt concurrency, modelleringsabstractie stelt het bloot
Modulaire abstractie is gericht op het dichten van lekken, vandaar het beroemde bericht van Joel Spolsky waarin hij klaagt dat "alle abstracties lekken" (all abstractions are leaky). Let op dat zijn lijst volledig gaat over modulaire abstractie: TCP (verbergt IP), string-bibliotheken (verbergen character arrays), bestandssystemen (verbergen draaiende schijven), virtueel geheugen / vlakke adresruimte (verbergen MMU en paging), SQL (verbergt queryplannen), NFS / SMB (verbergen het netwerk), C++ string-klassen (verbergen char*). Modulaire abstractie streeft ernaar om interleavings (onderlinge vermenging van processen) te verbergen en operaties te presenteren alsof ze atomair zijn. Het doel is om de module gemakkelijk bruikbaar te maken, maar daarmee wordt het opgeven van concurrency- of efficiëntiemogelijkheden in koop.
In scherp contrast hiermee gaat modelleringsabstractie juist over het identificeren van wat moet lekken en daar gebruik van maken. Het stelt de fijnmazige acties en volgordes bloot, en bewijst dat invarianten behouden blijven ondanks de interleavings. De beloning voor dit werk is dat men de maximale veilige concurrency uit het systeem kan halen.
Voorbeelden van modelleringsabstractie
Er is een overvloed aan modelleringsabstractie in het veld van gedistribueerde systemen. Het voelt alsof bijna alle protocollen op deze manier zijn ontworpen:
- Lamport logische klokken: gooi de kloktijd (wall-clock time) weg, behoud de happens-before relatie.
- Hybride logische klokken: behoud kloktijd en causaliteit, gooi de rest weg.
- TrueTime: tijd als een interval van begrensde onzekerheid.
- Consensus: het eens worden over één beslissing. De manier waarop Lamport Paxos heeft ontworpen is een meesterklasse in abstractie; van Consensus, via Stemmen, naar het uiteindelijke protocol.
- Lineariseerbaarheid (en in feite alle consistentiemodellen): gooi replicatie, caching en retries weg.
- Het idee dat het logboek de database is: gooi gematerialiseerde status als bron van waarheid weg; behoud alleen de geordende, append-only reeks gebeurtenissen.
- MapReduce/Spark: gooi orchestratie, parallellisme, scheduling en fouttolerantie weg. Behoud een DAG van deterministische transformaties over gepartitioneerde data — en laat het framework de rest reconstrueren vanuit dat skelet.
Soms lijkt het alsof de twee definities overlappen (bijv. lineariseerbaarheid, consensus, log-as-database, map-reduce). Maar dit is in feite een hergebruik in plaats van een overlap. Een echt goed ontworpen artefact kan gelijktijdig dienen als een specificatie om tegen te verfijnen (modulair) en als een skelet om vanuit te redeneren (modellering). Dit betekent simpelweg dat de twee toevallig samenvielen in één artefact, maar de abstractierollen blijven verschillend.