Ga naar hoofdinhoud

Verdieping: projecties

Betekenis en doel

Een projectie is een samenhangende en op de informatiebehoefte van afnemers toegesneden gegevensverzameling, bedoeld voor verstrekking. Waar het gevolgenjournaal nauwkeurig documenteert wat er is gebeurd, beantwoorden projecties primair vragen als "leeft persoon p1 nog?", "wat is zijn burgerlijke staat?", en "heeft hij gezag over p3?" Zulke vragen veronderstellen een stand (ook wel toestand of state), ofwel een beeld van de wereld dat gedurende een bepaalde periode geldig is.

Niet alle projecties beschrijven een toestand. Een notificatiebericht is daarvan een voorbeeld: het informeert een afnemer over een verandering die door registratie van een gevolg is veroorzaakt. Net als het onderliggende gevolg is zo'n bericht temporeel atomair - het beschrijft wat er is gebeurd, niet welke toestand na dat gebeuren geldig werd.

Hoe projecties technisch wordt bijgehouden is een implementatiekeuze: ze kunnen vooraf worden berekend en opgeslagen, of op het moment van bevraging op basis van de opgegeven parameters gegenereerd.

Projectieperspectief: continuant of occurrent?

Als we willen begrijpen hoe projecties eruit zien, helpt het te begrijpen hoe we data willen representeren en wat de consequenties daarvan zijn. Dat doen we door om te beginnen een onderscheid aan te brengen tussen projecties die gaan over continuants (ook wel endurants of in het Nederlands voortdurenden) en projecties van occurrents (ook wel perdurants of in het Nederlands perdurantisten of voorkomenden).

Een continuantprojectie projecteert een entiteit - de continuant - die in de tijd beschouwd kan worden. Zo'n projectie levert voor ieder moment van het bestaan (of de geldigheid) van de continuant een complete en betekenisvolle toestand op.

Niet alle continuants zijn gelijk. Sommige daarvan kunnen onder één identiteit maximaal één geldigheidscyclus doormaken (denk aan een mens). Hun bestaansperiode is continu. Daarnaast komen contiunants (zoals een huwelijk) voor die meerdere, discontinue (of onderbroken) geldigheidsperiodes kunnen kennen. Het ontstaan van een tweede (of derde, vierde etc.) geldigheidsperiode bij zo'n entiteit noemen we vaak herleven.

Een occurrentprojectie projecteert een entiteit - de occurrent - die zich in de tijd voltrekt. Zo'n projectie kan alleen compleet en betekenisvol zijn als we alle momenten die de voltrekking van de occurrent duurde samen beschouwen.

Occurrents kunnen we onderverdelen naar de tijd die voltrekking duurde. Punctuele occurrents zijn instantaan (of temporeel atomair) en voltrekken zich op één moment. Duratieve occurrents voltrekken zich gedurende een periode, die in veel gevallen kan worden opgedeeld in fases (of stages).

Wetenschappelijk achtergrond en debat

In deze handreiking noemen we continuant en occurrent omdat ze helpen geprojecteerde gegevens te begrijpen. Achter deze begrippen gaan een lange wetenschappelijke geschiedenis en veel debat schuil.

De woorden continuant en occurrent werden voor het eerst beschreven in het driedelige 'Logic' (1921–1924) van de Britse logicus W.E. Johnson. Via debatten over persistentie en formele ontologie, waaronder Barry Smiths' Basic Formal Ontology, vonden ze vervolgens hun weg naar de informatica.

Over deze begrippen bestaat binnen de wetenschap veel discussie. Zo stelde James F. Allen in 'Maintaining Knowledge about Temporal Intervals' dat occurrents weliswaar instantaan kunnen lijken, maar dat voltrekking bij nadere beschouwing ("turning up the magnification") toch altijd een periode met tijdsduur vraagt.

In reactie daarop ('A critical examination of Allen's theory of action and time') betoogde Antony Galton dat het problematisch is om alle occurrents als interval te behandelen en dat we daarnaast ook instants moeten kunnen herkennen. Een middenpositie wordt ingenomen door Bittner et al., die in 'Endurants and Perdurants in Directly Depicting Ontologies' de periode waarbinnen een occurrent zich voltrekt verdelen in al dan niet instantane stages (fases).

Ook het zelfstandig bestaansrecht van continuants staat ter discussie. Zo betogen perdurantisten dat alle objecten in vier dimensies bestaan. Wat we hierboven een continuant noemden, is vanuit dit perspectief geen zelfstandige entiteit, maar slechts een instantane doorsnede van zo'n vierdimensionale occurrent.

Projectiedoel bepaalt perspectief

Of een entiteit geprojecteerd wordt als continuant of als occurrent staat los van de manier waarop we gegevens in het gevolgenjournaal of andere bron voor onze projectie hebben vastgelegd. Het projectieperspectief wordt dus niet bepaald door het vastleggingspersperspectief van het bronmateriaal, maar door de manier waarop we naar dat bronmateriaal willen kijken - en in het verlengde daarvan van de informatiebehoefte die we met een projectie willen invullen.

Dit betekent dat op basis van één set gevolgen voor de ene doelgroep continuantprojecties kunnen worden geproduceerd, terwijl voor andere afnemers projecties vanuit occurrentperspectief worden gemaakt.

Onderstaand voorbeeld illustreert hoe op basis van één set gevolgen die rondom een vergunning zijn bijgehouden projecties in continuant- én occurrentvorm kunnen worden geproduceerd. De continuantprojectie beschouwt de vergunning als entiteit waarvoor een toestand kan worden getoond. Projecteren we de vergunning als occurrent, dan krijgen we een aan de hand van 'milestones' geïllustreerde levenscyclus te zien.

// In het gevolgenjournaal bekende gevolgen die de levenscyclus van de vergunning hebben beïnvloed

[
{
"gevolgId": "ev-001",
"gevolgType": "vergunningsaanvraag ontvangen",
"betreft": { "type": "aanvraag", "id": "av-2004-1459" },
"gebeurdOp": "2004-03-12"
},
{
"gevolgId": "ev-002",
"gevolgType": "vergunning verleend",
"betreft": { "type": "vergunning", "id": "vg-2004-0815" },
"beïnvloedt": { "type": "aanvraag", "id": "av-2004-1459" },
"gebeurdOp": "2004-06-18"
},
{
"gevolgId": "ev-003",
"gevolgType": "vergunning ter inzage gelegd",
"betreft": { "type": "vergunning", "id": "vg-2004-0815" },
"gebeurdOp": "2004-06-21"
},
{
"gevolgId": "ev-004",
"gevolgType": "bezwaar ontvangen",
"betreft": { "type": "bezwaar", "id": "bz-2004-0213" },
"beïnvloedt": { "type": "vergunning", "id": "vg-2004-0815" },
"gebeurdOp": "2004-06-23"
},
{
"gevolgId": "ev-005",
"gevolgType": "bezwaar afgewezen",
"betreft": { "type": "bezwaar", "id": "bz-2004-0213" },
"beïnvloedt": { "type": "vergunning", "id": "vg-2004-0815" },
"gebeurdOp": "2004-07-17"
},
{
"gevolgId": "ev-006",
"gevolgType": "vergunning onherroepelijk geworden",
"betreft": { "type": "vergunning", "id": "vg-2004-0815" },
"gebeurdOp": "2004-08-02"
}
]
// Vergunningaanvraag als continuant: het object met actuele toestand

// Request
{
"resource": "vergunningen",
"id": "vg-2004-0815",
"presentatieperspectief": "continuant",
"geldigOp": "2004-07-24"
}

// Response
{
"id": "vg-2004-0815",
"status": "verleend",
"isOnherroepelijk": "false"
}
// Vergunningaanvraag als occurrent: gefaseerde levenscyclus

// Request
{
"resource": "vergunningen",
"id": "vg-2004-0815",
"presentatieperspectief": "occurrent",
"gebeurdVanaf": "1970-01-01",
"gebeurdTot": "2004-07-25"
}

// Response
{
"id": "vg-2004-0815",
"fases": [
{ "type": "vergunning verleend", "gebeurdOp": "2004-06-18" },
{ "type": "vergunning ter inzage gelegd", "gebeurdOp": "2004-06-21" },
{ "type": "vergunning door bezwaar betwist", "gebeurdOp": "2004-06-23" },
{ "type": "betwisting vergunning door bezwaar beëindigd", "gebeurdOp": "2004-07-17" }
]
}

Intermezzo: van gevolg naar projectie

Een projectie is geen directe weergave van de gevolgen in het journaal — er zit altijd bewerking tussen. Bij de continuantprojectie hierboven is dat bijvoorbeeld zichtbaar in de boolean isOnherroepelijk. Die is op false gezet omdat er op het gevraagde moment nog geen gevolg "vergunning onherroepelijk geworden" was geregistreerd. Om tot een te projecteren toestand te komen, worden hier dus gevolgen geïnterpreteerd.

Ook bij een occurrentprojectie is bewerking nodig, maar die is subtieler. Omdat het gevolgenjournaal zelf al bestaat uit occurrents, zou je kunnen denken dat die in een projectie één op één overgenomen worden. De projectie in het voorbeeld hierboven wijkt niettemin subtiel van de gevolgen waarop die gebaseerd is. Dat komt door een afwijkend perspectief. Het journaal beschrijft vanuit bijhoudingsperspectief zo nauwkeurig mogelijk wat er binnen een bounded context gebeurt. Vanuit projectieperspectief is het gewenst dat gebeurde opnieuw te ordenen rond bepaalde kernconcepten.

In het voorbeeld zie je dit op twee manieren terug. Het gevolg "bezwaar ontvangen" is opgesteld het vanuit bijhoudingsperspectief relevantste concept - het bezwaar zelf. In de vergunningprojectie moet dit gevolg 'hertaald' worden zodat het leest als een fase in de levenscyclus van de vergunning, ergo "vergunning door bezwaar betwist". Het gevolg "vergunningsaanvraag ontvangen" verschijnt in de projectie helemaal niet omdat de vergunning op dat moment nog niet bestond en de levenscyclus daarvan dus nog niet was begonnen.

Tijdsaspecten van projectieperspectief

In de projectievoorbeelden hierboven worden in relatie tot 'tijd' verschillende begrippen gebruikt. De continuantprojectie wordt bevraagd op basis van geldigheidsmomenten (met parameters als geldigOp, geldigVanaf of geldigTot), terwijl we in het request voor de occurrentprojectie een voltrekkingsperiode (met gebeurdVanaf en gebeurdTot als parameters) opgeven. Dit is geen toeval: bij projecties vanuit verschillend perspectief horen verschillende temporele dimensies.

Nota bene: systeemtijd werkt voor de in dit hoofdstuk besproken projecties op dezelfde manier en wordt hier daarom niet nader behandeld; in de paragraaf projectiesoorten komen we hier op terug voor de gevallen waar systeemtijd een afwijkende rol speelt.

Continuants: geldigheid

Het begrip geldigheidstijd (of valid time) werd in 1986 gemunt door Richard Snodgrass en Ilsoo Ahn. In hun artikel 'Temporal Databases' illustreren de auteurs deze temporele dimensie aan de hand van een universiteitsmedewerker ('Merrie') die door de tijd verschillende functies heeft.

Informatie over de veranderende functie van Merrie vinden we door aan een projectie de vraag te stellen "wat was op moment tx de functie van Merrie?" Voor september 1973 zou het antwoord 'instructor' luiden, terwijl het voor december van dat jaar 'assistent professor' zou zijn. Hoewel het artikel dit niet expliciet maakt, veronderstelt dit voorbeeld een projectie over Merrie's functies vanuit continuantperspectief.

Occurrents: voltrekking

Bovenstaande conclusie kunnen we trekken omdat we een occurrentprojectie niet betekenisvol op de beschreven manier kunnen bevragen. Neem opnieuw de veranderende functie van Merrie, maar nu niet beschouwd vanuit een medewerker met verschillende rollen, maar als loopbaan: een gefaseerde voltrekking van opeenvolgende aanstellingen.

Stel dat je daarover vraagt: "hoe zag moment tx Merrie's loopbaan eruit?" Dan zou voor 1 oktober 1973 het antwoord als volgt kunnen luiden: "Merrie was als instructor aangetreden, de aanstelling als assistant professor was nog niet ingegaan." Wat hier beschreven wordt is geen toestand, maar een opsomming van op het bevragingsmoment gepasseerde en onderhanden fases.

Op basis hiervan kunnen we concluderen dat de 'geldigheid' van een loopbaan op 1 oktober 1973 (of een ander moment) eenvoudigweg niet bestaat. Wat wel bestaat is het feit dat een deel van de loopbaan achter de rug is - we noemen dit 'voltrokken' - en een ander deel nog moet komen. Dit betekent dat we occurrents niet bevragen en projecteren op basis van geldigheidstijd, maar op basis van voltrekkingstijd (of occurrence time).

Geldigheid + voltrekking = domeintijd

We hebben hierboven gezien dat continuants en occurrents ieder hun eigen tijdsdimensie kennen - geldigheidstijd voor de eerste, voltrekkingstijd voor de tweede. Dit plaatst ons voor een probleem. Want in literatuur wordt de term geldigheidstijd vaak gebruikt als generieke aanduiding voor alles wat geen systeemtijd is. Dat is een historisch gegroeide onnauwkeurigheid: geldigheidstijd is passend voor continuants, maar niet voor occurrents.

Wat geldigheidstijd en voltrekkingstijd gemeen hebben, is dat ze beide iets uitdrukken over de (fysieke, juridische of administratieve) werkelijkheid die het register beschrijft, en niet over het register zelf. Deze categorie tijdsbegrippen willen we met één begrip kunnen aanduiden. Hiervoor kiezen we het woord domeintijd. Die omvat alle vormen van tijd die niet door het register zelf worden bepaald maar door wat in het bedrijfsdomein gebeurt of geldt.

We werken tijdsaspecten technischer uit in de verdieping temporaliteit in projecties.

Projectiesoorten

Met het onderscheid tussen continuant en occurrent en de bijbehorende temporele dimensies hebben we de bouwstenen om projecties scherper te kunnen typeren. Voor welke 'soort' projectie is welke domeintijd relevant? Geldigheidstijd, voltrekkingstijd, of geen van beide? En binnen die dimensie: zijn meerdere geldigheidsperiodes mogelijk of niet, duurt voltrekking tijd, of gebeurt dat in één moment?

Onderstaande tabel plaatst deze categorieën op een domeintijdas. Op de andere as kunnen we dan de tijdsdimensie plaatsen die wel door het register wordt bepaald: de systeemtijd. De tabel die hierdoor ontstaat kunnen we vullen met acht projectiesoorten. Voor ieder daarvan volgt hieronder een korte typering en één of meer voorbeelden.

Projectiesoorten naar perspectief en temporele vereisten

Nota bene: tabel en projectiesoorten gaan over projecties die in het normaal verkeer aan afnemers worden getoond. Betrouwbaar beheer en navolgbaar foutherstel maken het in vrijwel alle gevallen gewenst systeemtijd bij te houden - dus ook voor specificatiegegevens, automatische observaties en vaste waarden.

Herlevend ding

Een continuantprojectie van een entiteit die meerdere, al dan niet aansluitende geldigheidsperiodes onder dezelfde identiteit kan kennen. Tussen periodes kan de geldigheid onderbroken zijn en later weer hervatten. Voorbeeld: een huwelijk dat na ontbinding opnieuw wordt voltrokken tussen dezelfde personen.

Niet-herlevend ding

Een continuantprojectie van een entiteit die onder één identiteit één aaneengesloten geldigheidsperiode kent. Eindigt de geldigheid, dan eindigt de entiteit definitief — een tweede geldigheidsperiode onder dezelfde identiteit is niet mogelijk. Voorbeelden: een mens, een dienstverband, een vergunning.

Traject

Een occurrentprojectie van een entiteit die zich gefaseerd over een aaneengesloten periode voltrekt. Het traject heeft een aanvang, een einde en interne fases die samen de voltrekking vormen. Voorbeelden: een vergunningprocedure, een behandeltraject, een bezwaarprocedure.

Gebeurtenis

Een occurrentprojectie van een entiteit die zich op één moment in de tijd voltrekt. De gebeurtenis kent geen interne fases en is temporeel atomair. Voorbeelden: een melding, een meting, een klantcontact.

Systeemevent

Een occurrentprojectie van een gebeurtenis die uitsluitend binnen het systeem plaatsvindt en geen tegenhanger heeft in de werkelijkheid daarbuiten. Domeintijd ontbreekt; alleen systeemtijd is relevant. Voorbeelden: een logregel, een audit trail entry, een systeemmelding.

Specificatiegegeven

Een continuantprojectie van een entiteit met beperkte veranderlijkheid die de kaders beschrijft waarbinnen andere, meer volatiele gegevens zich bewegen. Daarom hoeft hierover bijgehouden registratiehistorie in projecties doorgaans niet te worden getoond. Voorbeelden: een zaaktype, een producten- en dienstencatalogus, een classificatie.

Automatische observatie

Een occurrentprojectie waarbij vastlegging zonder menselijke tussenkomst plaatsvindt op het moment van plaatsvinden, waardoor registratiemoment en voltrekkingsmoment per definitie samenvallen. Voorbeelden: een sensormeting, een GPS-track, een automatische transactie.

Vaste waarde

Een continuantprojectie zonder tijdsdimensie. De waarde staat onveranderlijk vast en kent geen geldigheids- of registratiehistorie. Voorbeelden: een landcode, een geslachtsaanduiding, een natuurconstante.

De herhaalbare vraag

Zoals eerder in dit document genoemd is het een belangrijke eis van een betrouwbaar register om, zoveel als mogelijk, de herhaalbare vraag te kunnen beantwoorden. Een afnemer moet, nadat deze op tijdstip T1 een gegeven heeft opgevraagd, op tijdstip T2 nog steeds de vraag kunnen stellen wat dit gegeven op tijdstip T1 was. Een betrouwbaar register dient dit te kunnen nadat:

  1. Er nieuwe gevolgen zijn toegevoegd aan de registratie.
  2. Een gegeven hersteld is doordat het geldigheidstijdvak is veranderd vanwege een foutieve registratie.
  3. Een softwarebug in de opvraging is hersteld waardoor de initiële opvraging fout was.

Criterium 1 en 2 introduceren bitemporaliteit in de registratie. Criterium 3 vereist dat er mechanismen zijn die het mogelijk maken softwareaanpassingen te doen met behoud van de eerdere gegevensrepresentatie.

Inherente beperkingen aan de herhaalbare vraag

Elk register loopt tegen inherente beperkingen aan. Zowel geldigheids- als gevolgtijdstippen hebben te maken met eventual consistency: er zit altijd tijd tussen het begin van een registratie en het einde daarvan, en er zit altijd tijd tussen een opvraging en de zichtbaarheid van deze gegevens voor de afnemer. Dit betekent dat een afnemer altijd in potentie naar verouderde informatie kijkt.

Daarnaast heeft een register meestal niet de volledige controle over de verstrekking van informatie. Beweringen verlaten op een bepaald moment het register om elders te worden gepresenteerd — in een browser, een API-response, of een ander systeem dat het register niet kent.

Herhaalbaarheid van opvraging is dus hoogstens te behalen tot op het niveau van de gegevensrepresentatie net voordat deze het systeem verlaat. Hoe met deze beperkingen om te gaan is een ontwerpoverweging; zie eventual consistency als ontwerpoverweging.

Terugmelden

Terugmeldingen hebben altijd betrekking op een projectie. De afnemer meldt dat hij twijfelt aan de juistheid van (een deel van) die projectie.

Omdat projecties over uiteenlopende samenstellingen van gegevens kunnen gaan en de aard van geconstateerde onjuistheden sterk kan verschillen, kan een terugmelding vele vormen aannemen. Daarbij past geen beperkend 'terugmeldformulier', maar (vorm)vrijheid en veel ruimte voor toelichting in vrije tekst.

Als een bronhouder regelmatig terugmeldingen van dezelfde strekking ontvangt, kan hij overwegen daarvoor een specifieke, meer gestructureerde interface aan te bieden. Dit verlaagt de drempel voor de terugmelder en maakt de verwerking aan de kant van de bronhouder efficiënter.

Een terugmelding bevat in ieder geval:

  • Verwijzing naar de betreffende gegevens. De terugmelder geeft aan op welke projectie of welk onderdeel daarvan de melding betrekking heeft. Hoe die verwijzing er precies uitziet, is afhankelijk van hoe projecties identificeerbaar zijn gemaakt - bijvoorbeeld via een uniek kenmerk van de verstrekking of een combinatie van subject en tijdstip
  • Toelichting. De terugmelder beschrijft in vrije tekst wat hij als onjuist beschouwt en waarom. Dit biedt de bronhouder de context die nodig is om het onderzoek gericht te kunnen starten.
  • Contactgegevens van de terugmelder. Zodat de bronhouder, indien het onderzoek daarom vraagt, contact kan opnemen voor nadere toelichting of terugkoppeling.

Open vragen

  • Terugmelden is binnen het stelsel voor basisregistraties een voorwaarde voor afwijken van gegevens in de bron. Zouden terugmeldende afnemers dan voor eigen gebruik en hangende een onderzoek hun eigen, vermoedelijk juistere 'alternatieve' gegevens in het register moeten kunnen zetten?
  • Hoe wijzen we gegevens waarover we terugmelden voor de bronhouder (historisch) onderscheidbaar aan?

Onderzoeken

Onderzoek naar aanleiding van een terugmelding vindt plaats buiten het register en leidt niet tot nieuwe projecties. Wel kan uit onderzoek blijken dat bij vermoedelijk onjuiste projecties indicaties van verminderde zekerheid over de juistheid moeten worden aangebracht.

Corrigeren

In de meeste gevallen is een verstrekking foutief omdat één of meerdere gevolgen die de basis vormen van deze projectie foutief waren. Het corrigeren van een dergelijke verstrekking begint dan met correctiegevolgen in het gevolgenjournaal. Een correctiegevolg bevat de gevolgen 'hoe ze hadden moeten zijn', en op basis van deze subgevolgen kan een projectie hersteld worden. Er wordt bepaald vanaf welk moment een bestaande projectie niet langer geldig is. Die projectie krijgt daarna een vervallen op-indicatie, waarmee de verstrekking voor actief gebruik wordt afgesloten. En daarnaast worden nieuwe projecties gemaakt, die met terugwerkende kracht de foutieve projecties bovenschrijven. Bovenschrijven betekent hierbij dat bestaande projectie-elementen behouden blijven en nieuwe elementen ernaast worden geplaatst met een later systeemtijdstip. Het register overschrijft nooit; het schrijft alleen boven, als temporele consequentie van het append-only-patroon.

Het is ook mogelijk dat uit onderzoek blijkt dat de oorspronkelijk vastgelegde gevolgen correct waren, en dat de fout hem in de afleiding van de projectie zit. Een dergelijke softwarefout zal hersteld moeten worden, waarna een volledige of selectieve replay gedaan moet worden: Ook in dit scenario moet bepaald worden vanaf welk moment een bestaande foutieve toestand niet langer geldig is, en dat deze moet vervallen. Foutieve toestanden worden geïdentificeerd en opnieuw opgebouwd, waarna ze toegevoegd worden aan de projecties en de oude toestand bovenschrijven.

Herkomst

Omdat projecties direct worden afgeleid uit gevolgen in het gevolgenjournaal, zijn herkomstmetadata aan voor projecties beknopter van omvang dan aan de journaalkant. De voornaamste verantwoording ligt immers al besloten in de gevolgen waarop een projectie is gebaseerd.

Bron

De aanleiding verwijst naar het gevolg of de gevolgen die als basis dienden voor de productie van de projectie. Daarmee is de herkomst van een projectie altijd herleidbaar naar het gevolgenjournaal.

Legitimering

Voor zover van toepassing wordt een verwijzing vastgelegd naar het wettelijk of beleidskader dat diende als grondslag voor de productie van de projectie - bijvoorbeeld als regelgeving voorschrijft welke gegevens aan welke afnemers verstrekt mogen of moeten worden.

Verantwoordelijke

Bij ieder projectie-element wordt vastgelegd welke ambtenaar of organisatieafdeling voor productie daarvan verantwoordelijk was.

Werkwijze

Het projectie-element omvat een verwijzing naar het algoritme of de algoritmes die zijn gebruikt om van één of meer gevolgen een projectie af te leiden, inclusief de versie daarvan. Zo is achteraf reconstrueerbaar op welke manier de projectie tot stand is gekomen.

Registratie

Bij iedere concrete verstrekking kan het projectietijdstip — het systeemtijdstip waarop een projectie-element beschikbaar is gekomen — worden meegeleverd. Of dat wenselijk is, hangt af van de situatie. Bij een vraag naar de actuele stand is dit tijdstip vaak niet relevant. In andere gevallen kan het meesturen ervan juist ongewenst zijn, omdat het informatie kan onthullen die niet met iedereen gedeeld mag worden, zoals het feit dat een correctie heeft plaatsgevonden.

Geldigheid

Bij projecties die zijn opgebouwd uit meerdere gevolgen, is het belangrijk onderscheid te maken tussen de geldigheidsdatum van de projectie zelf en de domeindatums van de gegevens daarbinnen.

De geldigheidsdatum van een projectie geeft aan vanaf welk moment deze projectie in deze vorm als 'juist' of 'waar' beschouwd wordt. Die datum zegt (dus) niets over de ouderdom van in de projectie betrokken entiteiten of andere daarin opgenomen gegevens.

Neem als voorbeeld de volgende gevolgen:

  • woz-object w1 ontstaan | gebeurd op 15-08-1994
  • belanghebbende bij woz-object w1 is p1 | gebeurd op 23-08-1994
  • belanghebbende bij woz-object w1 is p2 | gebeurd op 19-10-2009
  • belanghebbende bij woz-object w1 is p3 | gebeurd op 07-03-2023

Het WOZ-object bestaat al sinds 15-08-1994, maar de projectie is voor het laatst bijgewerkt naar aanleiding van het gevolg van 07-03-2023. Die datum markeert dus niet het ontstaan van het object, maar het meest recente domeinmoment dat de huidige vorm van de projectie heeft bepaald.

Zonder die toelichting riskeert een afnemer de datum verkeerd te interpreteren. Uit de projectie moet de betekenis daarom voldoende duidelijk blijken - bijvoorbeeld door de geldig vanaf-datum expliciet aan de projectie te koppelen (zie het voorbeeld hieronder), of door aan te geven dat die datum de laatste relevante wijziging in het domein betreft.

projectie l1
geldig vanaf 07-03-2023
woz-object w1
eerste registratie 15-08-1994
belanghebbenden
p1
start belang 23-08-1994
einde belang 18-10-2009
p2
start belang 19-10-2009
einde belang 06-03-2023
p3
start belang 07-03-2023

Zekerheid

Zekerheidsaanduidingen zijn in de eerste plaats relevant voor afnemers. Zekerheid moet daarom zichtbaar zijn in projecties.

Omdat onzekerheid diep kan doorwerken in ketens, is het niet altijd voldoende alleen de zekerheid van een projectie als geheel aan te geven. Een daartoe geautoriseerde afnemer moet ook kunnen zien welk onderliggend gevolg de bron van twijfel is, zodat hij kan beoordelen in hoeverre zijn eigen verwerking daarop steunt en hoe hij daarmee wil omgaan.

Afhankelijk van de situatie kan een afnemer er bijvoorbeeld voor kiezen een bedrijfsregel situationeel buiten werking te stellen, onzekerheid door te geven aan zijn eigen afnemers, of processen die op de gegevens steunen expliciet te laten waarschuwen wanneer zij onzekere gegevens tegenkomen.

Onttrekking

Of een onttrekking ingrijpt in het gevolgenjournaal, projecties, of beide, hangt af van waar de fout zat. Zat deze fout uitsluitend in de wijze waarop projecties uit het gevolgenjournaal werden afgeleid - en niet in de gevolgen zelf - dan volstaat het de afleidingswijze te corrigeren en nieuwe projecties te produceren.

In alle gevallen resulteert een onttrekking in opname van een vervallen op-moment (zie ook corrigeren) bij de door de onttrekking geraakte projecties. Daarmee wordt de projectie voor actief gebruik afgesloten, zonder dat de oorspronkelijke vastlegging verdwijnt. De onttrokken projectie blijft om de herhaalbare vraag te waarborgen technisch behouden. Die is daarna echter alleen onder specifieke voorwaarden - bijvoorbeeld voor juridisch of historisch onderzoek - toegankelijk.

Als de onttrekking betrekking heeft op identiteitsdragende kenmerken van een projectie, wordt de volledige projectie onttrokken. Bij niet-identiteitsdragende kenmerken kan onttrekking beperkt blijven tot die kenmerken, mits de implementatie dit technisch toelaat.

Resultaat voor onttrokken gegevens moet in normaal verkeer hetzelfde resultaat zijn als bevragingen van niet-bestaande gegevens.

Ontwerpafwegingen

Temporaliteit

Een belangrijke factor voor een projectie is de keuze voor wat betreft temporaliteit. Voor het kunnen beantwoorden van de herhaalbare vraag is bitemporaliteit een eis: Als ingegrepen wordt op de tijdlijn, bijvoorbeeld als gevolg van een correctie, dient de projectie nog steeds de oorspronkelijke toestand te kunnen reproduceren.

Bitemporaliteit brengt op zichzelf echter complexiteit met zich mee die niet in alle gevallen nodig is. Wanneer een herhaalbare vraag kunnen stellen minder of niet van belang is, zou een specifieke temporele projectie op de geldigheidstijdlijn of alleen een actuele toestandsprojectie ook kunnen voldoen.

Een implementatiegerichte uitleg van verschillende vormen van temporaliteit in projecties is hier te vinden.

Eventual consistency als ontwerpoverweging

Tussen het vastleggen van een gevolg in het gevolgenjournaal en de zichtbaarheid van het resultaat in een projectie zit verwerkingstijd. Bij synchrone verwerking is die verwaarloosbaar; bij asynchrone of gedistribueerde architectuur kan het venster significant zijn. Gedurende dat venster kijkt een afnemer naar een projectie die het meest recente gevolg nog niet weerspiegelt.

Deze eventual consistency gaat uitsluitend over tijdigheid, niet over logische consistentie. Gevolgen zijn er juist op gericht om een eenduidige handeling als één samenhangend geheel vast te leggen, en ondersteunen daarmee de logische consistentie van het gevolgenjournaal. Een projectie die het meest recente gevolg nog niet weerspiegelt, is dus niet tegenstrijdig met wat al is vastgelegd — de informatie is alleen nog niet doorgekomen.

Dit is geen fout maar een eigenschap van de architectuur: gevolg en projectie leven in gescheiden stores, elk met een eigen systeemtijdstip. De inherente beperkingen aan de herhaalbare vraag benoemen dit als grens van herhaalbaarheid; hier benoemen we het als ontwerpkeuze. Bij het ontwerp van een projectie moet worden afgewogen hoeveel verwerkingstijd acceptabel is en welke consequenties dat heeft voor de garanties die aan afnemers worden geboden.

Query-complexiteit versus query-flexibiliteit

De keuze van gegevensrepresentatie van een projectie en de gewenste informatie die een afnemer blieft bepaalt de complexiteit van de (database)query die gedaan moet worden om in een informatiebehoefte te voorzien. In het voorgestelde patroon, waarin we commando's, gevolgen en projecties van elkaar scheiden, hebben we niet meer de 'ballast' van de commandokant, en kunnen we onze projecties specifieker optimaliseren voor de afnemer(s).

Hier zijn echter nog steeds afwegingen in te maken. Een projectie kan gebouwd worden op een manier dat de payload response van een query as is (in bijvoorbeeld een json- of xml-structuur) opgeslagen wordt in de database. We noemen dit de bitemporele opslag van payloads. Deze wijze van persisteren heeft een aantal voordelen:

  1. Dit is de best mogelijke manier om de herhaalbare vraag te kunnen beantwoorden: De payload wordt as-is opgeslagen, en (later) veranderende code beïnvloedt deze payload niet.
  2. Omdat de structuur van het bericht vast ligt, ook nadat er codewijzigingen gedaan worden, kan er in terugmeldingen en onderzoeken via bijvoorbeeld xpath of jsonpath hard verwezen worden naar entiteiten of velden waarover getwijfeld wordt.
  3. De (database) opvraging is eenvoudig: Op basis van tijdstippen en een index dient een payload opgezocht te worden. Dit voorkomt grotendeels het verstrekken van foutieve informatie als gevolg van foutief geïmplementeerde queries.

Zeker in combinatie met bitemporaliteit zien wij de opslag van payloads als een goede keuze voor wat betreft informatieverstrekking. Bitemporaliteit kan, in combinatie met bijvoorbeeld ingewikkelde correcties, zeer ingewikkelde situaties opleveren die zelfs voor experts moeilijk te doorgronden zijn. Het feit dat de query eenvoudig is en de payload statisch is bij een bitemporele payloadstore, maakt dat deze projectievorm uitermate robuust is voor het beantwoorden van de herhaalbare vraag.

De opslag van payloads heeft echter ook nadelen: Omdat de datastructuur zo rigide vast ligt kun je moeilijker, of niet, meerdere soorten vragen beantwoorden met dezelfde projectie. Ook leent deze vorm van opslag zich minder voor joins (het combineren van verschillende payloads/entiteiten). Dit alles maakt deze structuur minder flexibel, en dit dwingt je tot het maken van veel hele afnemerspecifieke projecties.

Het bitemporele tabel-model kan naargelang behoefte dan een goede keuze zijn. Een relationeel model, en zeker een bitemporeel relationeel model, is veel flexibeler in het kunnen beantwoorden van allerhande soorten vragen. De aard van de datarepresentatie maakt echter wel de queries en de mapping naar de doelstructuur van de payload complexer, wat het garanderen van herhaalbaarheid van vragen doet afnemen.

Betrouwbare modellen versus onbetrouwbare realiteit

Een goed datamodel beschrijft structuren, entiteiten en properties van een domein. Een huisnummer is een getal, terwijl een adres een straatnaam bevat als string met een maximaal aantal karakters. Deze eigenschappen worden idealiter goed gevalideerd aan de commandokant, en door dat te doen kun je duidelijke contracten afspreken met je afnemers over wat voor data je verstrekt en in welke vorm. Dergelijke modellen bepalen databasestructuren en beperkingen voor wat betreft gegevensopslag.

De realiteit is echter vaak weerbarstig: Ooit verkeerd geïmplementeerde validaties, oude data uit migraties of veranderingen in het datamodel naar verloop van tijd kunnen er in veel gevallen voor zorgen dat de data die je hebt niet altijd voldoet aan het voorgeschreven gegevensmodel. Huisnummers met letters, te lange straatnamen... Als je gebonden bent aan het principe van het kunnen beantwoorden van de herhaalbare vraag zal deze data altijd foutief blijven.

Een relationeel model biedt duidelijkheid over het datamodel, maar is minder flexibel als het gaat om data die niet aan dit model voldoet. Er moet altijd een keuze gemaakt worden: voor zeldzame uitzonderingen dient het model aangepast te worden, of deze uitzonderingen kunnen niet verwerkt worden. Hetzelfde probleem geldt vaak voor berichtvalidaties via bijvoorbeeld XSD's.

De consequenties van bijvoorbeeld een verhuizing niet doorgeven omdat een straatnaam te lang bevonden wordt zien wij als zeer onwenselijk. Afhankelijk van de datakwaliteit kan het dan een betere keuze zijn om data-opslag en berichtverkeer flexibeler te maken zodat afwijkingen van het datamodel wel opgeslagen en gecommuniceerd kunnen worden. Richting een afnemer kan het dan wenselijk zijn deze communicatie te doen met een extra melding: "in dit bericht voldoen we niet aan het datamodel".

Generaliseerbaar versus specifieke implementatie

TODO

Dit moet nog verder uitgewerkt worden

Varianten

Hieronder volgt een niet-uitputtende lijst van varianten van projecties die gebruikt kunnen worden. Elke projectievariant heeft voor- en nadelen die, afhankelijk van de use case, sterker of minder sterk gelden. Het is niet ons doel om te stellen welk van deze varianten de voorkeur geniet. Wel willen we voor- en nadelen van projectievarianten benoemen.

TemporaliteitRelationele databasePayloadsProjectiegevolgen
actueel
temporeel
bitemporeel

Transactionaliteit

Een gevolg legt één besluit of gebeuren vast. Dit besluit kan bestaan uit deelbesluiten of anderszins opdeelbare elementen, maar uiteindelijk betreft het nog steeds één besluit, dat (voor zover relevant voor de projectie) in zijn geheel wel of niet verwerkt dient te worden in een projectie, wat in databasetermen betekent dat een gevolg altijd in precies één databasetransactie verwerkt dient te worden. Het verwerken van een door de business erkend gevolg in meerdere (database)transacties kan er namelijk toe leiden dat datacorruptie optreedt: als een gevolg in twee transacties verwerkt wordt, zou de tweede transactie mis kunnen gaan, waarbij een ongeldige situatie ontstaat.

De implementatie-uitdaging bij projecties

Om van gevolg te komen tot een opvraagbare projectie hebben we een aantal transities nodig, waarbij meestal een vorm van opslag een tussenvorm is tussen het gevolg en wat de afnemer uiteindelijk op zijn scherm ziet. Een simpele flow chart van dit proces ziet er als volgt uit:

Uitgaande van deze architectuur hebben we in feite twee implementatie-uitdagingen:

  1. Hoe vertalen we de gevolgen naar een opgeslagen projectierepresentatie?
  2. Hoe vertalen we de opgeslagen projectierepresentatie (herhaalbaar) naar een leverbaar artefact?

Bij beide uitdagingen hebben we een implementatievorm nodig die robuust te bouwen is zodat deze een lange periode, mogelijk tientallen jaren, betrouwbaar herhaalbare vragen kan beantwoorden. En in die periode hebben we te maken met software die continue blijft evolueren, waar regelmatig (wekelijks, of zelfs dagelijks) nieuwe features aan toegevoegd worden, en de technologie je om de zoveel jaar stuurt naar software- of datamigraties.

Zowel een gevolgenjournaal als een bitemporele store bewaart data (grotendeels) append only: terwijl software veranderlijk is, blijft onze data behoorlijk statisch. We hebben dus vooral te maken met de veranderlijkheid van software. Hoe garandeer je dan de herhaalbare vraag? Bugs in deze software zijn ook onvermijdelijk. Hoe garandeer je hetzelfde (corrupte) antwoord na het oplossen van een bug? Zoals eerder benoemd kent herhaalbaarheid zijn grenzen, maar welke implementatiekeuzes het beste bij dit vraagstuk?

Door bij het opslaan van de transformatie van de gevolgen in de projectiestore te streven naar standaardisatie kunnen we fouten voorkomen: Een bitemporele store kunnen bijwerken met standaardoperaties, onafhankelijk van het soort gevolg, en aan de andere kant willen we herhaalbare, simpele queries hebben zodat de kans op softwarefouten bij het beantwoorden van de herhaalbare vraag zo klein mogelijk is. In het conceptueel registermodel worden Standaardoperaties voor het opbouwen van een projectie reeds besproken, wat implementatietechnisch is uitgewerkt in de verdieping van het bijwerken van projecties. Als elke projectie en elk gevolg afgehandeld wordt door een reeds eerder geïmplementeerde functie verkleint dat de fout op softwarefouten. Als we de transitie van gevolg naar projectie zoveel als mogelijk doen aan de 'linkerkant', kunnen we beter herhaalbaar leveren: Ook de meeste softwarefouten 'persisteren'.

Aan de rechter kant van onze store kunnen we streven naar 'zo min mogelijk' software voor de verstrekking van ons product. Als opvragingen uit onze store eenvoudig zijn, is de kans dat daar softwarefouten in zitten kleiner. Onze architectuur ziet er dan als volgt uit:

Het vereenvoudigen van de opvragingssoftware is niet zonder prijs. Er zal per projectie afgewogen moeten welke criteria het zwaarst wegen. Het volgende hoofdstuk gaat daarover.

Implementeringsvormen per projectie-archetype

Het conceptueel registermodel onderscheidt vijf archetypische projecties: aan de toestandskant de actueel geldige toestand, in domein geldige historische toestanden en alle historische toestanden, aan de gebeurenkant het onderschreven verloop en het volledig verloop. Deze archetypen zeggen wat een projectie bevat; ze zeggen niet hoe je die bouwt. Per archetype zijn meerdere implementeringsvormen mogelijk, die langs twee assen variëren:

  • Temporaliteit: alleen de actuele stand, domeintijd zonder systeemtijd, of domeintijd en systeemtijd samen (bitemporeel).
  • Opslag- en leveringsvorm: rijen in relationele tabellen, payloads, een hybride vorm van cellen en payload, of een stream die het register zelf uitgeeft.

Dit noemen we in dit document overigens geen 'soorten'; die term laten we voor de acht projectiesoorten hierboven, die gaan over het perspectief op de entiteit en niet over de bouwvorm van de projectie.

Dit hoofdstuk is een overzicht van de implementatievormen per archetype. De afwegingen tussen de vormen staan in de ontwerpafwegingen hierboven; de beslisboom hieronder leidt van de ontwerpvraag naar een van deze vormen.

Actueel geldige toestand

Voor de afnemer die alleen de stand van nu nodig heeft, komen twee vormen in aanmerking:

  • Actuele tabellen: één toestand per entiteit die bij elke nieuwe toestand wordt overschreven. De eenvoudigste en snelste vorm; historie ontbreekt volledig. Deze vorm kan volledig relationeel gemaakt worden.
  • Actuele payload: een payload per entiteit, eveneens herschreven bij elke nieuwe toestand.

Geen van deze vormen kan de herhaalbare vraag beantwoorden: een correctie in de domeintijd schrijft het verleden stilzwijgend over en het eerdere antwoord is weg.

In domein geldige historische toestanden

Wie enkel vragen over de domeinhistorie wil beantwoorden – "wat gold er op moment t?" – legt geldigheidsperiodes vast:

  • Temporele tabellen: per rij een geldigVanaf- en geldigTot-waarde, met bij elke bijhouding een gesloten oud-periode en een nieuw-op-volg-periode. Vragen naar wat er toen gold zijn flexibel te beantwoorden; vragen naar wat het register toen onderschreef niet, want een correctie met terugwerkende kracht herschrijft de historie.
  • Temporele payloads: payloads per geldigheidsperiode, in dezelfde hoedanigheid als hierboven, maar dan per geldigheidsmoment bewaard.

Deze vorm is passend zolang het antwoord op "wat gold er?" mag meebewegen met wat het register op dit moment voor juist houdt.

Alle historische toestanden

Dit archetype beantwoordt zowel "wat gold er?" als "wat onderschreef het register toen?", en is per definitie bitemporeel. De keuze uit de beslisboom over opslagvorm komt hier op neer:

  • Bitemporeel tabel model (zie bitemporele relationele databases): alle gegevens in cellen, geldigheid en registratie naast elkaar. Maximale query-flexibiliteit; herhaalbaarheid leunt dan voor een (groot) deel op query's en code die over de jaren hetzelfde gedrag moeten blijven vertonen.
  • Bitemporele opslag van payloads (zie de bitemporele payloadstore): per toestandsprojectie-element wordt de payload zoals deze verstrekt kan worden, vastgelegd, per geldigheids- en systeemtijdstippen. De query wordt eenvoudig en reduceert tot het opzoeken van één payload op basis van id en tijdstippen; de prijs is een eigen projectie per informatievraag.
  • Hybride oplossing: opslag van payloads, maar dan met extra cellen om in queries te kunnen filteren en te aggregeren.

Volledig verloop

Het volledig verloop bevat ook de elementen die het register ooit onderschreef maar inmiddels niet meer. Dit verloop kan op twee verschillende manieren verstrekt worden:

  • Als continue stroom van notificaties: elk gevolg (of een subset daarvan) leidt tot één of meerdere notificaties die direct aan afnemers geleverd wordt.
  • Als opvraagbare reeks per entiteit of entiteiten.

Omdat al het gebeuren gecommuniceerd wordt inclusief correcties levert deze wijze van leveren een bitemporeel beeld van de registratie.

Deze vorm lijkt het sterkst op het gevolgenjournaal zelf – en is het toch niet. Het journaal beschrijft vanuit bijhoudingsperspectief wat er binnen de bounded context gebeurde; een projectie vertaalt die naar een afgeleid gebeuren waar de afnemer naar kijkt, zoals het intermezzo 'van gevolg naar projectie' bij het projectieperspectief hierboven illustreert.

Onderschreven verloop

Het onderschreven verloop lijkt qua vorm sterk op het volledige verloop, en dus ook op het gevolgenjournaal, maar is dit niet. De vorm is hetzelfde, maar de inhoud niet. Niet langer onderschreven gevolgen worden gefilterd, correcties voegen nieuwe gebeuren toe. Het onderschreven verloop is dus expliciet een gebeuren-projectie.

Het verloop van gebeurenprojectie-elementen die het register nu onderschrijft kan je niet streaming leveren, enkel op verzoek (per entiteit of entiteiten). Indien er behoefte is aan herhaalbaarheid voor deze vraag dienen deze onderschreven gebeuren-projecties bitemporeel vastgelegd te worden bij elk gevolg dat met terugwerkende kracht werkt.

Beslisboom: perspectief, temporaliteit en opslagvorm

Nu we verschillende implementatievormen en hun kenmerken beschreven hebben is het zaak om te weten welke variant we onder welke omstandigheden zouden kiezen. Om hierbij te helpen hebben we een 'beslisboom' geformuleerd, die leidt tot een projectiekeuze.

Een dergelijke boom heet een beslisboom, maar ook hier geldt dat wij vanuit uit betrouwbare bron niet alle domeinspecifieke context mee kunnen wegen. Zie deze boom als een hulpmiddel om tot een keuze te komen en niet meer dan dat.

Beslisboom: welke projectievorm kies ik?

Boom 2: bitemporele toestandsprojectie

Boom 3: opvragen van gebeurenprojectie