Ik stel een aantal toevoegingen voor op de richtlijnen voor berichtontwerp:
De identificatie van een resource zit, wanneer die is opgenomen in de resource anders dan in _links.self, en gebruikt wordt als path-parameter van het resource-endpoint, altijd op het hoogste niveau van de resource in de vorm en inhoud zoals die wordt opgenomen in de uri (path-parameter) van de resource.
We nemen geen waarden op met een speciale betekenis die afwijkt van de normale betekenis van het gegeven.
bijvoorbeeld datum "0000-00-00" om aan te geven dat een datum onbekend is
bijvoorbeeld landcode "0000" om aan te geven dat het land onbekend is
We nemen geen reden op over het leeg/afwezig zijn van een waarde van een gegeven (zoals met StUF:noValue werd gedaan), tenzij duidelijk is dat er bij de gebruikers behoefte is om dit te weten.
Wanneer het gevuld zijn van een datum functionele betekenis heeft, ook wanneer deze volledig onbekend is, wordt een indicator opgenomen om dit aan te geven. Bijvoorbeeld of een persoon overleden is kan niet worden afgeleid uit het bestaan van een overlijdensdatum wanneer die datum onbekend is. Daarvoor kan een boolean "indicatieOverleden" worden gedefinieerd.
Eigenschappen die functioneel alleen een waarde Ja/aan/waar of Nee/uit/onwaar kunnen hebben, worden gedefinieerd als boolean. We gebruiken dus geen enumeratie zoals [J,N] voor dit soort situaties.
Wanneer een gegeven in het informatiemodel gedefinieerd is als enumeratie, maar de enumeratiewaarde door gebruikers van de API alleen gebruikt wordt om als tekst te tonen aan eindgebruikers (mensen), dan als string (niet als enumeratie) definiëren in de API.
Wanneer de enumeratiewaarde gebruikt wordt in code (algoritmes), dan betekenisvolle maar bondige code.
Ratio
Opnemen van de enumeratie in de API is een vorm van tight coupling
We gebruiken als enumeratiewaarden betekenisvolle waarden. Dus niet M en V, maar man en vrouw.
De lengte van enumeratiewaarden wordt beperkt. Bijvoorbeeld "Opstalhouder Nutsvoorzieningen op gedeelte van perceel" krijgt als code "nutsvoorzieningen_gedeelte".
Enumeratiewaarden worden opgenomen in snake_case.
We vermijden het gebruik van afkortingen in propertynamen. Propertynamen moeten zoveel mogelijk zelfverklarend zijn.
Gegevens in een resource moeten kunnen worden gebruikt en geïnterpreteerd zonder domeinkennis of complexe algoritmes.
We gebruiken geen oneOf of anyOf constructies voor polymorfe gegevens. Wanneer er veel overlap is en geen strijdigheid tussen de verschillende mogelijke types, worden ze platgeslagen tot één resource of één object. Alternatief is voor elk type een property op te nemen, met daarin de eigenschappen van dat type. In beide gevallen nemen we ook een type property op waaruit de gebruiker kan lezen welk type het betreft.
Wanneer er voor een begindatum of einddatum al een functioneel gegeven bestaat, gebruiken we die. Denk aan datumOntbindingHuwelijk of datumAanvangAdreshouding.
Voor einddatums moet er altijd expliciet in de naam staan of het "tot" of "totEnMet" is.
Als queryparameters voor het historisch opvragen gebruiken we "peildatum", "datumvan" en "datumtotenmet"
Wanneer er geen functioneel gegeven bestaat in het model voor einddatum, maar daar is wel behoefte aan (omdat historie getoond wordt) gebruiken we "datumTot". Bijvoorbeeld in BRP wordt alleen de begindatum van een verblijfplaats geregistreerd, geen einddatum, dus is datumTot=datumAanvang van de volgende verblijfplaats.
Wanneer er een gegevenswoordenboek (gegevenscatalogus, informatiemodel) bestaat, gebruiken we voor corresponderende resource of voor corresponderende properties in een resource de naam zoals die in het gegevenswoordenbook staat, met inachtneming van de naamgevingsrichtlijnen zoals die in dit document staan benoemd, zoals gebruik (Upper)snakeCase.
Van de naam in het gegevenswoordenboek kan worden afgeweken in o.a. de volgende situaties:
Weglaten van redundatie in de naam. Bijvoorbeeld "geboortedatum" in een gegevensgroep geboorte nemen we op als "datum".
Uitschrijven van afkortingen. Bijvoorbeeld "BSN" nemen we op als "burgerservicenummer".
Toevoegen van context, bijvoorbeeld wanneer het gegeven in een andere context wordt gebruikt dan in het gegevenswoordenboek. Bijvoorbeeld het opnemen van gegeven "identificatie" van een woonplaats bij een nummeraanduiding wordt property "woonplaatsIdentificatie"
Een van het gegeven via een algoritme afgeleide property. Bijvoorbeeld "leeftijd" van "geboortedatum".
Wanneer er in de naam van een property wordt afgeweken (anders dan toepassen snakeCase) van de naam van het corresponderende gegeven in het gegevenswoordenboek, wordt de naam van dat gegeven in het gegevenswoordenboek opgenomen in attribuut "title" in de definitie van het property in API. In alle andere gevallen wordt title niet opgenomen in de definitie van een property.
We nemen bij een property een description op die semantisch overeenkomt met de beschrijving in het gegevenswoordenboek. Deze kan ingekort, vereenvoudigd, of uitgebreid zijn, maar mag de betekenis van het gegeven niet laten afwijken van de betekenis van het corresponderende gegeven in het gegevenswoordenboek.
De description kan worden weggelaten wanneer evident is dat de gebruikers van de API uit de propertynaam weten wat bedoeld wordt (bijvoorbeeld huisnummer).
In de description van een property mag geen logica (algoritme) worden beschreven voor het samenstellen de inhoud van het property.
Ratio
Opnemen van providerlogica veroorzaakt tight coupling tussen de bron-implementatie en de API.
Er is geen directe koppeling tussen de definitie en structuur van gegevens in een gegevenswoordenboek (informatiemodel) en de definitie en structuur van de corresponderende resource en/of propertie in een API.
Voorbeelden:
Een resource mag meer gegevens bevatten dan het corresponderende object uit het gegevenswoordenboek. Er mogen bijvoorbeeld gegevens uit gerelateerde objecten aan de resource worden toegevoegd. Bijvoorbeeld bij een nummeraanduiding wordt de woonplaatsnaam opgenomen.
Een resource mag minder gegevens bevatten dan het corresponderende objecttype. In de resource worden alleen gegevens opgenomen waar behoefte aan is bij de gebruikers van de API.
Verschillende elementen uit het object mogen worden samengevoegd tot éen property van de resource. Bijvoorbeeld aanschrijfwijze is samengesteld uit o.a. voornamen, tussenvoegsel en geslachtsnaam.
Een element uit een model mag worden opgesplitst in meerdere properties in de resource. Bijvoorbeeld een mogelijk onbekende overlijdensdatum kan worden opgenomen als overlijdensdatum én indicatieOverleden.
Een abstract objecttype mag als (concrete) resource worden gedefinieerd. Bijvoorbeeld adresseerbaar object wordt resource adresseerbareObjecten.
Gegevens uit verschillende (gegevens)groepen mogen worden platgeslagen in de resource of in een gegevensgroep. Bijvoorbeeld Gemeente van inschrijving uit groep Inschrijving, functie adres uit groep Verblijfplaats en postcode uit groep Adres worden opgenomen in verblijfplaats.
Een resource mag gegevens opnemen in een andere representatievorm.
Bijvoorbeeld Indicatie geheim kan waarden 0 (niet geheim) of 7 (geheimhouding) hebben in het informatiemodel, maar in de API wordt dit opgenomen als boolean.
Bijvoorbeeld enumeratie Type openbare ruimte wordt opgenomen als string, wanneer deze waarde alleen voor mensenogen bedoeld is en niet door computercode geïnterpreteerd hoeft te worden.
Ratio
koppeling met de implementatie van de provider registratie beperkt de evolvability van zowel de achterliggende systemen, als van de applicaties die de API gebruiken als van de API zelf.
ontwerp van de resource gericht op de informatiebehoefte en het gebruik is eenvoudiger in gebruik en verkleint kan op verkeerd gebruik.
Wanneer in een API (comfort)gegevens worden opgenomen die authentiek zijn opgeslagen in een andere bron, worden deze bij voorkeur gemodelleerd op dezelfde manier als in de bron. Wanneer mogelijk wordt hergebruik gemaakt van de API specificatie van de andere bron (via $ref).
Bijvoorbeeld het adres (BAG) van een ingeschreven persoon (BRP) of vestiging (HR). Bijvoorbeeld de naam en geboortedatum (BRP) van een eigenaar in BRK of functionaris in HR.
Wanneer er meerdere componenten zijn met meerdere dezelfde properties, moet er hergebruik worden gemaakt via een allOf constructie). Dit sluit aan op object oriëntatie in de verschillende programmeeromgevingen.
Bijvoorbeeld een woonadres en een postadres zijn identiek, behalve dat postadres ook een postbusnummer kent. Dan is postadres een extensie op woonadres.
Bijvoorbeeld een natuurlijk persoon en een niet-natuurlijk persoon hebben beide een naam en een adres, maar beide hebben ook eigen gegevens (natuurlijk persoon heeft geboortedatum, niet-natuurlijk persoon heeft eigenaar), dan zijn beide een extensie op een bovenliggende component "Persoon".
Bijvoorbeeld bij een zakelijkGerechtigde worden alleen minimale identificerende gegevens van een persoon opgenomen (alleen naam en identificatie), maar bij de persoon (resource) worden meer eigenschappen van de persoon opgenomen (zoals adres). Dan gebrukt zakelijkGerechtigde component "persoonBeperkt" en is de uitgebreide persoon een extensie hierop.
Bij gebruik van allOf staat de component die hergebruikt wordt altijd eerst, en staan de toegevoegde properties als tweede.
Bijvoorbeeld correct gebruik van allOf:
NaamPersoon:
allOf:
- $ref: "#/components/schemas/Naam"
- description: "Gegevens over de naam van de persoon"
properties:
aanhef:
type: "string"
Bijvoorbeeld fout gebruik van allOf:
NaamPersoon:
allOf:
- description: "Gegevens over de naam van de persoon"
properties:
aanhef:
type: "string"
- $ref: "#/components/schemas/Naam"
Ratio
Afwijken van deze regel leidt tot problemen bij het genereren van code uit de API specificaties.
Bij gebruik van allOf is er altijd exact één component waarnaar gerefereerd wordt en één gedefinieerd object met ten minste één property.
Bijvoorbeeld fout gebruik van allOf, want overerving uit twee componenten:
NaamPersoon:
allOf:
- $ref: "#/components/schemas/Naam"
- $ref: "#/components/schemas/Aanschrijfwijze"
- description: "Gegevens over de naam van de persoon"
properties:
aanhef:
type: "string"
Bijvoorbeeld fout gebruik van allOf, want heeft geen eigen properties:
NaamPersoon:
allOf:
- $ref: "#/components/schemas/Naam"
- description: "Gegevens over de naam van de persoon"
Ratio
Afwijken van deze regel leidt tot problemen bij het genereren van code uit de API specificaties.
Ik stel een aantal toevoegingen voor op de richtlijnen voor berichtontwerp:
De identificatie van een resource zit, wanneer die is opgenomen in de resource anders dan in _links.self, en gebruikt wordt als path-parameter van het resource-endpoint, altijd op het hoogste niveau van de resource in de vorm en inhoud zoals die wordt opgenomen in de uri (path-parameter) van de resource.
We nemen geen waarden op met een speciale betekenis die afwijkt van de normale betekenis van het gegeven.
We nemen geen reden op over het leeg/afwezig zijn van een waarde van een gegeven (zoals met StUF:noValue werd gedaan), tenzij duidelijk is dat er bij de gebruikers behoefte is om dit te weten.
Wanneer het gevuld zijn van een datum functionele betekenis heeft, ook wanneer deze volledig onbekend is, wordt een indicator opgenomen om dit aan te geven. Bijvoorbeeld of een persoon overleden is kan niet worden afgeleid uit het bestaan van een overlijdensdatum wanneer die datum onbekend is. Daarvoor kan een boolean "indicatieOverleden" worden gedefinieerd.
Eigenschappen die functioneel alleen een waarde Ja/aan/waar of Nee/uit/onwaar kunnen hebben, worden gedefinieerd als boolean. We gebruiken dus geen enumeratie zoals [J,N] voor dit soort situaties.
Wanneer een gegeven in het informatiemodel gedefinieerd is als enumeratie, maar de enumeratiewaarde door gebruikers van de API alleen gebruikt wordt om als tekst te tonen aan eindgebruikers (mensen), dan als string (niet als enumeratie) definiëren in de API. Wanneer de enumeratiewaarde gebruikt wordt in code (algoritmes), dan betekenisvolle maar bondige code.
Ratio Opnemen van de enumeratie in de API is een vorm van tight coupling
We gebruiken als enumeratiewaarden betekenisvolle waarden. Dus niet M en V, maar man en vrouw.
De lengte van enumeratiewaarden wordt beperkt. Bijvoorbeeld "Opstalhouder Nutsvoorzieningen op gedeelte van perceel" krijgt als code "nutsvoorzieningen_gedeelte".
Enumeratiewaarden worden opgenomen in snake_case.
We vermijden het gebruik van afkortingen in propertynamen. Propertynamen moeten zoveel mogelijk zelfverklarend zijn.
Gegevens in een resource moeten kunnen worden gebruikt en geïnterpreteerd zonder domeinkennis of complexe algoritmes.
We gebruiken geen oneOf of anyOf constructies voor polymorfe gegevens. Wanneer er veel overlap is en geen strijdigheid tussen de verschillende mogelijke types, worden ze platgeslagen tot één resource of één object. Alternatief is voor elk type een property op te nemen, met daarin de eigenschappen van dat type. In beide gevallen nemen we ook een type property op waaruit de gebruiker kan lezen welk type het betreft.
Wanneer er voor een begindatum of einddatum al een functioneel gegeven bestaat, gebruiken we die. Denk aan datumOntbindingHuwelijk of datumAanvangAdreshouding. Voor einddatums moet er altijd expliciet in de naam staan of het "tot" of "totEnMet" is. Als queryparameters voor het historisch opvragen gebruiken we "peildatum", "datumvan" en "datumtotenmet" Wanneer er geen functioneel gegeven bestaat in het model voor einddatum, maar daar is wel behoefte aan (omdat historie getoond wordt) gebruiken we "datumTot". Bijvoorbeeld in BRP wordt alleen de begindatum van een verblijfplaats geregistreerd, geen einddatum, dus is datumTot=datumAanvang van de volgende verblijfplaats. Wanneer er een gegevenswoordenboek (gegevenscatalogus, informatiemodel) bestaat, gebruiken we voor corresponderende resource of voor corresponderende properties in een resource de naam zoals die in het gegevenswoordenbook staat, met inachtneming van de naamgevingsrichtlijnen zoals die in dit document staan benoemd, zoals gebruik (Upper)snakeCase. Van de naam in het gegevenswoordenboek kan worden afgeweken in o.a. de volgende situaties:
Wanneer er in de naam van een property wordt afgeweken (anders dan toepassen snakeCase) van de naam van het corresponderende gegeven in het gegevenswoordenboek, wordt de naam van dat gegeven in het gegevenswoordenboek opgenomen in attribuut "title" in de definitie van het property in API. In alle andere gevallen wordt title niet opgenomen in de definitie van een property.
We nemen bij een property een description op die semantisch overeenkomt met de beschrijving in het gegevenswoordenboek. Deze kan ingekort, vereenvoudigd, of uitgebreid zijn, maar mag de betekenis van het gegeven niet laten afwijken van de betekenis van het corresponderende gegeven in het gegevenswoordenboek. De description kan worden weggelaten wanneer evident is dat de gebruikers van de API uit de propertynaam weten wat bedoeld wordt (bijvoorbeeld huisnummer).
In de description van een property mag geen logica (algoritme) worden beschreven voor het samenstellen de inhoud van het property.
Ratio Opnemen van providerlogica veroorzaakt tight coupling tussen de bron-implementatie en de API.
Er is geen directe koppeling tussen de definitie en structuur van gegevens in een gegevenswoordenboek (informatiemodel) en de definitie en structuur van de corresponderende resource en/of propertie in een API. Voorbeelden:
Ratio
Wanneer in een API (comfort)gegevens worden opgenomen die authentiek zijn opgeslagen in een andere bron, worden deze bij voorkeur gemodelleerd op dezelfde manier als in de bron. Wanneer mogelijk wordt hergebruik gemaakt van de API specificatie van de andere bron (via $ref). Bijvoorbeeld het adres (BAG) van een ingeschreven persoon (BRP) of vestiging (HR). Bijvoorbeeld de naam en geboortedatum (BRP) van een eigenaar in BRK of functionaris in HR.
Wanneer er meerdere componenten zijn met meerdere dezelfde properties, moet er hergebruik worden gemaakt via een allOf constructie). Dit sluit aan op object oriëntatie in de verschillende programmeeromgevingen.
Bij gebruik van allOf staat de component die hergebruikt wordt altijd eerst, en staan de toegevoegde properties als tweede. Bijvoorbeeld correct gebruik van allOf:
Bijvoorbeeld fout gebruik van allOf:
Ratio Afwijken van deze regel leidt tot problemen bij het genereren van code uit de API specificaties.
Bij gebruik van allOf is er altijd exact één component waarnaar gerefereerd wordt en één gedefinieerd object met ten minste één property. Bijvoorbeeld fout gebruik van allOf, want overerving uit twee componenten:
Bijvoorbeeld fout gebruik van allOf, want heeft geen eigen properties:
Ratio Afwijken van deze regel leidt tot problemen bij het genereren van code uit de API specificaties.