Vandaar dat URL al een hele tijd deprecated is
Edit: Spuit 11.
[ Voor 3% gewijzigd door Hydra op 15-12-2021 17:59 ]
https://niels.nu
Vandaar dat URL al een hele tijd deprecated is
[ Voor 3% gewijzigd door Hydra op 15-12-2021 17:59 ]
https://niels.nu
Maar op z'n PHPsiaans nooit echt verwijderd ?Hydra schreef op woensdag 15 december 2021 @ 17:57:
[...]
Vandaar dat URL al een hele tijd deprecated is
Toen zijn een aantal Java ontwikkelaars Javascript gaan ontwikkelen, wat alles beter moest maken. Een betere taal, een beter ecosysteem.
[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]
We don’t need everyone to upgrade log4j, just enough for herd immunity to takeover
— Ricky (@rickhanlonii) 12 december 2021
[ Voor 56% gewijzigd door Firesphere op 16-12-2021 09:54 ]
I'm not a complete idiot. Some parts are missing.
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
We don’t need everyone to upgrade log4j, just enough for herd immunity to takeover
— Ricky (@rickhanlonii) 12 december 2021
Nouja, URL domweg verwijderen zou echt een hoop dingen stukmaken. Java maakt in principe geen breaking API changes. Da's ook de reden dat collections zoals Vector nog in de API zitten.gekkie schreef op woensdag 15 december 2021 @ 17:59:
Maar op z'n PHPsiaans nooit echt verwijderd ?
https://niels.nu
Nee, om dezelfde reden dat ze ontwerpfouten nooit hebben rechtgetrokken: backwards compatibility. Je kunt een programma gemaakt voor JDK 1.5 draaien op bijvoorbeeld JDK 17. Als ze het verwijderen kan dat niet meer.gekkie schreef op woensdag 15 december 2021 @ 17:59:
[...]
Maar op z'n PHPsiaans nooit echt verwijderd ?
Of Python waar men weet ik hoe lang twee parallelle versies in stand hield.mcDavid schreef op donderdag 16 december 2021 @ 11:09:
Wat dat betreft een sterk contrast met PHP wat bijvoorbeeld de `mysql` api gewoon verwijderd heeft toen er iets beters voor in de plaats gekomen was.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Heeft ook wel even geduurd en ik ben nu met PHP ook wel weer de andere kant tegen gekomen, met een prestashopje vast zitten omdat er geen upgrade path was met de php versies van Debian, omdat de handel ineens heel snel deprecated en vervolgens verwijderd werd, althans duidelijk sneller dan de Debian release cycle.mcDavid schreef op donderdag 16 december 2021 @ 11:09:
Wat dat betreft een sterk contrast met PHP wat bijvoorbeeld de `mysql` api gewoon verwijderd heeft toen er iets beters voor in de plaats gekomen was.
[ Voor 12% gewijzigd door gekkie op 16-12-2021 12:29 ]
Maar dat is toch een extensie die gewoon weer kan instaleren? Mysql (zonder i) word nog steeds genoeg gebruikt door bv. wordpress.mcDavid schreef op donderdag 16 december 2021 @ 11:09:
Wat dat betreft een sterk contrast met PHP wat bijvoorbeeld de `mysql` api gewoon verwijderd heeft toen er iets beters voor in de plaats gekomen was.
Neuh, die extension is vanaf de 7.0 branch al niet meer beschikbaar. Ook niet voor wordpress.RagingPenguin schreef op donderdag 16 december 2021 @ 12:35:
[...]
Maar dat is toch een extensie die gewoon weer kan instaleren? Mysql (zonder i) word nog steeds genoeg gebruikt door bv. wordpress.
Nee, maar er zijn wel shims beschikbaar online om het toch werkend te krijgen.RagingPenguin schreef op donderdag 16 december 2021 @ 12:35:
[...]
Maar dat is toch een extensie die gewoon weer kan instaleren? Mysql (zonder i) word nog steeds genoeg gebruikt door bv. wordpress.
🠕 This side up
Ah, dan zijn we toch iets verder dan ik dachtmcDavid schreef op donderdag 16 december 2021 @ 13:43:
[...]
Neuh, die extension is vanaf de 7.0 branch al niet meer beschikbaar. Ook niet voor wordpress.
Volgens mij is het beveiligingsverschil tussen mysqli_ en mysql_ niet zo groot, of mis ik iets? Het grootste verschil is voor mijn gevoel of de connectie globaal is of dat je 'm steeds in de functie moet meegeven.RagingPenguin schreef op donderdag 16 december 2021 @ 16:24:
[...]
Ah, dan zijn we toch iets verder dan ik dacht
🠕 This side up
Vooral het verschil tussen de nieuwe library en de oude, outdated libraryKoenvh schreef op donderdag 16 december 2021 @ 19:57:
[...]
Volgens mij is het beveiligingsverschil tussen mysqli_ en mysql_ niet zo groot, of mis ik iets? Het grootste verschil is voor mijn gevoel of de connectie globaal is of dat je 'm steeds in de functie moet meegeven.
Mysql heeft geen prepared statements, mysqli wel. Dat is de enige aceptable manier om sql-injecties tegen te gaan, geklooi met het escapen van user input terwijl je strings aan elkaar plakt heeft een te grote kans om fout te gaan. Daarnaast ondersteund mysql i.t.t mysqli ook geen connecties over SSL. Dat zou genoeg redenen moeten zijn om mysql nooit te willen gebruiken.Koenvh schreef op donderdag 16 december 2021 @ 19:57:
[...]
Volgens mij is het beveiligingsverschil tussen mysqli_ en mysql_ niet zo groot, of mis ik iets? Het grootste verschil is voor mijn gevoel of de connectie globaal is of dat je 'm steeds in de functie moet meegeven.
Aha, het oude project had geen user input, en de server draaide op localhost, dus daar ben ik nooit achter gekomen (zelf verder nooit met mysql_ gewerkt).RagingPenguin schreef op donderdag 16 december 2021 @ 20:20:
[...]
Mysql heeft geen prepared statements, mysqli wel. Dat is de enige aceptable manier om sql-injecties tegen te gaan, geklooi met het escapen van user input terwijl je strings aan elkaar plakt heeft een te grote kans om fout te gaan. Daarnaast ondersteund mysql i.t.t mysqli ook geen connecties over SSL. Dat zou genoeg redenen moeten zijn om mysql nooit te willen gebruiken.
🠕 This side up
Nouja voor 7.x gebeurde dat niet of zelden, ze zijn nu in de versnelling gegaan om het wel te doen, soms nog wel eens iets te vlot althans voor mij als eindgebruiker bij de combinatie met distropackages van stable distro'smcDavid schreef op donderdag 16 december 2021 @ 20:25:
ik haalde het vooral op als voorbeeld dat PHP echt niet bang is backward compatibility te breken, zoals @gekkie impliceerde. Ik had ook register_globals of zo kunnen noemen. Maar er zijn ook genoeg moderne voorbeelden
Toch gaan ze dat in nieuwere java versies wel doen.ThomasG schreef op donderdag 16 december 2021 @ 10:44:
[...]
Nee, om dezelfde reden dat ze ontwerpfouten nooit hebben rechtgetrokken: backwards compatibility. Je kunt een programma gemaakt voor JDK 1.5 draaien op bijvoorbeeld JDK 17. Als ze het verwijderen kan dat niet meer.
1
| @Deprecated(since = "4.5", forRemoval = true) |
let the past be the past.
Dit zie ik ook veel te veel.Mugwump schreef op dinsdag 14 december 2021 @ 18:34:
Ondanks dat het sarcastisch is leg ik soms wel degelijk dat soort regeltjes op. Als er bijvoorbeeld duidelijk afspraken zijn over wat je controleert bij een MR, maar je hebt er een paar bij die twee seconden kijken en goedkeuring geven zonder dat er enig benul is van wat de MR beoogt en of het dat ook doet, dan voer ik gewoon heel kinderachtig administratieve processen in de vorm van checklistjes in of iets dergelijks.
https://fgheysels.github.io/
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
Ik maak inderdaad gewoon een lijstje van dingen die gecheckt moeten worden en dan in bepaalde vorm verplichten dat de reviewer een afgevinkt lijstje oplevert, evt met bevindingen als ze echt hardnekkig zijn.whoami schreef op donderdag 16 december 2021 @ 23:57:
[...]
Dit zie ik ook veel te veel.
Een pull-request met wijzigingen in 20 files ofzo, en dan binnen 2 minuten 'approved'.
Wat houden die 'administratieve processen' precies in ? Ik maak soms PR-templates, maar dat is dan vooral voor diegen die de pull-request maakt. (Unit tests gemaakt ? Documentatie aangepast ? etc... ).
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Controleren of unit tests correct / zinvol zijn kan ook weer gedeeltelijk automatisch. Dit middels mutation testing waarbij "bugs in de code worden toegepast" (bv > aanpassen naar >=. Of hardcoded numbers aanpassen naar een +1 en -1 variant) en dan zou dus op zijn minst een unit test moeten falen. Faalt geen enkele test dan zijn de tests dus ook niet goed. Bijvoorbeeld dat niet goed op een edge wordt getest bij een > vs >=. Of als je langere/complexere condities hebt met && en/of || dat blijkt dat een bepaald deel van de conditie nooit getest wordt. (Bv foo || bar, en dat het aanpassen naar foo || !bar geen falende test oplevert, dus alleen foo wordt getest maar niet bar).Mugwump schreef op vrijdag 17 december 2021 @ 10:21:
Unit tests worden altijd wel afgedwongen door code coverage in de basis, maar code coverage is natuurlijk ook maar een metric die lang niet altijd inhoudt dat je ook zinvolle tests schrijft, dus ook daarvoor geldt dat je criteria op kunt stellen voor het evalueren van tests die je weer in lijstjes kunt zetten.
Klopt, ik ben bekend met mutation testing.RobertMe schreef op vrijdag 17 december 2021 @ 10:31:
[...]
Controleren of unit tests correct / zinvol zijn kan ook weer gedeeltelijk automatisch. Dit middels mutation testing waarbij "bugs in de code worden toegepast" (bv > aanpassen naar >=. Of hardcoded numbers aanpassen naar een +1 en -1 variant) en dan zou dus op zijn minst een unit test moeten falen. Faalt geen enkele test dan zijn de tests dus ook niet goed. Bijvoorbeeld dat niet goed op een edge wordt getest bij een > vs >=. Of als je langere/complexere condities hebt met && en/of || dat blijkt dat een bepaald deel van de conditie nooit getest wordt. (Bv foo || bar, en dat het aanpassen naar foo || !bar geen falende test oplevert, dus alleen foo wordt getest maar niet bar).
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
https://niels.nu
🠕 This side up
https://issues.apache.org/jira/browse/LOG4J2-3230 Hoppa, we mogen de dans nog eens doen naar 2.17 binnenkort want 2.16 en eerder doet een infinite recursion op bepaalde inputAntrax schreef op vrijdag 17 december 2021 @ 10:14:
Antrax heeft best wel een slechte week
[Afbeelding]
Ziet eruit als een mogelijkheid tot DoS?Ghehe schreef op vrijdag 17 december 2021 @ 19:33:
[...]
https://issues.apache.org/jira/browse/LOG4J2-3230 Hoppa, we mogen de dans nog eens doen naar 2.17 binnenkort want 2.16 en eerder doet een infinite recursion op bepaalde input
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
[ Voor 9% gewijzigd door gekkie op 17-12-2021 20:00 ]
Ik vind dit om de 1 of andere reden veel te leuk
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
I dub theeGhehe schreef op vrijdag 17 december 2021 @ 19:33:
[...]
https://issues.apache.org/jira/browse/LOG4J2-3230 Hoppa, we mogen de dans nog eens doen naar 2.17 binnenkort want 2.16 en eerder doet een infinite recursion op bepaalde input
I'm not a complete idiot. Some parts are missing.
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
Ask yourself if you are happy and then you cease to be.
Die komen bij mij niet echt van de grond. Maar ik heb een beginnetje met home automation gedaan een tijdje terug. Home Assistant, zigbee2mqtt, Conbee 2, diverse sensoren van Xaiomi, Tradfri stopcontacten etc.Koenvh schreef op vrijdag 17 december 2021 @ 18:23:
Zijn hier nog vakantieknutselprojectplannen?Ik wil eens kijken welke data ik allemaal uit de slimme meter kan uitlezen.
Ask yourself if you are happy and then you cease to be.
Ik heb graag hetzelfde toetsenbord thuis als op de zaak. Dus als ik het thuis helemaal gaaf zou vinden dan bestel ik er nog een voor op kantoor.gekkie schreef op zaterdag 18 december 2021 @ 22:34:
Silent, tss beetje de triangel of picolo speler van het orkest.
Ask yourself if you are happy and then you cease to be.
(oude) lamp die automagisch ingeschakeld werd en toevallig eens warm genoeg werd om de pir te triggeren ?Lethalis schreef op zaterdag 18 december 2021 @ 22:32:
Collega van mij heeft zijn eigen domotica systeem gebouwd ooit, maar die is ook al een keer voor niks naar huis gereden vanuit kantoor omdat zijn bewegingssensoren afgingen.
Blijft een beetje een "wil ik dit wel" project.
[ Voor 3% gewijzigd door gekkie op 18-12-2021 22:38 ]
Al een tijdje bezig met een collega tweaker om mijn ESP8266 rules library te implementeren in een controller bordje voor Panasonic Warmtepompen. Daarmee kan een eigen regeling van de warmtepomp direct vanuit dat controller bordje gedan worden waardoor je geen externe domotica meer nodig hebt.Koenvh schreef op vrijdag 17 december 2021 @ 18:23:
Zijn hier nog vakantieknutselprojectplannen?Ik wil eens kijken welke data ik allemaal uit de slimme meter kan uitlezen.
Sinds de 2 dagen regel reageer ik hier niet meer
Oplossing: gebruik de Silent toetsenbord om je collega hard te meppen. Kies daarna eentje met Blue'sLethalis schreef op zaterdag 18 december 2021 @ 22:36:
[...]
Collega heeft al aangegeven dat hij gek ervan zou worden als het teveel herrie maakt![]()
Vandaar de silent
2x Dell UP2716D | R9 7950X | 128GB RAM | 980 Pro 2TB x2 | RTX2070 Super
.oisyn: Windows is net zo slecht in commandline als Linux in GUI
Het hangt veel af van je applicatie. Heb je veel statische content zoals tweakers.net waar het dynamische (bv. filtering) enkel in iets zoals de pricewatch zit, dan kom je nog steeds goed weg met een serverside setup en hoef je niet bezig te zijn met een SPA. Voeg dan gerust wat simpele AJAX toe. Heck, pak er nog eens jQuery bij for all I care.F.West98 schreef op zaterdag 18 december 2021 @ 23:22:
Kan iemand me uitleggen wat er nou beter is aan een hele Node + React + Webpack + minifyers + weetikwat + backend + API stack dan gewoon lekker klassiek alles server-side renderen met wat kekke dynamische componentjes in web components ofzo?
Models op meerdere plekken: valt me nog goed mee. Toen ik ooit nog fullstack .NET MVC deed, hadden ze op het werk de gewoonte om naast Models ook ViewModels te hebben en zaten we ook met een hoop duplicatie. Nu heb ik mijn eigen models in TypeScript waarmee ik eigenlijk definieer hoe een server response er minstens moet uitzien omdat het geen 1-op-1 match hoeft te zijn. Heb ik enkel A en B van model X nodig maar stuurt backend ook nog C en D door in dezelfde request? Fine, dan heeft mijn model enkel A en B. Voeg daar nog eens iets als een graphql aan toe en het wordt al helemaal interessant, maar ook dat is optioneel. Ik heb het nog niet in een professionele context nodig gehad.F.West98 schreef op zaterdag 18 december 2021 @ 23:22:
Je hebt verder gewoon ineens een vrij onhandige extra laag/hurdle in je flow tussen DB en DOM: je web request. Gevolg: je moet je (api/view)models op meerdere plekken definiëren en bijhouden. Je moet je validatielogica op meerdere plekken definiëren en bijhouden. Error handling kost nog meer moeite.
Ik werk nu op een grote commerciële website die als SPA geschreven is en wij hebben geen problemen met de SEO. Prerendering is iets wat we bekeken hebben maar uiteindelijk niet nodig hadden. Dat was in de tijd dat de code echt nog niet snel was en de website 20+ seconden nodig had op initial load. Daar wordt elke website op afgestraft in SEO, of dat nu SPA of non-SPA is. We hebben nu een sitemap (wat sowieso al good practice is, zelfs in een non-SPA setting).F.West98 schreef op zaterdag 18 december 2021 @ 23:22:
En dan de kers op de taart: de SEO werkt niet goed (want een crawler gaat niet goed om met SPA), dus de oplossing is: je SPA server-side pre-renderen!En dan wordt er gedaan alsof server-side rendering super hot en nieuw is... Het enige gevolg is dat je nu ook in je backend ineens dezelfde JS codebase moet gaan gebruiken, en ineens Node moet gaan draaien, en je huidige backend framework moet laten praten met die Node instance ofzo.. Sorry maar ik kan hier met mn verstand niet bij. Waar zijn we nou mee bezig?
So basically hangt het af van je toepassing. De stack die je opnoemt is niet the holy grail. Sommigen doen alsof het wel the next best thing is omdat iets nieuws altijd meer hip en cool aanvoelt. En zijn we als ITers sowieso niet geneigd om vaak te zoeken naar het betere en naar excuses om de boel te herschrijven? De grootste roepers dat zo'n dev stack het beste ter wereld is, zijn vaak zij met ofwel een eigen agenda (want ze hebben een blog, hebben een boek geschreven, zijn "advocate" voor die tech, ...) ofwel omdat ze oogkleppen zoals een paard ophebben en enkel maar de kudde kunnen volgen.F.West98 schreef op zaterdag 18 december 2021 @ 23:22:
Kan iemand me uitleggen wat er nou beter is aan een hele Node + React + Webpack + minifyers + weetikwat + backend + API stack dan gewoon lekker klassiek alles server-side renderen met wat kekke dynamische componentjes in web components ofzo?
Without nipples, boobs are pointless - 365 project - In mijn hoofd is het alle dagen Kerstmis - What type of bees make milk? Boobies! - What type of bees are scary? BoooOOOOOooobeees! - Cactusliefhebster
Have you heard about our lord and savior Glarses?Lethalis schreef op zaterdag 18 december 2021 @ 22:21:
Misschien slaat het nergens op. De filmpjes op YouTube zijn wel hilarisch. Allemaal mensen die zichzelf filmen terwijl ze iets typen en dan de reacties eronder over het geluid etcHet lijkt wel een parallel toetsenbord fetish universum
Without nipples, boobs are pointless - 365 project - In mijn hoofd is het alle dagen Kerstmis - What type of bees make milk? Boobies! - What type of bees are scary? BoooOOOOOooobeees! - Cactusliefhebster
Roses are red, violets are blue, unexpected '{' on line 32.
Dat is misschien makkelijk, maar ook een pain in the ass. Je data-model is dan zo hard gekoppeld met je API model dat backend wijzigingen niet zomaar mogelijk meer zijn. Je impacteert meteen alle clients + die clients moeten dan ook jouw datamodel kennen.WernerL schreef op zondag 19 december 2021 @ 12:18:
Verder heb ik zelf goede ervaringen met odata. Met ASP.NET en entity framework kun je vrij eenvoudig je data beschikbaar stellen via odata-endpoints waardoor je in de frontend je queries kunt schrijven en niet meer voor ieder ding een custom-endpoint hoeft te bouwen. Heb je ook niet het probleem dat je aan 2 kanten viewModels moet definieren. En anders zijn er ook tools waarmee je typescript-definities kunt genereren van je backend-models. TypeGen bijvoorbeeld.
https://fgheysels.github.io/
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
In het geval de backend slechts één client hoeft te bedienen is de backend sowieso al heel erg gefocussed op te functionaliteit van de desbetreffende applicatie. Een backend wijziging zal dan in veel gevallen samengaan met een frontend wijziging dus ik vind dat niet een issue.whoami schreef op zondag 19 december 2021 @ 13:04:
[...]
Dat is misschien makkelijk, maar ook een pain in the ass. Je data-model is dan zo hard gekoppeld met je API model dat backend wijzigingen niet zomaar mogelijk meer zijn. Je impacteert meteen alle clients + die clients moeten dan ook jouw datamodel kennen.
Met OData heb je ook de mogelijkheid om aan te geven welke data je wilt hebben. Ook data van relaties kun je selecteren via een expand. Nadeel van GraphQL vind ik dat je zelf keuzes moet maken over hoe je sortering, paginering en filtering oplost. Iets wat gewoon onderdeel is van de OData-spec waardoor je als developer alleen moet weten hoe het data-model eruit ziet.Mugwump schreef op zondag 19 december 2021 @ 13:14:
Ik vind OData echt de meest waardeloze API-spec die er ooit bedacht is, al komt SOAP aardig in de buurt.
Nou houdt mijn werk tegenwoordig ook op bij de API laag en bouw ik dus geen systemen waarbij je een tightly coupled data store en front end heb, maar breed inzetbare APIs die door meerdere afnemers geconsumeerd worden.
GraphQL is nog wel interessant. Wij lopen nogal eens aan tegen APIs die een vrij brede set aan data leveren, waarbij veel afnemers dan weer specifiek geïnteresseerd zijn in een bepaald onderdeel, dat kan met GraphQL weer veel efficiënter aangezien de afnemer simpelweg kan aangeven welke data die wil ontvangen.
Roses are red, violets are blue, unexpected '{' on line 32.
Het idee van odata is een beetje dat je (custom) backend code ook maar client is die te leven heeft met het data model van de OData server. Al werk je met OData dan moet je het klasieke concept van de monolitische backend die alle data beheerd en abstraheert los laten en ipv redeneren in clients die taken uitvoeren (wat zowel frontend als backend kan zijn, dat verschil is dan niet meer zo relevant). Daarnaast heeft OData ook gewoon API versies, al wil je een model in de api aanpassen dan kan je dat in een nieuwe versie doen.whoami schreef op zondag 19 december 2021 @ 13:04:
[...]
Dat is misschien makkelijk, maar ook een pain in the ass. Je data-model is dan zo hard gekoppeld met je API model dat backend wijzigingen niet zomaar mogelijk meer zijn. Je impacteert meteen alle clients + die clients moeten dan ook jouw datamodel kennen.
Toch komt OData bij mij heel erg over als geschikt voor "forms-over-data" CRUD toepassingen. Dat is niet het soort werk dat ik doe, dus wellicht komt mijn aversie daar vandaan.WernerL schreef op zondag 19 december 2021 @ 13:22:
[...]
In het geval de backend slechts één client hoeft te bedienen is de backend sowieso al heel erg gefocussed op te functionaliteit van de desbetreffende applicatie. Een backend wijziging zal dan in veel gevallen samengaan met een frontend wijziging dus ik vind dat niet een issue.
Enkel wanneer je stand-alone APIs ontwikkeld die door meerdere producten gebruikt moet worden kan ik me voorstellen dat je iets anders nadenkt over je API-ontwerp.
[...]
Met OData heb je ook de mogelijkheid om aan te geven welke data je wilt hebben. Ook data van relaties kun je selecteren via een expand. Nadeel van GraphQL vind ik dat je zelf keuzes moet maken over hoe je sortering, paginering en filtering oplost. Iets wat gewoon onderdeel is van de OData-spec waardoor je als developer alleen moet weten hoe het data-model eruit ziet.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Het is iets dat mij iig opvalt. Bij een traditionele .NET MVC app heb je meestal een Model en een soort ViewModel, waarna je die laatste direct in je View verwerkt en klaar. Nu heb je ipv een ViewModel meer een soort ApiModel, en moet je die in je frontend weer opnieuw definiëren, samen met veel logica om met je API te communiceren. Dat voelt soms vrij omslachtig - maar goede tooling kan dat inderdaad vereenvoudigen (maar dan heb je nóg meer packages nodig).ElkeBxl schreef op zondag 19 december 2021 @ 09:48:
Models op meerdere plekken: valt me nog goed mee. Toen ik ooit nog fullstack .NET MVC deed, hadden ze op het werk de gewoonte om naast Models ook ViewModels te hebben en zaten we ook met een hoop duplicatie. Nu heb ik mijn eigen models in TypeScript waarmee ik eigenlijk definieer hoe een server response er minstens moet uitzien omdat het geen 1-op-1 match hoeft te zijn. Heb ik enkel A en B van model X nodig maar stuurt backend ook nog C en D door in dezelfde request? Fine, dan heeft mijn model enkel A en B. Voeg daar nog eens iets als een graphql aan toe en het wordt al helemaal interessant, maar ook dat is optioneel. Ik heb het nog niet in een professionele context nodig gehad.
Dat is zeker best practice. Alleen is voor mij het "bekende" alternatief .NET server-side rendering die automagisch op basis van één ViewModel zowel back-end als front-end validation doetValidatielogica op meerdere plekken: is het niet sowieso best-practice om al iets van frontend validatie te hebben om de eerste dingen zoals required form field errors te hebben? Ik verwacht dat backend echt alle validatielogica doet en de frontend validatie is er om heel snelle feedback naar de user te hebben die er ook voor zorgt dat er minder slechte requests naar backend hoeven te gebeuren. Backend validatie is nodig, frontend validatie is er voor de user experience en optioneel.
Goed, dat is mijn gebrek aan kennis. Ik las vooral dat SSR toch echt nodig was om je SEO op orde te krijgen.Ik werk nu op een grote commerciële website die als SPA geschreven is en wij hebben geen problemen met de SEO. Prerendering is iets wat we bekeken hebben maar uiteindelijk niet nodig hadden. Dat was in de tijd dat de code echt nog niet snel was en de website 20+ seconden nodig had op initial load. Daar wordt elke website op afgestraft in SEO, of dat nu SPA of non-SPA is. We hebben nu een sitemap (wat sowieso al good practice is, zelfs in een non-SPA setting).
Dat is inderdaad vooral wat mij stoort, hoe men online doet alsof SSR+SPA de beste uitvinding sinds gesneden brood is en alsof het allemaal geweldige magie is... terwijl ik hier dan zit te lezen van ja SSR dat doen ze al decennia.So basically hangt het af van je toepassing. De stack die je opnoemt is niet the holy grail. Sommigen doen alsof het wel the next best thing is omdat iets nieuws altijd meer hip en cool aanvoelt. En zijn we als ITers sowieso niet geneigd om vaak te zoeken naar het betere en naar excuses om de boel te herschrijven? De grootste roepers dat zo'n dev stack het beste ter wereld is, zijn vaak zij met ofwel een eigen agenda (want ze hebben een blog, hebben een boek geschreven, zijn "advocate" voor die tech, ...) ofwel omdat ze oogkleppen zoals een paard ophebben en enkel maar de kudde kunnen volgen.
Dat is heel leuk, maar ik heb toch liever niet mijn backend "vervuild" met JavaScript en consortenCaelorum schreef op zondag 19 december 2021 @ 12:04:
Tja dat hele SPA verhaal overweeg ik ook alleen als zowel e frontend als backend talen dezelfde zijn. Dan kan je eenvoudig functies en models hergebruiken aan beide kanten. Pak je dan iets als https://fable.io/ dan wordt het wel heel fijn.
Ik heb me er niet enorm in verdiept, maar is het niet dat je dan volledig vastzit aan je DB model? Ik heb vaak genoeg dat ik in de codebase en al helemaal richting clients een ander datamodel wil presenteren: sommige relations niet meer genormaliseerd, of sommige velden weglaten, of bijvoorbeeld data aggregaten. Is dat ook te doen met OData? Ik ben het zelf nog niet tegengekomen maar zou het wel enorm handig vinden.WernerL schreef op zondag 19 december 2021 @ 12:18:
Verder heb ik zelf goede ervaringen met odata. Met ASP.NET en entity framework kun je vrij eenvoudig je data beschikbaar stellen via odata-endpoints waardoor je in de frontend je queries kunt schrijven en niet meer voor ieder ding een custom-endpoint hoeft te bouwen. Heb je ook niet het probleem dat je aan 2 kanten viewModels moet definieren. En anders zijn er ook tools waarmee je typescript-definities kunt genereren van je backend-models. TypeGen bijvoorbeeld.
2x Dell UP2716D | R9 7950X | 128GB RAM | 980 Pro 2TB x2 | RTX2070 Super
.oisyn: Windows is net zo slecht in commandline als Linux in GUI
In het geval van fable is zowel frontend als backend f#, wat je met moeite onder javascript kan scharen lijkt me.F.West98 schreef op zondag 19 december 2021 @ 14:57:
[...]
Dat is heel leuk, maar ik heb toch liever niet mijn backend "vervuild" met JavaScript en consorten
[...]
We are shaping the future
Dat is wat ik ook probeerde te verwoordenF.West98 schreef op zondag 19 december 2021 @ 14:57:
[...]
Ik heb me er niet enorm in verdiept, maar is het niet dat je dan volledig vastzit aan je DB model? Ik heb vaak genoeg dat ik in de codebase en al helemaal richting clients een ander datamodel wil presenteren: sommige relations niet meer genormaliseerd, of sommige velden weglaten, of bijvoorbeeld data aggregaten. Is dat ook te doen met OData? Ik ben het zelf nog niet tegengekomen maar zou het wel enorm handig vinden.
https://fgheysels.github.io/
Als ik het goed begrijp heb je dan eigenlijk voor een zwaarder tikkend toetsenbord gekozen?Ryur schreef op zaterdag 18 december 2021 @ 22:45:
[...]
Oplossing: gebruik de Silent toetsenbord om je collega hard te meppen. Kies daarna eentje met Blue's
Hier hetzelfde probleem, mijn collega's werden ook gek van mijn toetsenbord (toen had ik nog Browns). Nu met het thuiswerken dus lekker blue's, en ALS ik ooit weer naar kantoor moet zie ik het wel
Ask yourself if you are happy and then you cease to be.
Doe morgen vroeg maar (of straks na het avondeten een bakkie).Alex) schreef op zondag 19 december 2021 @ 16:27:
Goedemiddag, hier ben ik al lang niet meer geweest! Tweakers is echt helemaal uit mijn systeem gevallen...
Koffie?
[Afbeelding]
[ Voor 17% gewijzigd door CodeCaster op 19-12-2021 17:00 ]
https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...
In het kader van het sluiten van de sportscholen, krachttraining op maatLethalis schreef op zondag 19 december 2021 @ 16:52:
[...]
Als ik het goed begrijp heb je dan eigenlijk voor een zwaarder tikkend toetsenbord gekozen?
Ik dacht dat "purist" zijn op dit gebied betekende dat je resource een root entity is van een afgebakend domein en vooral géén armoedige 1 op 1 mapping naar een relationeel model isCodeCaster schreef op zondag 19 december 2021 @ 16:54:
Of je hebt van die "puristen" die vinden dat dat alles REST moet zijn, en dat je API-calls allemaal over één entity moeten gaan, waarbij een entity dan liefst ook nog één-op-één mapt naar een databasetabel. Gevolg: je landingpage/dashboard moet twintig separate API-calls doen om het overzicht voor de gebruiker (je weet wel, de klant die je uiteindelijk bedient) samen te stellen, dit duurt 20 seconden, en dan gaat men workarounds met caching, skeleton screens, loading throbbers en weet ik veel wat introduceren.
Ask yourself if you are happy and then you cease to be.
Maar de UX wordt er niet beter van.Lethalis schreef op zondag 19 december 2021 @ 17:09:
[...]
Daarnaast zijn losse API calls vanuit een frontend meestal niet zo'n probleem omdat ze parallel kunnen worden uitgevoerd
We are shaping the future
It depends. As usual.
Ask yourself if you are happy and then you cease to be.
Ik heb zelf nooit Red's geprobeerd trouwens, heb Browns & Blues altijd.Lethalis schreef op zondag 19 december 2021 @ 16:52:
[...]
Als ik het goed begrijp heb je dan eigenlijk voor een zwaarder tikkend toetsenbord gekozen?
MX Red 45cN operating force
MX Brown 55cN operating force
MX Blue 60cN operating force
Ik heb ook deels voor de Red gekozen zodat het soepel zal zijn. Nu heb ik geen ervaring hiermee, dus kan zijn dat ik er straks spijt van krijg en toch iets anders wil... maar dat is een kwestie van uitproberen.
Wat maakt de MX Blue voor jou ideaal? Meeste feedback?
Mijn models zijn zoveel mogelijk afgestemd op het formaat van de response die backend stuurt. En voor de uitzonderingen van velden (zoals het parsen van een datetime string in een Date obejct om nu simpel voorbeeld te nemen), kleine functie erover om dat te parsen en klaar. Eigenlijk werk ik dus meestal met een APImodel in mijn frontend. Hoe dat er op backend uitziet heb ik geen idee van. Maar die backend zit dan ook met de situatie dat dezelfde endpoints die ik aanroep, ook aangeroepen wordt door ander frontends. Om dan (voor zover ik heb gezien) soms maar 5 van de 100 object properties te gebruiken. Dan lijkt een model per frontend wel clean om mee te werken. Het is iets dat ik ook vaker van collegas hoor dat 1 backend meerdere frontends van data voorziet.F.West98 schreef op zondag 19 december 2021 @ 14:57:
[...]
Het is iets dat mij iig opvalt. Bij een traditionele .NET MVC app heb je meestal een Model en een soort ViewModel, waarna je die laatste direct in je View verwerkt en klaar. Nu heb je ipv een ViewModel meer een soort ApiModel, en moet je die in je frontend weer opnieuw definiëren, samen met veel logica om met je API te communiceren. Dat voelt soms vrij omslachtig - maar goede tooling kan dat inderdaad vereenvoudigen (maar dan heb je nóg meer packages nodig).
Gewoon dezelfde validatie kunnen importeren zou wel iets cool kunnen zijn. Maar daar staat dan tegenover dat ik mijn JS niet wil vervuilen met backend codeF.West98 schreef op zondag 19 december 2021 @ 14:57:
[...]
Dat is zeker best practice. Alleen is voor mij het "bekende" alternatief .NET server-side rendering die automagisch op basis van één ViewModel zowel back-end als front-end validation doetVolgens mij kunnen meerdere engines dat wel. In dat opzicht is het dus een extra duplicatie in je code.
No worries, zo roepen het overal dus ik snap dat wel. En uiteindelijk ben ik ook maar 1 ervaring... Google zelf geeft wel wat info erover zoals in deze codelab: https://codelabs.develope...age-app-search-friendly#3 waar ze eigenlijk showcasen dat bv. je meta tags aanpassen in JS geen probleem lijkt te zijn. Meeste SPAs die ik heb gezien komen nooit aan de meta tags aan en passen de titel van de pagina niet aan. Tja, dan schiet je jezelf in je voet natuurlijk.F.West98 schreef op zondag 19 december 2021 @ 14:57:
[...]
Goed, dat is mijn gebrek aan kennis. Ik las vooral dat SSR toch echt nodig was om je SEO op orde te krijgen.
Ik wou dat meer Electron apps zo'n plezier waren om te runnen zoals VS Code. Wat zou mijn laptop zoveel minder zitten blazen...F.West98 schreef op zondag 19 december 2021 @ 14:57:
[...]
De enige uitzondering tot nu toe is VS Code
Headless CMS for the win!WernerL schreef op zondag 19 december 2021 @ 12:18:
Ook voor websites hebben SPAs voordelen. Veel CMS systemen zijn enorm opinionated waardoor het best een pain in the ass kan zijn om er mee te werken. Door de frontend los te trekken van het CMS heb je meer vrijheid voor het schrijven en structuren van je frontend code.
Daar ben ik echt benieuwd naar wat de toekomst wordt van webassembly. Van wat ik hoor van klanten en collega's is er nog niet zoveel volk chaud en lijken ze het vooral te kennen van ports van games en andere "demo's" om te laten zien hoe snel het is. Zelf heb ik het nu nog niet nodig, daarvoor zijn mijn frontends te simpel en zit er weinig tot geen rekenkracht of zware grafische meuk in.gekkie schreef op zondag 19 december 2021 @ 12:14:
Of wellicht dat rust en webasm nog wat zou kunnen worden.
Ik heb zelf MX Brown's en het bottomen is iets wat ik ook ervaar. O-rings hielpen daar al wat in, maakte het voor de partner al wat aangenamer als ze ging slapen en ik nog zat te tokkelen in de kamer ernaastRyur schreef op zondag 19 december 2021 @ 17:33:
[...]
De reden eigenlijk waarom ik voor Blue's ben gegaan is dat ik bij Brown's veel merk dat ik zit te "bottomen" (oftewel de key eigenlijk tegen het toetsenbord zelf aanduwen).
[ Voor 6% gewijzigd door ElkeBxl op 19-12-2021 21:12 ]
Without nipples, boobs are pointless - 365 project - In mijn hoofd is het alle dagen Kerstmis - What type of bees make milk? Boobies! - What type of bees are scary? BoooOOOOOooobeees! - Cactusliefhebster
Ik heb ook gehoord dat O-rings willen helpen ja. Of ze extra te 'luben', maar zo ver wil ik niet echt gaanElkeBxl schreef op zondag 19 december 2021 @ 21:11:
[...]
Ik heb zelf MX Brown's en het bottomen is iets wat ik ook ervaar. O-rings hielpen daar al wat in, maakte het voor de partner al wat aangenamer als ze ging slapen en ik nog zat te tokkelen in de kamer ernaast
[ Voor 13% gewijzigd door Voutloos op 20-12-2021 08:01 ]
{signature}
? Met een SPA laadt je nog steeds de website vanaf het domein waar die op geserveerd is, met exact dezelfde user-agent als bij een MPA. Wat in de begin dagen van SPA's vooral kut was dat analytics tools niet om konden gaan met client-side routing.Voutloos schreef op maandag 20 december 2021 @ 07:59:
Cynisch: Dingen als React zorgen er voor dat je altijd Google of Facebook als vertrekpunt hebt als je gaat surfen. Ten opzichte van primair serverside zal er altijd meer complexiteit voor de user agent zichtbaar zijn.
[ Voor 28% gewijzigd door Voutloos op 20-12-2021 08:23 ]
{signature}
Inderdaad.CodeCaster schreef op zondag 19 december 2021 @ 16:54:
Mensen die fitties gooien over SOAP kan ik ook niet serieus nemen; die hebben blijkbaar het tijdperk gemist waarin API-documentatie niet bestond en het gemiddelde dataverkeer nog niet over HTTPS liep. Met een gegenereerde WSDL weet je in ieder geval nog welke endpoints er op een API zitten en welke modellen die teruggeeft. Ja het is XML, en dat is wat meer verbose dan JSON. Als dat het enige is wat je kunt inbrengen...
[ Voor 6% gewijzigd door hackerhater op 20-12-2021 09:29 ]
Roses are red, violets are blue, unexpected '{' on line 32.
Probleem is dat Swagger in het algemeen alleen maar documentatie isWernerL schreef op maandag 20 december 2021 @ 09:30:
Voor Rest APIs heb je swagger waarmee je ook harde afspraken vast kunt leggen over je API design. Dat het weinig geruikt wordt is een ander verhaal.
Ik heb het even bekeken, maar ik zie niet hoe dat voor een gebruiker van de API af dwingt dat A x keer mag voorkomen en echt een int is en dat B 1 keer mag voorkomen met de keuze uit x,y of z?Caelorum schreef op maandag 20 december 2021 @ 09:33:
Voor dat afdwingen hebben we dan ook https://pact.io/, wat veel beter afdwingt DAN Soap (als je het goed inzet)
[ Voor 35% gewijzigd door hackerhater op 20-12-2021 09:47 ]
Als je het laat genereren uit je code is het nog goed te doen. Ons platform genereert on-the-fly een swagger als je deze opvraagt na de laatste deployment, en die cached hij dan tot er een nieuwe deployment plaatsvindt. Op die manier heb je altijd de nieuwste versie van de swaggerdefinitie die hoort bij de opgevraagde API. Omdat 'ie genereert op basis van de code heb je ook direct de juiste definities voor velden.hackerhater schreef op maandag 20 december 2021 @ 09:31:
[...]
Probleem is dat Swagger in het algemeen alleen maar documentatie is
Nadeel van een code first approach is dat je je API onbedoeld kan wijzigen. Zeker wanneer je API afgenomen wordt door anderen is een contract first aanpak veiliger.Merethil schreef op maandag 20 december 2021 @ 09:47:
[...]
Als je het laat genereren uit je code is het nog goed te doen. Ons platform genereert on-the-fly een swagger als je deze opvraagt na de laatste deployment, en die cached hij dan tot er een nieuwe deployment plaatsvindt. Op die manier heb je altijd de nieuwste versie van de swaggerdefinitie die hoort bij de opgevraagde API. Omdat 'ie genereert op basis van de code heb je ook direct de juiste definities voor velden.
Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'
Zeker, maar daar houd je dan ook rekening mee in je opzet van je API/code. Sowieso hadden we het hier laatst al over viewmodels - die houden wij ook aan. Elke "source" (API endpoint) krijgt zijn eigen viewmodel waarop wij alleen dingen toevoegen. Als er toch een wijziging moet plaatsvinden waarbij we zaken verwijderen danwel hernoemen wordt het een nieuwe versie van het endpoint (met versienummer in de URL) en ondersteunen we ook de oude versie.Janoz schreef op maandag 20 december 2021 @ 10:06:
[...]
Nadeel van een code first approach is dat je je API onbedoeld kan wijzigen. Zeker wanneer je API afgenomen wordt door anderen is een contract first aanpak veiliger.
[ Voor 19% gewijzigd door Merethil op 20-12-2021 10:19 ]
Het ging om contract first vs code first. Niet WSDL vs swagger. Contract first is met een WSDL triviaal.Merethil schreef op maandag 20 december 2021 @ 10:14:
Hetzelfde probleem houd je ook met je WSDL's als deze niet correct opnieuw worden gegenereerd - kijk maar eens naar het aantal mopperende mensen die een WSDL krijgen waar de provider zich uiteindelijk helemaal niet netjes aan houdt
Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'
Duidelijk, zo las ik het niet helemaal. Excuus!Janoz schreef op maandag 20 december 2021 @ 10:50:
[...]
Het ging om contract first vs code first. Niet WSDL vs swagger. Contract first is met een WSDL triviaal.
Ja, dat. Er is een verschil tussen "Oeps, die wijziging aan die entity die drie niveaus diep toch uit de API bleek te komen, hebben we over het hoofd gezien" en "Oh, die nieuwe property moet ook uit de API komen, op welke plek gaan we die in de WSDL / het schema stoppen?".Janoz schreef op maandag 20 december 2021 @ 10:50:
[...]
Het ging om contract first vs code first. Niet WSDL vs swagger. Contract first is met een WSDL triviaal.
Mijn ervaring met (andere partijen die) Swagger/OpenAPI gebruiken, is dat het één keer wordt gegenereerd (development-time) en vervolgens niet meer aangeraakt.WernerL schreef op maandag 20 december 2021 @ 09:30:
Voor Rest APIs heb je swagger waarmee je ook harde afspraken vast kunt leggen over je API design. Dat het weinig geruikt wordt is een ander verhaal.
Oh hou op schei uit. Als ik die tegenkom op Stack Overflow, krijgen ze steevast een down- en soms closevote omdat ze op meningen of incorrecte aannames zijn gebaseerd.Lethalis schreef op zondag 19 december 2021 @ 17:09:
[...]
Het REST purist zijn gaat meestal toch ook meer over de juiste HTTP verbs en response codes gebruiken en een goede hiërarchie in de urls aan te brengen?
[ Voor 72% gewijzigd door CodeCaster op 20-12-2021 11:17 ]
https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...
Ik ben een tijdje terug overgestapt op NSwag, dat werkt naar mijn ervaring nét even ietsjes beter samen met enums. Ik heb daarna in de build een stap opgenomen die automatisch een complete client genereert (via NSwag.MSBuild).CodeCaster schreef op maandag 20 december 2021 @ 10:57:
[...]
Bij .NET heb je tenminste nog Swashbuckle
We are shaping the future
Hoe ik het normaal zou inzetten is dat de afnemers via een contract aangeven wat ze precies gebruiken/verwachten, doorgaans doordat ze het in de eigen testbase opnemen en bij het draaien van de tests een contract produceren. Aan de API kant neem je dat dan op in je testbase en dan weet je meteen bij veranderingen welke contracten met consumers je breekt.hackerhater schreef op maandag 20 december 2021 @ 09:39:
[...]
Ik heb het even bekeken, maar ik zie niet hoe dat voor een gebruiker van de API af dwingt dat A x keer mag voorkomen en echt een int is en dat B 1 keer mag voorkomen met de keuze uit x,y of z? [...]
[ Voor 7% gewijzigd door Caelorum op 20-12-2021 11:38 ]
Ik doe zelf meestal idd gewoon een 400 Bad Request en geef een JSON body met omschrijving (reason) terug die bijvoorbeeld in de frontend wordt getoond.CodeCaster schreef op maandag 20 december 2021 @ 10:57:
[...]
- Geen, wat je beschrijft is RPC, geen REST, en REST doet niks met statuscodes, tenzij ze over het HTTP-niveau gaan (authentication, authorization, rate limiting, content negotiation, conditional requests). Moet je dan toch per se de HTTP-statusregel gebruiken en niet een JSON-body waar de ontvangende kant wat mee kan, dan heb je 9 van de 10 keer 409 Conflict of 422 Unprocessable Entity nodig (of gewoon een 400 want who cares), en de rest (ha-ha) is praktisch irrelevant. En dan nog weet de caller niet wat er mis is, dus again, zet het in je fucking body.
Ask yourself if you are happy and then you cease to be.
API's schrijven en consumeren is mijn dagelijkse werk, naast of in combinatie met ETL, documentatie schrijven en test-, release- en source control-processen verbeteren.Lethalis schreef op maandag 20 december 2021 @ 11:41:
[...]
Ik doe zelf meestal idd gewoon een 400 Bad Request en geef een JSON body met omschrijving (reason) terug die bijvoorbeeld in de frontend wordt getoond.
Maar goed, ik ben dan ook geen puristEn vaak te lui om dat soort details uit te zoeken, laat staan dat ik er een post op SO aan zou wijden.
Sowieso is een "resource" lastig als het om een handeling gaat die geen CRUD is, maar je mag werkwoorden gebruiken dacht ik.
Anyways... gaat het wel goed?Ik dacht dat ik gefrustreerd was
Ben nog aan het bijkomen van het feit dat mijn dochtertje van 5 voorlopig thuis zit en ik maar moet kijken hoe ik het oplos met mijn werk.
Heb voorlopig maar vrije dagen opgenomen. Ik ben helaas iemand die het beste werkt als hij zich zo ongeveer opsluit in een kamer, multi tasken is mijn ding niet... dus ik zie de komende periode somber in.
Ik doe maar even alsof de deadlines er niet zijn
https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...
Ik loop nu steeds tegen een interne developmentclub bij een klant aan die REST-resources maken á laCodeCaster schreef op maandag 20 december 2021 @ 12:33:
[...]
API's schrijven en consumeren is mijn dagelijkse werk, naast of in combinatie met ETL, documentatie schrijven en test-, release- en source control-processen verbeteren.
Ik kom daarbij een heleboel troep en incompetentie tegen en raak daar soms een beetje gefrustreerd van ja. Gelukkig kan ik het hier en op SO van me af schrijven, en ben ik in het echt meestal best gezellig.
Kan me inderdaad voorstellen dat het lastig is met kinderen die plots weer drie weken thuis zitten...
1
| GET /restapi/customer/setPhotoForCustomer?guestNumber={gnum}&photo_location={phot_loc}&IsAvailable=true |
1
2
| PUT /restapi/guest/{gnum}/addVisiToSiteForCustomer?site_code={siteCode}×tamp={datetime}&guest_number={gnum} Body: {leeg} |
1
2
3
4
| { "succes": "false", "error": "Customer number 1234567890 not found" } |
Het enige wat daar REST aan is, is het eerste stukje van de URL. Maar goed, API's bedenken is heel makkelijk, een consistente, logische API die enigszins doet wat een developer verwacht (principle of least surprise) is moeilijk.Merethil schreef op maandag 20 december 2021 @ 13:55:
[...]
Ik loop nu steeds tegen een interne developmentclub bij een klant aan die REST-resources maken á la
code:
1 GET /restapi/customer/setPhotoForCustomer?guestNumber={gnum}&photo_location={phot_loc}&IsAvailable=true
of
code:
1 2 PUT /restapi/guest/{gnum}/addVisiToSiteForCustomer?site_code={siteCode}×tamp={datetime}&guest_number={gnum} Body: {leeg}
en elke keer vraag ik me af wat ze aan het doen zijn als ze weer een excentriek endpoint verzinnen. Het mooiste is nog dat we de helft van de tijd 200 / OK terugkrijgen, met in de body:
code:
1 2 3 4 { "succes": "false", "error": "Customer number 1234567890 not found" }
Ook dan ben ik blij dat ik een collega heb die hetzelfde meemaakt, kunnen we even tegen elkaar mopperen
Met een contract first is het natuurlijk ook prima mogelijk om non-compatibel te zijn na een wijziging van het contract. Natuurlijk is dat risico met code-first wel iets groter, maar met een juiste opzet ( en bijbehorende checks ) moet je aan dezelfde regels voldoen om compatible te blijven.Janoz schreef op maandag 20 december 2021 @ 10:06:
[...]
Nadeel van een code first approach is dat je je API onbedoeld kan wijzigen. Zeker wanneer je API afgenomen wordt door anderen is een contract first aanpak veiliger.
“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”
* ElkeBxl meldt haar ook met deze ervaring en moppert wat meeMerethil schreef op maandag 20 december 2021 @ 13:55:
[...]
en elke keer vraag ik me af wat ze aan het doen zijn als ze weer een excentriek endpoint verzinnen. Het mooiste is nog dat we de helft van de tijd 200 / OK terugkrijgen, met in de body:
code:
1 2 3 4 { "succes": "false", "error": "Customer number 1234567890 not found" }
Ook dan ben ik blij dat ik een collega heb die hetzelfde meemaakt, kunnen we even tegen elkaar mopperen
Without nipples, boobs are pointless - 365 project - In mijn hoofd is het alle dagen Kerstmis - What type of bees make milk? Boobies! - What type of bees are scary? BoooOOOOOooobeees! - Cactusliefhebster
O wow. " we vinden de data niet", elke beetje devver zou er dan een 404 van maken. Maar dat helemaal kapot redeneren naar een 204, alsof er een product owner die denkt te kunnen devven zich er mee bemoeit heeft......ElkeBxl schreef op maandag 20 december 2021 @ 14:19:
[...]
Hun uitleg? "we vinden de data niet met die request en dus is er geen content om terug te sturen".
"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney
Zo werkte ik ooit eens in een team met een volstrekt onhandelbare front-enderdie z'n vak totaal niet verstond, maar wel het idee had dat hij zo ongeveer de best mogelijke developer ooit was en derhalve ook van niemand iets wilde aannemen. Ik had een REST API ontwikkeld die inderdaad bij een opvraging op basis van ID netjes een 404 gaf op het moment dat iets niet bestond. Meneer de rockstar developer begreep helemaal niets van REST (het was immers pas 2018 ofzo) en kwam informeren wat ik dacht dat die 404 moest betekenen. Ik antwoordde uiteraard dat dit betekent dat de resource niet bestaat, waarna ik een hele tirade kreeg over dat meneer wel wist hoe het HTTP protocol werkte, maar dat hij wilde weten wat een 404 van een REST API betekende.ElkeBxl schreef op maandag 20 december 2021 @ 14:19:
[...]
* ElkeBxl meldt haar ook met deze ervaring en moppert wat mee
Hier exact hetzelfde met die bullshit "success" dingen in de response. Niet eens een code meegeven, gewoon direct de vertaling van de error in NL, FR, EN en DE. Moet ik zelf nog uitzoeken wat er fout is gelopen en hopen dat de vertaalde labels uberhaupt bestaan. Genoeg meegemaakt dat ik enkel een "success": "false" terugkrijg. Tja dan krijgen ze gewoon een bericht met een copy van de request en een "please fix this".
Ondertussen beginnen ze de response codes beetje bij beetje te gebruiken. Maar een 404 gebruiken voor als ik iets opvraag dat niet bestaat, dat doen we niet. Nee we gebruiken 204 No Content om aan te geven dat de data die ik opvraag niet bestaatHun uitleg? "we vinden de data niet met die request en dus is er geen content om terug te sturen".
En natuurlijk heeft niet elke response die "success" in de response body dus dat is dan ook al niet betrouwbaar. So yeah...
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
De marketingtool waar ik tegenaan moest praten (Selligent) gaf ook op alle calls een 500 Internal Server Error terug:ElkeBxl schreef op maandag 20 december 2021 @ 14:19:
[...]
* ElkeBxl meldt haar ook met deze ervaring en moppert wat mee
Hier exact hetzelfde met die bullshit "success" dingen in de response. Niet eens een code meegeven, gewoon direct de vertaling van de error in NL, FR, EN en DE. Moet ik zelf nog uitzoeken wat er fout is gelopen en hopen dat de vertaalde labels uberhaupt bestaan. Genoeg meegemaakt dat ik enkel een "success": "false" terugkrijg. Tja dan krijgen ze gewoon een bericht met een copy van de request en een "please fix this".
Ondertussen beginnen ze de response codes beetje bij beetje te gebruiken. Maar een 404 gebruiken voor als ik iets opvraag dat niet bestaat, dat doen we niet. Nee we gebruiken 204 No Content om aan te geven dat de data die ik opvraag niet bestaatHun uitleg? "we vinden de data niet met die request en dus is er geen content om terug te sturen".
En natuurlijk heeft niet elke response die "success" in de response body dus dat is dan ook al niet betrouwbaar. So yeah...
1
2
| Header: 500 Internal Server Error Body: "Resource /rest/endpoint/naamvanapplicatie/naamvantabel unavailable" |
1
2
| Header: 500 Internal Server Error Body: "Data in field XYZ not in line with expected definition" |
1
2
| Header: 500 Internal Server Error Body: "Unexpected error occurred" |
Dat laatste is vooral een drama. Al heb je een of ander vaag RCP-achtig protocol op basis van REST dan is dat opzich niet zo'n probleem. Daar bouw ik dan wel een WeirdosRCPClient ding voor die alle ongein mapt naar iets wat logisch is. Maar als het van uitzonderingen aan elkaar hangt dan moet je dus per call met een httpclient gaan klooien om het een beetje consitent te maken naar de rest van je applicatie.ElkeBxl schreef op maandag 20 december 2021 @ 14:19:
[...]
En natuurlijk heeft niet elke response die "success" in de response body dus dat is dan ook al niet betrouwbaar. So yeah...
Wij hebben hier gewoon een interne retry library die hangfire gebruikt om dat op de achtergrond te doen (die scheduled elke keer dat een call failed een retry over X tijd). Aan de voorkant houden we er dan rekening mee dat er een inprogres state is voor een actie. Dat lost ook direct op dat veel van die vage systemen totaal niet om kunnen gaan met piek belastingen.Merethil schreef op maandag 20 december 2021 @ 15:10:
[...]
De marketingtool waar ik tegenaan moest praten (Selligent) gaf ook op alle calls een 500 Internal Server Error terug:
Gemiddelde 404-achtige error:
code:
1 2 Header: 500 Internal Server Error Body: "Resource /rest/endpoint/naamvanapplicatie/naamvantabel unavailable"
Gemiddelde 400-achtige error:
code:
1 2 Header: 500 Internal Server Error Body: "Data in field XYZ not in line with expected definition"
Gemiddelde 500-achtige error:
code:
1 2 Header: 500 Internal Server Error Body: "Unexpected error occurred"
Die laatste kwam voor alles wat ze niet expliciet hadden ingebouwd naar voren, maar dus ook voor:... en zo nog veel andere permutaties.
- geplande downtime
- een ongerelateerde applicatie die verderop in het landschap eruit lag
- een record dat niet bestaat
- een veld dat niet bestaat maar wel gevuld is in de request, een veld dat wél bestaat en gevuld is in de request maar opeens 'niet gevonden' kan worden in de database (wtf?!)
Omdat 'ie ook vaak teruggegeven werd terwijl er helemaal niets mis leek te zijn hebben we een retry ingebouwd: na elke 500 Internal Server Error proberen we het nog tweemaal extra met tussenpozen van 3 seconden (yup... Elke request kan zomaar 10+ seconden duren) en dan ging het opeens prima.
Op die manier ongeveer 90% van de foutlogging richting die applicatie weg weten te werken
🠕 This side up
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
| <?xml version="1.0" encoding="UTF-8"?> <HandleOfferDetails> <Header> <Context> <ServiceUser>SelfService</ServiceUser> <Domain>MIJNESSENT</Domain> <Channel>BACO</Channel> <Brand>essent</Brand> </Context> </Header> <request> <SendOffer>false</SendOffer> <Customer> <SegmentType code="HH" text="" /> <Connection> <Address> <HouseNr>1</HouseNr> <HouseNrExt /> <Postcode>9999ZZ</Postcode> </Address> </Connection> </Customer> <Campaign> <CampaignID>143131</CampaignID> <Incentive id="" /> <Products> <Product> <Services> <Service code="LOOPTIJD" value="F" /> <Service code="VERBLIJFSFUNCTIE" value="1" /> </Services> </Product> </Products> </Campaign> <ContactDate>2021-12-20</ContactDate> <StandardAnnualUsages> <StandardAnnualUsage> <EnergyType code="01" text="" /> <ValueStandard>100000</ValueStandard> </StandardAnnualUsage> <StandardAnnualUsage> <EnergyType code="02" text="" /> <ValueStandard>250000</ValueStandard> </StandardAnnualUsage> </StandardAnnualUsages> </request> <response> <Campaign> <Campaign code="143131" text="Acq DF Variabel OBT (dec)" /> <Type Code="Above the line" /> <Description>Variabel contract, onbepaalde looptijd (tijdelijk aanbod)</Description> <Priority>100</Priority> <Period FromDate="2021-12-01" ToDate="2021-12-31" /> <CampaignDetails> <Actions> <Action code="AddCustomer" text="AddCustomer" /> </Actions> <SegmentType code="HH" text="Huishouden" /> <AsIsProducts /> <ToBeProducts> <Product> <EnergyType code="01" text="Elektriciteit" /> <ProductPackage code="E_H_BD" text="Elektriciteit Keuzetarief Groene Stroom" /> <Services> <Service code="LOOPTIJD" text="Looptijd"> <Option value="F" description="F" /> </Service> <Service code="KEUZE_TARIEF_E" text="Keuze tarief E"> <Option value="S" description="Standaard" /> </Service> <Service code="VERBLIJFSFUNCTIE" text="Verblijfsfunctie"> <Option value="1" description="Ja" enabled="true" isDefault="true" Blocked="false" /> <Option value="0" description="Nee" enabled="true" isDefault="false" Blocked="false" /> </Service> </Services> </Product> <Product> <EnergyType code="02" text="Gas" /> <ProductPackage code="G_H_B" text="Gas" /> <Services> <Service code="LOOPTIJD" text="Looptijd"> <Option value="F" description="F" /> </Service> </Services> </Product> </ToBeProducts> <CampaignServices /> <UseContractDate>false</UseContractDate> </CampaignDetails> <PropositionType>Dual Fuel Acquisitie</PropositionType> </Campaign> <StandardAnnualUsages> <StandardAnnualUsage> <EnergyType code="01" text="01" /> <ValueStandard>100000</ValueStandard> <UnitOfMeasurement>kWh</UnitOfMeasurement> </StandardAnnualUsage> <StandardAnnualUsage> <EnergyType code="02" text="02" /> <ValueStandard>250000</ValueStandard> <UnitOfMeasurement>m3</UnitOfMeasurement> </StandardAnnualUsage> </StandardAnnualUsages> <TotalAmounts> <TotalMonthlyAmount> <Amount>39743.33</Amount> <Description>Totaal maandkosten elektriciteit en gas</Description> </TotalMonthlyAmount> <TotalYearlyAmount> <Amount>476919.63</Amount> <Description>Totaal jaarkosten elektriciteit en gas</Description> </TotalYearlyAmount> </TotalAmounts> <TotalDiscountedAmounts /> <Offers> <OfferOverview> <Product> <EnergyType code="01" text="" /> <SegmentType code="HH" text="" /> <PropositionID>AW5_E_H_BD-99-S</PropositionID> <PropositionDescription>Groene Stroom - Variabel - Flexibele looptijd</PropositionDescription> <Services> <Service code="KEUZE_TARIEF_E" value="S" /> <Service code="LOOPTIJD" value="F" /> <Service code="VERBLIJFSFUNCTIE" value="1" /> </Services> <CARData> <Profile> <Origin>DEFAULT</Origin> <Profile code="NPK" text="" /> </Profile> <GridCompanyInformation> <Origin>DEFAULT</Origin> <GridCompany EAN="8716879000004" name="" /> </GridCompanyInformation> <NetAreaInformation> <Origin>DEFAULT</Origin> <NetArea EAN="871687910000219120" name="" /> </NetAreaInformation> <Residential> <Origin>REQUEST</Origin> <Value>1</Value> </Residential> <CapacityTariffInformation> <Origin>DEFAULT</Origin> <CapacityTariff code="8742010102115" text="8742010102115" /> </CapacityTariffInformation> <DeterminationComplex> <Origin>EDSN</Origin> <Value>00</Value> </DeterminationComplex> </CARData> </Product> <ConsumptionPrice> <TotalConsumPrice> <Amount>0.4432</Amount> <Description>elektriciteit Enkeltarief (1 t/m 10.000 kWh):</Description> <Zone>1</Zone> </TotalConsumPrice> <TotalConsumPrice> <Amount>0.40503</Amount> <Description>elektriciteit Enkeltarief (10.001 t/m 50.000 kWh):</Description> <Zone>2</Zone> </TotalConsumPrice> <TotalConsumPrice> <Amount>0.33669</Amount> <Description>elektriciteit Enkeltarief (50.001 t/m 10 mln kWh):</Description> <Zone>3</Zone> </TotalConsumPrice> </ConsumptionPrice> <PriceGroups> <Description>Leveringskosten elektriciteit</Description> <SequenceNr>010</SequenceNr> <Percentage>79</Percentage> <Prices> <Description>Variabele leveringskosten Enkeltarief</Description> <SequenceNr>1</SequenceNr> <PriceType>SUP_ELEC</PriceType> <UnitPrice> <Amount>0.29282</Amount> </UnitPrice> <MonthlyPrice> <Amount>2440.17</Amount> </MonthlyPrice> <YearlyPrice> <Amount>29282</Amount> </YearlyPrice> <UoM>€/kWh</UoM> </Prices> <Prices> <Description>Vaste leveringskosten (€ 6,49 / maand)</Description> <SequenceNr>5</SequenceNr> <PriceType>FIXED_SUP_ELEC</PriceType> <UnitPrice> <Amount>0.21323</Amount> </UnitPrice> <MonthlyPrice> <Amount>6.49</Amount> </MonthlyPrice> <YearlyPrice> <Amount>77.83</Amount> </YearlyPrice> <UoM>€/dag</UoM> </Prices> <Prices> <Description>Totaal leveringskosten</Description> <SequenceNr>10</SequenceNr> <PriceType>SUBTOTAL_SUPPLY</PriceType> <TotalMonthlyPrice> <Amount>2446.66</Amount> </TotalMonthlyPrice> <TotalYearlyPrice> <Amount>29359.83</Amount> </TotalYearlyPrice> <UoM /> </Prices> </PriceGroups> <PriceGroups> <Description>Netbeheerkosten</Description> <SequenceNr>020</SequenceNr> <Percentage>1</Percentage> <Prices> <Description>Netbeheerder : Capaciteitstarief t/m 3 x 25A of t/m 1 x 80A (€ 250,81 / jaar)</Description> <SequenceNr>1</SequenceNr> <PriceType>CAPTAR_ELEC</PriceType> <UnitPrice> <Amount>0.68716</Amount> </UnitPrice> <MonthlyPrice> <Amount>20.9</Amount> </MonthlyPrice> <YearlyPrice> <Amount>250.81</Amount> </YearlyPrice> <UoM>€/dag</UoM> </Prices> <Prices> <Description>Totaal netbeheerkosten</Description> <SequenceNr>2</SequenceNr> <PriceType>SUBTOTAL_NETWORK</PriceType> <TotalMonthlyPrice> <Amount>20.9</Amount> </TotalMonthlyPrice> <TotalYearlyPrice> <Amount>250.81</Amount> </TotalYearlyPrice> <UoM /> </Prices> </PriceGroups> <PriceGroups> <Description>Belasting en toeslagen</Description> <SequenceNr>030</SequenceNr> <Percentage>20</Percentage> <Prices> <Description>Energiebelasting zone 1 (1 t/m 10.000 kWh)</Description> <SequenceNr>3</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.11408</Amount> </UnitPrice> <MonthlyPrice> <Amount>95.07</Amount> </MonthlyPrice> <YearlyPrice> <Amount>1140.8</Amount> </YearlyPrice> <UoM>€/kWh</UoM> </Prices> <Prices> <Description>Energiebelasting zone 2 (10.001 t/m 50.000 kWh)</Description> <SequenceNr>3</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.06248</Amount> </UnitPrice> <MonthlyPrice> <Amount>208.27</Amount> </MonthlyPrice> <YearlyPrice> <Amount>2499.2</Amount> </YearlyPrice> <UoM>€/kWh</UoM> </Prices> <Prices> <Description>Energiebelasting zone 3 (50.001 t/m 10 mln kWh)</Description> <SequenceNr>3</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.01664</Amount> </UnitPrice> <MonthlyPrice> <Amount>69.33</Amount> </MonthlyPrice> <YearlyPrice> <Amount>832</Amount> </YearlyPrice> <UoM>€/kWh</UoM> </Prices> <Prices> <Description>Opslag duurzame energie- en klimaattransitie zone 1 (1 t/m 10.000 kWh)</Description> <SequenceNr>4</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.0363</Amount> </UnitPrice> <MonthlyPrice> <Amount>30.25</Amount> </MonthlyPrice> <YearlyPrice> <Amount>363</Amount> </YearlyPrice> <UoM>€/kWh</UoM> </Prices> <Prices> <Description>Opslag duurzame energie- en klimaattransitie zone 2 (10.001 t/m 50.000 kWh)</Description> <SequenceNr>4</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.04973</Amount> </UnitPrice> <MonthlyPrice> <Amount>165.77</Amount> </MonthlyPrice> <YearlyPrice> <Amount>1989.2</Amount> </YearlyPrice> <UoM>€/kWh</UoM> </Prices> <Prices> <Description>Opslag duurzame energie- en klimaattransitie zone 3 (50.001 t/m 10 mln kWh)</Description> <SequenceNr>4</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.02723</Amount> </UnitPrice> <MonthlyPrice> <Amount>113.46</Amount> </MonthlyPrice> <YearlyPrice> <Amount>1361.5</Amount> </YearlyPrice> <UoM>€/kWh</UoM> </Prices> <Prices> <Description>Vermindering energiebelasting (€ -558,56 / jaar)</Description> <SequenceNr>7</SequenceNr> <PriceType>TAX_REDUCTION</PriceType> <UnitPrice> <Amount>-1.5303</Amount> </UnitPrice> <MonthlyPrice> <Amount>-46.55</Amount> </MonthlyPrice> <YearlyPrice> <Amount>-558.56</Amount> </YearlyPrice> <UoM>€/dag</UoM> </Prices> <Prices> <Description>Totaal belasting en toeslagen</Description> <SequenceNr>8</SequenceNr> <PriceType>SUBTOTAL_TAXES</PriceType> <TotalMonthlyPrice> <Amount>635.6</Amount> </TotalMonthlyPrice> <TotalYearlyPrice> <Amount>7627.14</Amount> </TotalYearlyPrice> <UoM /> </Prices> </PriceGroups> <PriceGroups> <Description>Totaal elektriciteit</Description> <SequenceNr>040</SequenceNr> <Percentage /> <Prices> <Description>Totaal elektriciteit</Description> <SequenceNr /> <PriceType>SUBTOTAL_ELEC</PriceType> <TotalMonthlyPrice> <Amount>3103.16</Amount> </TotalMonthlyPrice> <TotalYearlyPrice> <Amount>37237.78</Amount> </TotalYearlyPrice> <UoM /> </Prices> </PriceGroups> </OfferOverview> <OfferOverview> <Product> <EnergyType code="02" text="" /> <SegmentType code="HH" text="" /> <PropositionID>AW5_G_H_B-99</PropositionID> <PropositionDescription>Gas - Variabel - Flexibele looptijd</PropositionDescription> <Services> <Service code="LOOPTIJD" value="F" /> <Service code="VERBLIJFSFUNCTIE" value="1" /> </Services> <CARData> <Profile> <Origin>DEFAULT</Origin> <Profile code="G1A" text="" /> </Profile> <GridCompanyInformation> <Origin>DEFAULT</Origin> <GridCompany EAN="8716879000004" name="" /> </GridCompanyInformation> <NetAreaInformation> <Origin>DEFAULT</Origin> <NetArea EAN="871718518003003501" name="" /> </NetAreaInformation> <Residential> <Origin>REQUEST</Origin> <Value>1</Value> </Residential> <CapacityTariffInformation> <Origin>DEFAULT</Origin> <CapacityTariff code="8742010202112" text="8742010202112" /> </CapacityTariffInformation> <DeterminationComplex> <Origin>EDSN</Origin> <Value>00</Value> </DeterminationComplex> </CARData> </Product> <ConsumptionPrice> <TotalConsumPrice> <Amount>1.65003</Amount> <Description>tarief gas (1 t/m 170.000 m3):</Description> <Zone>1</Zone> </TotalConsumPrice> <TotalConsumPrice> <Amount>1.23296</Amount> <Description>tarief gas (170.001 t/m 1 mln m3):</Description> <Zone>2</Zone> </TotalConsumPrice> </ConsumptionPrice> <PriceGroups> <Description>Leveringskosten gas</Description> <SequenceNr>010</SequenceNr> <Percentage>64</Percentage> <Prices> <Description>Variabele leveringskosten (G1/gasregio 4)</Description> <SequenceNr>1</SequenceNr> <PriceType>SUP_GAS</PriceType> <UnitPrice> <Amount>1.1253</Amount> </UnitPrice> <MonthlyPrice> <Amount>23443.75</Amount> </MonthlyPrice> <YearlyPrice> <Amount>281325</Amount> </YearlyPrice> <UoM>€/m3</UoM> </Prices> <Prices> <Description>Vaste leveringskosten (€ 6,49 / maand)</Description> <SequenceNr>3</SequenceNr> <PriceType>FIXED_SUP_GAS</PriceType> <UnitPrice> <Amount>0.21323</Amount> </UnitPrice> <MonthlyPrice> <Amount>6.49</Amount> </MonthlyPrice> <YearlyPrice> <Amount>77.83</Amount> </YearlyPrice> <UoM>€/dag</UoM> </Prices> <Prices> <Description>Totaal leveringskosten</Description> <SequenceNr>7</SequenceNr> <PriceType>SUBTOTAL_SUPPLY</PriceType> <TotalMonthlyPrice> <Amount>23450.24</Amount> </TotalMonthlyPrice> <TotalYearlyPrice> <Amount>281402.83</Amount> </TotalYearlyPrice> <UoM /> </Prices> </PriceGroups> <PriceGroups> <Description>Netbeheerkosten</Description> <SequenceNr>020</SequenceNr> <Percentage>0</Percentage> <Prices> <Description>Netbeheerder : Capaciteitstarief t/m 10 m3/uur, stand. jaarv. tot 4.000 m3 (€ 181,52 / jaar)</Description> <SequenceNr>1</SequenceNr> <PriceType>CAPTAR_GAS</PriceType> <UnitPrice> <Amount>0.49731</Amount> </UnitPrice> <MonthlyPrice> <Amount>15.13</Amount> </MonthlyPrice> <YearlyPrice> <Amount>181.52</Amount> </YearlyPrice> <UoM>€/dag</UoM> </Prices> <Prices> <Description>Totaal netbeheerkosten</Description> <SequenceNr>2</SequenceNr> <PriceType>SUBTOTAL_NETWORK</PriceType> <TotalMonthlyPrice> <Amount>15.13</Amount> </TotalMonthlyPrice> <TotalYearlyPrice> <Amount>181.52</Amount> </TotalYearlyPrice> <UoM /> </Prices> </PriceGroups> <PriceGroups> <Description>Belasting en toeslagen</Description> <SequenceNr>030</SequenceNr> <Percentage>36</Percentage> <Prices> <Description>Energiebelasting zone 1 (1 t/m 170.000 m3)</Description> <SequenceNr>3</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.42176</Amount> </UnitPrice> <MonthlyPrice> <Amount>8786.67</Amount> </MonthlyPrice> <YearlyPrice> <Amount>105440</Amount> </YearlyPrice> <UoM>€/m3</UoM> </Prices> <Prices> <Description>Energiebelasting zone 2 (170.001 t/m 1 mln m3)</Description> <SequenceNr>3</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.07922</Amount> </UnitPrice> <MonthlyPrice> <Amount>1650.42</Amount> </MonthlyPrice> <YearlyPrice> <Amount>19805</Amount> </YearlyPrice> <UoM>€/m3</UoM> </Prices> <Prices> <Description>Opslag duurzame energie- en klimaattransitie zone 1 (1 t/m 170.000 m3)</Description> <SequenceNr>4</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.10297</Amount> </UnitPrice> <MonthlyPrice> <Amount>2145.21</Amount> </MonthlyPrice> <YearlyPrice> <Amount>25742.5</Amount> </YearlyPrice> <UoM>€/m3</UoM> </Prices> <Prices> <Description>Opslag duurzame energie- en klimaattransitie zone 2 (170.001 t/m 1 mln m3)</Description> <SequenceNr>4</SequenceNr> <PriceType /> <UnitPrice> <Amount>0.02844</Amount> </UnitPrice> <MonthlyPrice> <Amount>592.5</Amount> </MonthlyPrice> <YearlyPrice> <Amount>7110</Amount> </YearlyPrice> <UoM>€/m3</UoM> </Prices> <Prices> <Description>Totaal belasting en toeslagen</Description> <SequenceNr>8</SequenceNr> <PriceType>SUBTOTAL_TAXES</PriceType> <TotalMonthlyPrice> <Amount>13174.8</Amount> </TotalMonthlyPrice> <TotalYearlyPrice> <Amount>158097.5</Amount> </TotalYearlyPrice> <UoM /> </Prices> </PriceGroups> <PriceGroups> <Description>Totaal gas</Description> <SequenceNr>040</SequenceNr> <Percentage /> <Prices> <Description>Totaal gas</Description> <SequenceNr /> <PriceType>SUBTOTAL_GAS</PriceType> <TotalMonthlyPrice> <Amount>36640.17</Amount> </TotalMonthlyPrice> <TotalYearlyPrice> <Amount>439681.85</Amount> </TotalYearlyPrice> <UoM /> </Prices> </PriceGroups> </OfferOverview> </Offers> <DisclaimerRegion>ZUID</DisclaimerRegion> <DisclaimerCode>ZAOMDIS_DEF_ND</DisclaimerCode> <DisclaimerURL>https://www.essent.nl/content/system/HTML/disclaimers/ZAOMDIS_DEF_ND.html</DisclaimerURL> <OfferType>SA</OfferType> <PaymentMethods> <PaymentMethod code="Automatische incasso" text="Automatische incasso" AdminCost="0" DiscountCost="-0.605" /> <PaymentMethod code="Handmatige betaling" text="Handmatige betaling" AdminCost="2.42" DiscountCost="2.42" /> </PaymentMethods> <VAT>true</VAT> <Messages> <Message> <Type>I</Type> <Code /> <Message>Success</Message> </Message> </Messages> </response> </HandleOfferDetails> |
🠕 This side up
Apple iPhone 16e LG OLED evo G5 Google Pixel 10 Samsung Galaxy S25 Star Wars: Outlaws Nintendo Switch 2 Apple AirPods Pro (2e generatie) Sony PlayStation 5 Pro
Tweakers is onderdeel van
DPG Media B.V.
Alle rechten voorbehouden - Auteursrecht © 1998 - 2025
•
Hosting door TrueFullstaq