Voor een klant ben ik de afgelopen tijd druk bezig geweest met de implementatie van een API die zowel een eigen database benaderd als data uit een backend systeem haalt.
Dit heb ik gedaan door een centrale class te maken die op basis van settings alles afhandeld, met een functiehook die eventuele post processing doet van de resulterende data. Mijn overweging daarbij was dat het zowel een single point of failure als succes was. Deze class bevat inmiddels filtering op het resultaat, paginering, totalen telling, en specifieke zaken als bijvoorbeeld het ophalen van profielbeelden van personen op basis van de id.
De API word door Cypress tests afgetest.
Mijn klant heeft dit laten reviewen door een bedrijf (overigens buiten mijn weten terwijl ik niet de beloofde tijd heb gekregen om de technische schuld in te lossen of de source code review klaar te maken).
Uit dat rapport kwamen diverse aanbevelingen waarvan de meeste inmiddels verwerkt zijn omdat het bekende problemen waren (de technische schuld) of gewoon zinnige aanvullingen/correcties.
Het punt wat is overgebleven is dat het advies is om van de centrale class af te stappen en kleine taakgerichte classes te maken. Dit voornamelijk met als motivatie dat dat beter onderhoudbaar zou zijn.
Ik heb daar moeite mee. Niet alleen vanwege onnodige risico’s op falen (de huidige API is in productie en draait prima), maar ook omdat de klant - met een maatschappelijke doelstelling - forse financiële tegenvallers kent en de kosten voor refactoring daar nog bovenop zouden komen. Daarnaast denk ik dat het juist meer werk is aanpassingen te doen en dat dat door het decentrale karakter ervan juist foutgevoeliger is.
Ik geef een voorbeeld van de huidige vorm en de nieuwe (dit is een simpele variant maar toont de structuur-verschillen goed):
Een mock-up van de voorgestelde aanpassing (dummy code, maar om het idee te duiden):
In mijn visie is een centrale class onderhoudbaarder want nieuwe functionaliteit op 1 plek kan worden gebouwd, getest en geimplementeerd worden met default gedrag voor backwards compatibiliteit.
Zo heb ik laatst de optie voor caching ingebouwd en de API endpoints waar caching gewenst was hoefden alleen een setting met de cache identifier op te nemen. Geen enkele regel code. Als er een bug was geweest had ik die centraal op kunnen lossen.
Bij de voorgestelde nieuwe structuur zullen die API endpoints zelf alle functionaliteit in de endpoint moeten hebben (cache id bepalen, maar ook het ophalen en bewaren)
Bij bugs of aanpassingen aan de logica moet dat dan in iedere endpoint worden gedaan.
En meer code = meer bugs.
Ik heb geprobeerd tussenwegen te bewandelen maar het advies blijft staan. Afscheid nemen van de centrale class is de enige juiste manier.
Donderdag besluit ik op basis van jullie reacties wat ik ga doen. Ik kijk daarom uit naar jullie oprechte mening (alles is welkom zolang onderbouwd) en waardeer nu al de tijd die je erin hebt gestoken om tot zover te lezen!
Dit heb ik gedaan door een centrale class te maken die op basis van settings alles afhandeld, met een functiehook die eventuele post processing doet van de resulterende data. Mijn overweging daarbij was dat het zowel een single point of failure als succes was. Deze class bevat inmiddels filtering op het resultaat, paginering, totalen telling, en specifieke zaken als bijvoorbeeld het ophalen van profielbeelden van personen op basis van de id.
De API word door Cypress tests afgetest.
Mijn klant heeft dit laten reviewen door een bedrijf (overigens buiten mijn weten terwijl ik niet de beloofde tijd heb gekregen om de technische schuld in te lossen of de source code review klaar te maken).
Uit dat rapport kwamen diverse aanbevelingen waarvan de meeste inmiddels verwerkt zijn omdat het bekende problemen waren (de technische schuld) of gewoon zinnige aanvullingen/correcties.
Het punt wat is overgebleven is dat het advies is om van de centrale class af te stappen en kleine taakgerichte classes te maken. Dit voornamelijk met als motivatie dat dat beter onderhoudbaar zou zijn.
Ik heb daar moeite mee. Niet alleen vanwege onnodige risico’s op falen (de huidige API is in productie en draait prima), maar ook omdat de klant - met een maatschappelijke doelstelling - forse financiële tegenvallers kent en de kosten voor refactoring daar nog bovenop zouden komen. Daarnaast denk ik dat het juist meer werk is aanpassingen te doen en dat dat door het decentrale karakter ervan juist foutgevoeliger is.
Ik geef een voorbeeld van de huidige vorm en de nieuwe (dit is een simpele variant maar toont de structuur-verschillen goed):
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
| const apiretrieve = require("../classes/class_retrieve.js"); export default async (req, res) => { const options = { res: res, req: req, result_name: "gegevens", method: "GET", call: "persoon/{ID}?embed=bedrijven", return404: true, skip_userdetails: false } new apiretrieve(options); }); |
Een mock-up van de voorgestelde aanpassing (dummy code, maar om het idee te duiden):
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| const init = require("../classes/init.js"); const user = require("../classes/user.js"); const data = require("../classes/data.js"); const ret = require("../classes/ret.js"); export default async (req, res) => { const context = { req: req, res:res }; init_api( context ); get_user_details ( context ); fetch_data( context, "GET", "persoon/{ID}?embed=bedrijven"); ret_result( context, "gegevens" ) }); |
In mijn visie is een centrale class onderhoudbaarder want nieuwe functionaliteit op 1 plek kan worden gebouwd, getest en geimplementeerd worden met default gedrag voor backwards compatibiliteit.
Zo heb ik laatst de optie voor caching ingebouwd en de API endpoints waar caching gewenst was hoefden alleen een setting met de cache identifier op te nemen. Geen enkele regel code. Als er een bug was geweest had ik die centraal op kunnen lossen.
Bij de voorgestelde nieuwe structuur zullen die API endpoints zelf alle functionaliteit in de endpoint moeten hebben (cache id bepalen, maar ook het ophalen en bewaren)
Bij bugs of aanpassingen aan de logica moet dat dan in iedere endpoint worden gedaan.
En meer code = meer bugs.
Ik heb geprobeerd tussenwegen te bewandelen maar het advies blijft staan. Afscheid nemen van de centrale class is de enige juiste manier.
Donderdag besluit ik op basis van jullie reacties wat ik ga doen. Ik kijk daarom uit naar jullie oprechte mening (alles is welkom zolang onderbouwd) en waardeer nu al de tijd die je erin hebt gestoken om tot zover te lezen!