Code Monkey home page Code Monkey logo

haal-centraal-common's Introduction

Haal-Centraal-common

lint oas

De Haal Centraal common repository is opgezet om zaken die gemeenschappelijk over alle Haal Centraal API's worden toegepast op één plek vast te leggen en te delen.

In de common.yaml een aantal yaml-componenten opgenomen die op diverse plaatsen herbruikt worden. Op het moment dat onderdelen hiervan op een hoger nieveau eenduidig gedefinieerd worden (VNG, Landelijke API-strategie eyc) kan bezien worden of de HC-API's zich daaran conformeren.

Er zijn diverse features opgenomen die in alle Haal Centraal API's van toepassing zijn.

Design decisions die van toepassing zijn op alle Haal Centraal API's zijn opgenomen in het Design Decisions document

haal-centraal-common's People

Contributors

dependabot[bot] avatar fsamwel avatar johanboer avatar melsk-r avatar melvlee avatar rhengeveld avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

haal-centraal-common's Issues

Voorstel tot correcties op design_decisions.md

Bij de review van pull request #26 heb ik een aantal verbetermogelijkheden geconstateerd:

DD1.12 Redundantie in propertynamen weghalen. Dit is het geval wanneer in een propertynaam de gegevensgroepnaam of resourcenaam wordt herhaald waar die in zit.

DD2.1 voorvoegseltabel is geen voorbeeld van een referentielijst met code en waarde.

DD2.1 (90) "Als landelijk beheerde dynamische domeinwaarden ook daadwerkelijk landelijk beschikbaar gesteld worden (zoals de common ground gedachte wel beoogd) dan worden deze als resource ontsloten en dus als link (uri) opgenomen.": dit suggereert dat in dat geval de code en omschrijving niet meer worden meegeleverd en alleen een link. dat is erg onvriendelijk voor de gebruiker. het toevoegen van de link naast de code en omschrijving is dan wel een goed idee, hoewel de toegevoegde waarde erg beperkt is. het volgen van die link geeft namelijk nauwelijks extra informatie. hoogstens sinds wanneer de code in gebruik is. Graag verwijderen.

DD2.2 "wordt altijd de code van de entry gebruikt": hier "altijd" verwijderen

DD2.3 "Enumeraties worden in het bericht opgenomen als waarde": Moet worden: "We gebruiken als enumeratiewaarden betekenisvolle waarden. Dus niet M en V, maar man en vrouw."
Regel 96 t/m 100 (toelichting en ratio bij DD2.3) graag verwijderen, deze klopt niet. Want:
- De reden om een enumeratie op te nemen is omdat het een computerleesbare code moet zijn, niet om deze te tonen aan een persoon (daarvoor kan het ook een normale string zijn). Het is en blijft een code.
- In code wordt een enumeratiewaarde een constante. Je wil in code geen heel lange constantenamen. Enumeratiewaarden zijn regelmatig heel lang.
- In applicaties zal normaal gesproken nooit een enumeratiewaarde direct getoond worden aan een eindgebruiker en het hoeft dus ook niet voor een eindgebruiker vriendelijk leesbaar te zijn.
Dat geldt zelfs al voor codes voor geslacht als "man" en "vrouw". In een implementatie kan dat gebruikt worden om "meneer" en "mevrouw" te tonen, of "hij" en "zij".
- de ratio is dus dat een developer in zijn code moet begrijpen wat de code betekent, om fouten in de implementatie te voorkomen.

DD3.1 Graag verwijderen. Voegt niks toe. Kan hoogstens een opmerking zijn bij DD3.2.

DD3.4 Graag verwijderen. Deze is achterhaald (geldt alleen voor BRP API).

DD4.2 Graag verwijderen. Zo hebben we dat nergens in de HC API's gedaan. We gebruiken functionele datums wanneer die bestaan. En voor einddatums nemen we in de naam op of het een datum tot is of een datum tot en met.

DD4.1 en DD4.3 Vraag ik me af of dit algemene Haal Centraal richtlijnen zijn. Zo hebben we dat gedaan voor BRP. Maar moet dit altijd zo?

DD5.1 Hier moeten we nog over spreken. De beschreven manier toont de descriptions niet in Swagger en het komt ook niet door als comment in gegenereerde code. Ik pleit ervoor het zo op te nemen dat descriptions wel doorkomen in zowel Swagger als gegenereerde code.

DD5.3 Graag algemenere beschrijving: De technische definitie van properties alleen opnemen voor zover noodzakelijk voor gebruik.
Meestal is definitie van properties in de response voldoende met propertynaam, type, format, description en example.
We gebruiken niet pattern, minimum, maximum, minLength, maxLength, minItems, required, tenzij....
Title gebruiken we alleen wanneer de propertynaam afwijkt van de naam in het informatiemodel (en het informatiemodel bekend is bij veel gebruikers).
Enum gebruiken we wanneer (sommige/mogelijke) gebruikers de mogelijke waarden gebruiken in code/algoritmes en daarom moeten weten welke mogelijke waarden er zijn.

DD5.5 Dit is een architectuurprincipe voor HC. Kan veel algemener worden beschreven. We nemen in de API alleen gegevens op die zijn vastgelegd in de bronregistratie van de provider van de API. Een van de consequenties daarvan is DD3.2 het niet embedded van resources uit een andere registratie. Een andere consequentie is het niet opnemen van kerngegevens. Dus de regel is halen bij de bron, een consequentie (toelichting of voorbeeld) is het niet opnemen van gemeentelijke kerngegevens en plusgegevens.

DD5.8 Deze graag verwijderen. Dit impliceert namelijk dat de API specificaties worden ontworpen vanuit het informatiemodel. Zo doen we dat niet. De API wordt ontworpen vanuit user stories, niet vanuit een informatiemodel. Dát moet de ontwerprichtlijn zijn. Hoe dat in een informatiemodel gemodelleerd is, is totaal niet relevant. We gebruiken een gegevenswoordeboek (bij BRK en BAG in de vorm van een informatiemodel, bij BRP in de vorm van het logisch ontwerp) om namen en betekenissen van gebruikte gegevens (properties en soms resources) te kennen en gebruiken.

DD5.11 Deze kan denk ik verwijderd worden. Dit is toch hetzelfde als DD5.10?
Verder graag geen term "indicator" of "attribuut" gebruiken wanneer je "property" bedoelt. We gebruiken JSON(-schema), niet UML. Dus moeten ook JSON termen worden gebruikt: "object", "property" en "array".

definities common.yaml voldoen niet aan DD5.3

DD5.3 Technische definities van properties alleen opnemen voor zover dat noodzakelijk is voor gebruik

Meestal volstaat het om in de definitie van properties in de response de propertynaam, type, format, description en example op te nemen.
We gebruiken daar niet de technische definities pattern, minimum, maximum, minLength, maxLength, minItems en required, tenzij....

  • gebruik minimum en maximum in Datum_onvolledig dag, maand en jaar.
  • minItems en maxItems in de geoJson definities

N.B. waarom zitten geoJson componenten in common.yaml? In BAG en BRK verwijzen we naar definities van opengis , niet naar common.yaml. Volgens mij kunnen die verwijderd worden uit common.yaml

N.B. we kunnen regel toevoegen aan spectral lint om DD5.3 te testen:

  too-much-information:
    description: properties of GET responses should not use pattern, minimum, maximum, minLength, maxLength, minItems or required
    resolved: false
    type: style
    message: 'Gebruik geen {{property}} in response definitie: {{path}}'
    given: '$.components.schemas..properties[*]'
    then:
      - field: "minItems"
        function: falsy

      - field: "maxItems"
        function: falsy

      - field: "maxLength"
        function: falsy

      - field: "maxLength"
        function: falsy

      - field: "minimum"
        function: falsy

      - field: "maximum"
        function: falsy

      - field: "required"
        function: falsy

      - field: "pattern"
        function: falsy

Parameters voldoen niet aan DD1.5

In de common.yaml staan een aantal componenten voor parameters gedefinieerd. Een aantal daarvan voldoet qua 'name' property niet aan DD1.5 waarin wordt gesteld dat namen van endpoints, url's en parameters alleen kleine letters mogen bevatten.
Het gaat om de componenten:

  • datumVan
  • datumTotEnMet
  • pageSize
  • contentCrs
  • acceptCrs

Overigens is DD1.5 denk ik niet helemaal correct aangezien ik vermoed dat endpoints, url's en parameters ook tekens zoals bijv. '-' mogen bevatten.

Splitsen design_decisions.md in ontwerprichtlijnen en architectuurprincipes

design_decisions.md bevat nu twee soorten informatie, die geen van beide echt ontwerpbeslissingen zijn.

Een deel van de inhoud betreft richtlijnen en tips voor een berichtontwerper om tot consistent berichtontwerp te komen.

Een deel van de inhoud betreft architectuurprincipes.

Ik stel voor dat dit dan ook in documenten komt met een naam die duidelijk maakt wat het is, waarvoor het is en voor wie het is: respectievelijk "berichtontwerp_richtlijnen.md" en "architectuurprincipes_Haal_Centraal.md"

(semi) automatisch valideren, resolveer en code genereren

Wanneer er wijzigingen worden gedaan aan de yaml voor een API, moeten we nu handmatig (in Swagger o.i.d.) deze yaml valideren en een resolved versie maken.
Dit is extra werk en bovendien zien we dat vaak wijzigingen alleen worden doorgevoerd op de beheer-yaml en er pas na een aantal (grotere) wijzigingen een nieuwe resolved versie wordt gemaakt.

Via één opdracht (al dan niet in een script of batch bestand) kun je het valideren en resolven automatiseren. Bijvoorbeeld met https://www.npmjs.com/package/swagger-cli.

Het is bovendien mogelijk dit te koppelen aan een pre-commit hook, zodat bij een commit automatisch wordt gecheckt of de te committee yaml wel valide is.

Hiernaast is het voor gebruikers erg handig wanneer er al SDK's beschikbaar zijn. Dan hoeven ze zelf de code niet te genereren. Ik denk dat developers veel blijer worden van een SDK dan van een yaml specificatie.
SDK's genereren kan ook geautomatiseerd, met bijvoorbeeld https://github.com/swagger-api/swagger-codegen

Foutafhandeling features op de common worden op termijn deprecated.

De ervaring leert inmiddels dat foutafhandeling generiek beschrijven een obstakel is om per API- specifieke fout-afhandeling te definiëren. We kiezen er voor om de generieke fout-afhandeling features in Haal Centraal Common deprecated te verklaren als we bij alle API's de spcifieke foutafhandelings-features gerealiseerd hebben.

Verbeteringen aan paginering

N.a.v. opmerkingen @strijm, zie #40 (review)

  1. Toevoegen last link (laatste pagina) aan feature en common.yaml

  2. features/paginering.feature, regel 13:

Wanneer de opgegeven pagina met de page parameter hoger is dan het aantal pagina's resultaat, worden een foutmelding getoond.

Moet worden:

Wanneer de opgegeven pagina met de page parameter hoger is dan het aantal pagina's resultaat, wordt een foutmelding getoond.

  1. features/paginering.feature, regel 54 en 76: toevoegen self link

Foutmelding toevoegen voor foutieve parameter waarden

Als dienst beheerder willen we de foutafhandeling.feature uitbreiden met een foutmelding voor de situatie dat een parameter (een reeks van) karakters bevat die niet is toegestaan.

| validatie | voorbeeld reason | code |
| paramWaarde | Parameter bevat niet toegestane karakters | notAllowedCharacter |

Dit is ten behoeve encoding / escaping voor velden waar geen pattern validatie op zit.
De overige foutmelding zijn niet geschikt voor deze situatie.

Welke foutmelding bij geen path parameter

Als we er vanuit gaan dat met zoekparameter een query parameter wordt bedoeld.In de foutafhandeling feature beschrijving, dan staat er op dit moment niet een scenario beschreven voor de situatie waarbij geen path parameter wordt opgegeven. De beschrijving bij het eerste scenario voldoet niet voor de situatie dat er geen path parameter wordt meegegeven. De beschrijving bij het derde scenario waarbij met een zoekparameter wordt gezocht voldoet niet voor een path parameter.

Kan de feature beschrijving worden aangepast zodat duidelijk wordt hoe de foutmelding eruit moet zien, in het geval er geen path parameter wordt meegegeven.

Voorstel is om het volgende terug te geven:

| Foutsituatie | status | title | code |
| Geen parameter is meegegeven | 400 | Ten minste één parameter moet worden opgegeven. | paramsRequired

| validatie | reason | code |
| required | Parameter is verplicht. | required |

Toevoeging aan Design Decisions nav teambespreking 2-9-2020

Voeg het volgende toe aan de Design Decisions:

Voor een Hal component die alleen bestaat uit _links voldoet de naam aan de volgende syntax:

'xxxHalBasis' (waarbij xxx staat voor de naam van de resource).

Als ook een _embedded moet worden toegevoegd wordt er een extensie gemaakt op 'xxxHalBasis' waarin de _embedded wordt toegevoegd. De naam van dat component voldoet aan de volgende syntax:

'xxxHal' (waarbij xxx wederom staat voor de naam van de resource).

Fields filteren die voorkomen als attribuut en/of als _link onnodig complex

In de fields.feature beschrijving staat dat er gefilterd moet kunnen worden met de fields parameter bv. op:

  1. attribuut pand en/of
  2. _links.pand
    Hiermee kunnen functioneel gezien één van beide of beide parameters worden opgevraagd, dit is conform NL API Strategie Designrules Extension hoofdstuk 7 en 17.15 en compleet en eenduidig.
    De functionaliteit zoals beschreven bij 1 en 2 is functioneel correct, compleet en eenduidig.

Daarnaast is er een constructie beschreven waarbij met bv. fields=pand het volgende opgevraagd kan worden:

  1. het pand attribuut van de resource als dit attribuut bestaat of
  2. _links.pand als er geen pand attribuut in de resource bestaat
    In dit geval werkt pand als een soort alias voor alles in een resource.
    Functioneel gezien voegen 3 en 4 helemaal niets toe aan de fields functionaliteit die bij 1 en 2 zijn beschreven, omdat met 1 en 2 alle parameters al opgevraagd kunnen worden, die is compleet en duidelijk.
    De constructie waarbij met een soort alias wordt gezocht op attributen of _links komt m.i. niet overeen met wat er in de NL API strategie Designrules Extensions hoofdstuk 7 en 17.15 staat:

17.15 API-30: Use query parameters corresponding to the queryable fields
Use unique query parameters that correspond to the fields that can be queried.

Ik maak hieruit op dat de attributen die bij fields worden gebruikt de naam van een attribuut van de resource moet zijn (zonder vermelding van de resource, in dit geval pand) of van een attribuut van een field of subresource (met vermelding van het attribuut/de resource geschieden door '.', in dit geval _links.pand).
Het gebruik van aliassen is hiermee strijdig omdat die het attribuut van een (sub)resource niet uniek identificeert.
Deze constructie maakt de implementatie aan de provider kant tevens onnodig complex en foutgevoelig.
Mijn voorstel en advies is dan ook om de functionaliteit zoals beschreven bij 3 en 4 te laten vervallen uit de fields.feature beschrijving.

Toevoegen aan design_decisions.md (berichtontwerprichtlijnen)

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.

foutbericht instance niet definieren als uri

in Foutbericht wordt instance gedefinieerd als format: uri:

        instance:
          type: string
          format: uri
          description: Uri van de aanroep die de fout heeft veroorzaakt

hierdoor is een relatieve url niet toegestaan, althans niet volgens sommige tooling, zoals Postman.

In Href voor andere links hebben we daarom format: uri verwijderd. Ik denk dat we dat hier ook zouden moeten doen.

@MelvLee @JohanBoer Is dat een breaking change wanneer we dat zouden doorvoeren op een bestaande api?

self link voor collecties bevat altijd page en pageSize

Op dit moment bevat de self link van collecties waarbij pagenering mogelijk is altijd page en pageSize.

Dat is m.i. niet terecht, want deze self link moet de request tonen die geleid heeft tot de getoonde response.

Bijvoorbeeld /adressen/zoek?zoek=bestaatniet%20nootdorp
Dit levert geen resultaten, maar wel page en pageSize toegevoegd aan de self link:

{
   "_links" : {
      "self" : {
         "href" : "https://api.bag.test.kadaster.nl/esd/huidigebevragingen/v1/adressen/zoek?zoek=bestaatniet%20nootdorp&page=1&pageSize=20"
      },
      "first" : {
         "href" : "https://api.bag.test.kadaster.nl/esd/huidigebevragingen/v1/adressen/zoek?zoek=bestaatniet%20nootdorp&page=1&pageSize=20"
      }
   },
   "_embedded" : { }
}

verwijderen vaste naamgeving componenten met underscore

Componenten moeten in UpperCamelCase (== PascalCase) worden opgenomen: DD1.3.

Maar in strijd daarmee nemen we bepaalde componenten op met een underscore: DD1.11: _enum en _tabel

In de praktijk doen we dat ook voor _embedded en _links, maar daar is zo te zien geen regel voor (of ik kijk scheel).

Vanuit consistentie (op DD1.3) zou ik het beter vinden deze underscore weg te halen.

Kan dat nu nog zonder grote consequenties? In BAG en BRK hebben we underscore in de schemacomponent namen gebruikt en deze hebben vastgestelde releases in productie. Of kunnen we die aanpassen in de eerstvolgende release? M.a.w. levert dat breaking changes op?

Bij het toepassen van een linter (#75) levert dit meldingen op. Kan natuurlijk ook in de linter worden opgelost, maar toch...

Fields parameter i.cm. templated links issue

Uit de uri-templating feature lees ik dat als er met een fields parameter op _links wordt gefilterd maar niet op de property (array) die identificaties bevat die ingevuld kunnen worden in een templated link. De lijst altijd geleverd moet worden.

Mijn conclusie is dan, dat er altijd maar één link is en dat het dus niet nodig is om een array van links te hebben.

Bv. de BAG panden links ziet er nu als volgt uit:

Pand_links:
  type: object
  properties:
    self:
      $ref: 'https://raw.githubusercontent.com/VNG-Realisatie/Haal-Centraal-common/v1.0.0/api-specificatie/common.yaml#/components/schemas/HalLink'
    adressen:
      type: array
      items:
        $ref: 'https://raw.githubusercontent.com/VNG-Realisatie/Haal-Centraal-common/v1.0.0/api-specificatie/common.yaml#/components/schemas/HalLink'
    adresseerbareObjecten:
      type: array
      items:
        $ref: 'https://raw.githubusercontent.com/VNG-Realisatie/Haal-Centraal-common/v1.0.0/api-specificatie/common.yaml#/components/schemas/HalLink'

Maar doordat er gebruik wordt gemaakt van URI templates, is er maar één link nodig, dus hoeft er onder adressen en adresserbareObjecten geen array maar één enkele link te staan. Als dit het geval is, moet dan de BAG OAS specificatie hierop aangepast worden?

vullen links bij paginering

Er is discussie over:

  • het opnemen van defaultwaarden in page en pageSize in de self link
  • het opnemen van first (en last) (en previous) op de eerste pagina

n.a.v. opmerking @strijm in #40 (comment):

Hoe weten clients in dit geval om welke pagina het hier gaat? _links.self is er wel maar zonder page en pageSize, _links.first is er niet, _links.prev is er niet en _links.next is er wel. Dat betekent dat een client dus niet uit de self link kan bepalen om welk pagina het hier gaat en dan uit het feit dat er geen _links.first of _links.prev en wel een _links.next moet halen dat het om de eerste pagina gaat? Wat een omslachtige manier van werken. Ik ben er echt voor om gewoon in de self page en pageSize op te nemen, dan is er één gegeven waar een client altijd aan kan zien om welke pagina het gaat. De andere gegevens kunnen dan gebruikt worden om of helemaal naar het begin of helemaal naar het einde van een result set te gaan (altijd) of één pagina terug of verder te gaan (indien aanwezig), supersimpel!
Ik vind het argument dat dit consistent moet zijn met het gedrag van fields en expand niet helemaal kloppen. Ik ben het er wel mee eens dat als deze parameters een default zouden hebben, deze ook gebruikt moeten worden, omdat dat eigenlijk impliciet is wat er door een client is opgegeven, maar fields en expand hebben nu geen default in de specificatie, dus is het gedrag per definitie anders dan van parameters die wel een default hebben.

Als een result set leeg is, kun je erover twisten of er wel of geen pagina is. Geen pagina omdat er geen resultaten zijn of is er één pagina zonder resultaten. M.i. de laatste.
En natuurlijk geven we geen prev en next links terug als een result set leeg is. Prev en next links kunnen immers niet ingevuld worden omdat er geen (andere) pagina's zijn met resultaten. Als er geen pagina is zonder resultaten, dan kunnen ook first en last links niet worden geretourneerd. Als er wel één pagina zonder resultaten is, dan zijn de eerste (en dus ook de laatste pagina) hetzelfde (net als self overigens) en bevatten geen resultaten. We kunnen dus wel altijd een first, last en self link invullen. Dat die soms hetzelfde zijn lijkt me geen probleem, als clients altijd een self link krijgen met page en pageSize weten ze altijd waar ze zijn en met de links kunnen ze bepalen welke mogelijkheden ze hebben qua navigatie.

Reactie @MelvLee:

Ik zou de self link niet wijzigen omdat dit een heel ander doel heeft dan navigatie, maar ik begreep uit een eerdere reactie dat dit het gedrag is van een gebruikte framework. Mijn voorstel is daarom om dan de page en pageSize parameter verplicht te maken omdat deze door de framework toch in alle paging links worden toegevoegd.

Verder vind ik het prima om de first en prev links altijd toe te voegen.

Reactie @fsamwel daarop:

Mijn voorstel is daarom om dan de page en pageSize parameter verplicht te maken omdat deze door de framework toch in alle paging links worden toegevoegd.

We hebben deze specificaties nu in de Haal-Centraal-common zitten. Dat betekent dat deze specificaties ook gelden voor andere API's die paginering gebruiken, zoals voor het Handelsregister.
Ik ben er niet voor om ook voor bijvoorbeeld het HR dingen gedrag te beschrijven (verplichten) omdat voor het BAG een framework is gebruikt die blijkbaar niet voldoende configureerbaar is om het eigenlijk gewenste gedrag te vertonen. Dan moeten we de paginering (parameters) specifiek in de BAG specs opnemen en niet hergebruiken van de common.

Ook zou ik het gek vinden dat een request "/adressen?zoekresultaatidentificatie=adr-5c01945883b0f0390d7a52f8462b0686" een foutmelding zou geven, omdat geen page en pageSize is opgegeven. Bij deze vraag zal er immers maar één adres terugkomen.

Wat bedoel je met "Verder vind ik het prima om de first en prev links altijd toe te voegen."?
Dat je ook wanneer er maar één resultaat is (of zelfs geen resultaat) toch first en previous links worden geleverd? Waarom?

Herformuleren DD1.17

Ik ben niet zo blij met DD1.17. Staat er nu zo dat het verplicht (sterk aanbevolen) is title toe te voegen wanneer er een afwijking is.

DD1.17 Maak gebruik van 'title' (en alleen dan) indien wordt afgeweken van de naam van het corresponderende gegeven in het gegevenswoordenboek

Wanneer er in de naam van een property wordt afgeweken (anders dan toepassen lowerCamelCase, UpperCamelCase en snakeCase) van de naam van het corresponderende gegeven in het gegevenswoordenboek, wordt de naam van dat gegeven in het gegevenswoordenboek opgenomen. Daarbij wordt gebruik gemaakt van het attribuut 'title' in de definitie van het property in de API. In alle andere gevallen wordt 'title' niet opgenomen in de definitie van een property.

Ik denk dat title alleen nodig is wanneer dit begrip in het gegevenswoordenboek voor een bepaalde doelgroep een erg bekend begrip is, en de gekozen naar van het gegeven daar zoveel van afwijkt dat verwijzing naar het andere begrip nodig is. Enig voorbeeld in de Haal Centraal API's tot nu toe dat ik me voor de geest kan halen is geheimhoudingPersoonsgegevens - indicatie geheim.
Andere afwijkingen ("straatnaam" wordt "straat"), zoals inkorten, uitschrijven van een afkorting, enz. maakt de title niet nodig.
In essentie moet gebruik van title dus een grote uitzondering zijn, want waarom zou je zo ver afwijken van het begrip in het gegevenswoordenboek, wanneer dit begrip voor veel gebruikers wel bekend is...

Ik stel de volgende formulering voor:

DD1.17 Maak alleen gebruik van 'title' indien wordt afgeweken van de naam van het corresponderende gegeven in het gegevenswoordenboek

Wanneer er in de naam van een property vergaand wordt afgeweken (anders dan toepassen lowerCamelCase, UpperCamelCase en snakeCase, inkorten, uitschrijven afkorting, enz.) van de naam van het corresponderende gegeven in het gegevenswoordenboek, en vermoed wordt dat dit voor sommige gebruikers verwarring kan veroorzaken, wordt de naam van dat gegeven in het gegevenswoordenboek opgenomen in attribuut 'title' van de property definitie. In alle andere gevallen wordt 'title' niet opgenomen in de definitie van een property.
In deze situaties is het eerst verstandig om de afwijkende naamgeving voor het property nog eens te overwegen.

N.B. mijn voorgestelde zin is zo lang geworden dat waarschijnlijk niemand het meer snapt. Suggesties om dat anders te doen?

Aanpassingen foutafhandeling.feature beschrijving

Graag zien we een uitbreiding van de foutafhandeling feature met een scenario, waarbij uit een set van meerdere parameters er altijd maar één opgegeven kan worden voor de situatie dat er geen queryparameter wordt opgegeven.

Bv. bij de BAG /adressen endpoint kan één van de volgende parameters worden opgegeven:

  • zoekresultaatIdentificatie
  • adresseerbaarObjectIdentificatie
  • pandIdentificatie

Als geen van deze parameters wordt opgegeven, dan moet er een 400 fout worden gegeven, maar het scenario:

Scenario: geen enkele zoekparameter opgegeven in zoekvraag
Als ingeschrevenpersonen worden gezocht zonder parameters
Dan is de http status code van het antwoord 400
En is in het antwoord title=Minimale combinatie van parameters moet worden opgegeven.
En is in het antwoord status=400
En eindigt attribuut instance met /ingeschrevenpersonen
En is in het antwoord code=paramsRequired
En is in het antwoord title=Ten minste één parameter moet worden opgegeven
En komt attribuut invalidParams niet voor in het antwoord

volstaat hier niet. De eerste title is niet van toepassing omdat het niet gaat om een combinatie van parameters maar slechts om één parameter. De tweede title is niet van toepassing omdat er niet tenminste één parameter maar precies één parameter opgegeven moet worden.

Ook de andere scenario's volstaan niet voor deze situatie.

Toevoeging aan Design decisions n.a.v. BAG#234

HaalCentraal BAG issue 234 gaat over de wijze van definiëren van url's voor interne links. Dit kan met absolute urls maar in het issue wordt aangegeven dat relatieve url's de voorkeur hebben.

Ik vraag me af of dit niet ergens in de Design Decision moet landen.
Overigens gaat het hier n.m.m. niet echt om een Design Decision en is het dus de vraag waar het na invoering van #27 moet worden ondergebracht.

Toevoeging aan Design decisions n.a.v. BAG#265?

HaalCentraal BAG issue 265 en het daarmee samenhangende #44 gaat over de interpretatie/implementatie van de 'field' parameter op het moment dat er in een resource, in de _links en/of in een groep een property voorkomt met dezelfde naam.
In de API strategie is uitgelegd hoe deze functionaliteit geïmplementeerd moet worden. In #44 wordt echter een nuancering aangebracht die leidt tot een toevoeging in de functionaliteit zonder dat deze in tegenspraak is met de betreffende paragraaf in de API strategie.

Ik vraag me af of die toevoeging niet in de Design Decision moet worden vermeldt.
Overigens gaat het hier n.m.m. niet echt om een Design Decision en is het dus de vraag waar het na invoering van #27 moet worden ondergebracht.

Pas DD 5.22 aan n.a.v. dubbele $ref in datum.yaml in HC BRP API

In DD5.22 staat nu

Bij gebruik van allOf is er altijd exact één component waarnaar gerefereerd wordt en één gedefinieerd object met ten minste één property.

In het voorstel voor datum.yaml (BRP API) staat echter:

 GbaDatum:
  description: Datum conform LO GBA
  allOf:
    - $ref: '#/components/schemas/AbstractDatum'
    - $ref: '#/components/schemas/GbaDatumBasis'
  required:
    - datum
  example:
    value:
      type: GbaDatum
      datum: "20180700"

dus 2 componenten waarnaar gerefereerd wordt en geen object waarin minimaal één property wordt toegevoegd.
Inmiddels is me duidelijk dat het toch wat genuanceerder ligt. Er mogen maximaal 2 componenten zijn waarnaar gerefereerd wordt omdat C# en .Net maar van 2 objecten kunnen overerven, multieritance wordt daar niet ondersteund. De vraag is echter of de eis dat er daarnaast ook één gedefinieerd object met ten minste één property aanwezig moet zijn in die situatie nog steeds geldt.

Dus, moet het worden:

Bij gebruik van allOf

  • is er exact één component waaraan gerefereerd wordt en één gedefinieerd object met ten minste één property.
  • of zijn er twee en niet meer dan twee componenten waarnaar gerefereerd wordt.

of

Bij gebruik van allOf

  • is er exact één component waaraan gerefereerd wordt en één gedefinieerd object met ten minste één property.
  • of zijn er twee en niet meer dan twee componenten waarnaar gerefereerd wordt met optioneel nog één gedefinieerd object met ten minste één property.

of ligt het nog genuanceerder?

Descriptions in v1.3.0 (master) van hallink, expand en fields verwijzen naar features op v1.2.0

bijvoorbeeld:

    expand:
      name: expand
      in: query
      required: false
      description: "Hiermee kun je opgeven welke gerelateerde resources meegeleverd moeten worden, en hun inhoud naar behoefte aanpassen. Hele resources of enkele properties geef je in de expand parameter kommagescheiden op. Properties die je wil ontvangen geef je op met de resource-naam gevolgd door de property naam, met daartussen een punt. In de definitie van het antwoord kun je bij _embedded zien welke gerelateerde resources meegeleverd kunnen worden. Zie [functionele specificaties](https://github.com/VNG-Realisatie/Haal-Centraal-common/blob/v1.2.0/features/expand.feature)."
      schema:
        type: string
    fields:
      name: fields
      in: query
      required: false
      description: "Hiermee kun je de inhoud van de resource naar behoefte aanpassen door een door komma's gescheiden lijst van property namen op te geven. Bij opgave van niet-bestaande properties wordt een 400 Bad Request teruggegeven. Wanneer de fields parameter niet is opgegeven, worden alle properties met een waarde teruggegeven. Zie [functionele specificaties](https://github.com/VNG-Realisatie/Haal-Centraal-common/blob/v1.2.0/features/fields.feature)"
      schema:
        type: string

onnodig lange relatienamen volgens conventie

ik ben (achteraf) niet zo blij met de naamgevingsconventie in de design decisions op relaties:

Relaties: De naam van de relatie plus de naam van de gerelateerde resource, tenzij er een reden is om dat niet te doen.

(ook al heb ik dit zelf eerder in een comment ingetypt: VNG-Realisatie/BAG-Gemeentelijke-wensen-tav-BAG-Bevragingen#42 (comment))

Bijvoorbeeld een adres heeft een property woonplaats en ook een link naar de resource woonplaats. Waarom moet dat dan ligtInWoonplaats zijn? Had het property dan ook ligtInWoonPlaatsNaam moeten heten?

Bijvoorbeeld bij een zakelijk recht horen een aantal stukken. Moeten de relaties daarnaartoe dan in isGebaseerdOpStukken en isVermeldInStukken? Tot nu toe is volstaan met de relatie stukken.

We nemen meestal relaties op twee mogelijke manieren op:

  • de identificatie van de gerelateerde resource. Bijvoorbeeld "openbareRuimteIdentificatie"
  • een HAL link naar de gerelateerde resource.

Deze naamgevingsconventie zegt niet expliciet over welke vorm van relatie opnemen we het hebben. Ik neem aan dat bedoeld wordt relaties in HAL links.

Mijn bezwaren:

  1. hiermee committeren we ons aan een directe koppeling met de relatie en elementnaam uit (een versie van) een informatiemodel
  2. propertynamen worden onnodig lang. Bijvoorbeeld een relatie van een persoon naar diens adres is duidelijk genoeg met "adres". Relatienaam "verblijftOpAdres" is niet duidelijker.
    Soms is de naam van de resource duidelijker en voldoende (bijvoorbeeld "woonplaats" voor de ligt in relatie van een adres naar de woonplaats-resource), soms is de naam van de relatie duidelijker (bijvoorbeeld een persoon heeft relaties naar ouders, partners en kinderen die allemaal personen zijn), dan zijn de naam van alleen de resource of alleen de relatie niet duidelijk of ambigu, zodat je beide moet gebruiken.
  3. HAL-links zijn bedoeld om de gebruiker te helpen, dus voor discoverability. Het is niet bedoeld om relaties aan te duiden, maar deze naamgevingsconventie suggereert dit wel met het aanduiden van HAL links als relaties en het "dwingen" om deze naar de relatie te benoemen.

Paginering headers toevoegen

Omdat bij een POST request met geoemtrie geen paginering links geretourneerd kunnen worden moet de paginering informatie met headers worden teruggegeven aan de client. Daarbij kwamen we erachter dat de volgende headers ontbreken:

X-Total-Count
X-Pagination-Count

Bij deze het verzoek deze toe te voegen en een nieuwe release te maken zodat we die release kunnen gebruiken in de HC BAG Bevragen API specificatie.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.