Webblog

GDPR voor softwaredevelopers

GDPR voor softwaredevelopers

Toegegeven, het is voor de meeste ontwikkelaars niet het favoriete onderwerp en het is ook niet nieuw, tegelijkertijd is basiskennis van GDPR en AVG belangrijk om te voorkomen dat we onszelf in de voet schieten. Dit artikel geeft een samenvatting van ons webinar en we hopen je hiermee op weg te helpen om een basis begrip te hebben van deze belangrijke Europese wetgeving.

Voor wie is de GDPR van toepassing?

De GDPR wetgeving is bedoeld om personen, lees inwoners van de EU, te beschermen m.b.t. elke vorm van dataverwerking van persoonlijke data. De wetgeving gaat veel verder dan alleen het beschermen van privacy. Zodra je als organisatie gegevens van personen in beheer hebt, dan ben je gebonden aan de GDPR wetgeving. Omdat GDPR gaat over mensen, heeft de wetgeving geen betrekking op gegevens over bedrijven of geanonimiseerde gegevens. Met die laatste categorie moet je voorzichtig zijn, omdat het soms mogelijk is om anonieme data alsnog aan personen te koppelen door databestanden te combineren. In dat geval is de data niet anoniem.

Waar is de GDPR van toepassing?

De GDPR is van toepassing op alle burgers binnen de EU waarbij Noorwegen en IJsland zich aan de wetgeving hebben verbonden. Groot Brittannië heeft inmiddels een zelfstandige, maar identieke versie van de GDPR in gebruik. Let op de GDPR is van toepassing op alle verwerking van data van burgers en dus niet van de locatie van het bedrijf dat deze data verwerkt. Dus ook bedrijven die buiten de EU gevestigd zijn, dienen zich te houden aan de GDPR als ze data van inwoners van de EU landen verwerken. Als data buiten de EU opgeslagen of verwerkt wordt, moet dit expliciet aan de burger gemeld worden.

Rollen binnen GDPR?

De GDPR kent drie specifieke rollen: de data subject, de data controller en de data processor. De data subject is de formele term voor de levende persoon waar data van verwerkt wordt. De data controller is de rechtspersoon die bepaalt hoe en waarvoor data wordt verwerkt. De data processor is een organisatie die in opdracht van de data controller taken uitvoert. Neem een praktisch voorbeeld van data over mijzelf als werknemer. Dan ben ik zelf het data subject, mijn werkgever is de data controller, en als de werkgever gebruik maakt van een SAAS dienst om mijn personeelsdossier bij te houden, dan is deze SAAS aanbieder de data processor. Data controller en data processor delen binnen GDPR het de verantwoordelijkheid. De data controller is eindverantwoordelijk, maar een data processor kan zich daar niet achter verschuilen.

Principes binnen GDPR

De GDPR gaat veel verder dan alleen privacy regelgeving. Het gaat over verantwoordelijk omgaan met data van burgers. Dit betekent:

  • Dat data wordt opgeslagen met een rechtmatige reden;
  • Dat alleen wordt opgeslagen wat nodig is om de taak uit te voeren waarvoor je de data opslaat;
  • Dat je ervoor verantwoordelijk bent dat de data juist is;
  • Dat je de data verwijderd (of anonimiseert) als deze niet meer nodig is;
  • Dat de data veilig wordt bewaard;
  • Dat je als organisatie aantoonbaar verantwoordelijkheid neemt over de data die je onder je hoede hebt (denk aan ISO certificeringen etc.).

Rechtmatige redenen om data te bewaren

Het is belangrijk om na te gaan welke data je beheert en vooral waarom je die data hebt. Het is alleen toegestaan om data over personen op te slaan als je voldoet aan één of meerdere van de volgende redenen:

  • Er is sprake van een contract tussen data subject en data controller;
  • Er is een wettige reden om data op te moeten slaan (denk aan de belastingdienst die data over burgers moet vastleggen conform wetten die gelden);
  • Het vastleggen van de data beschermd een vitaal belang (denk aan zaken rondom gezondheidszorg);
  • De data dient een publiek belang of is vastgelegd door een overheidsinstantie;
  • Er is sprake van een legitiem belang om de data vast te leggen (dit is voer voor juristen);
  • In alle andere gevallen mag data alleen worden vastgelegd op basis van toestemming van de persoon in kwestie. Dit wordt ook wel op basis van “consent” genoemd.

Speciale categorie data

Binnen de GDPR zijn er speciale categorieën van data die ervoor zorgen dat je aanvullende maatregelen moet nemen. Het gaat om de volgende vier categorieën:

  • Data die kan bijdragen aan discriminatie. Dit is van toepassing op data over afkomst of ras, maar ook bijvoorbeeld data m.b.t. geloofsovertuiging;
  • Data die een verhoogd risico geeft op identiteitsfraude. Strikt genomen zijn vooral biometrische of genetische data benoemd, maar zaken als burger-servicenummer of bankgegevens worden ook onder speciale data geschaard;
  • Elke vorm van medische data;
  • Data over het seksleven of seksuele oriëntatie.

In principe gelden dezelfde rechtmatige redenen, alleen ze worden veel strenger toegepast. Met andere woorden: als je deze data wilt opslaan en verwerken, dan zul je juridisch moeten toetsen of de reden voldoende onderbouwd is. Daarnaast gelden strengere eisen voor beveiliging en toegang. Denk bijvoorbeeld aan het versleuteld opslaan van de data.

Er is één speciale reden benoemd voor het vastleggen van speciale categorie data en dat is als het hebben van deze data onderdeel is van de natuur van de organisatie. Denk hierbij aan de ledenlijst van een geloofsgemeenschap. Overigens ontslaat dat deze organisaties er niet van dat de persoon in kwestie expliciet toestemming geeft dat zijn gegevens worden opgeslagen.

Rechten van de “data subject”

Tot nu toe hebben we gekeken naar geldige redenen om data op te slaan conform de GDPR regels. De wetgeving geeft ook aan welke rechten een burger heeft in relatie tot de organisatie die zijn/haar data verwerkt:

  • Iemand heeft het recht om geïnformeerd te worden als zijn/haar data ergens gebruikt wordt. Specifiek zijn de volgende zaken benoemd die in zo’n kennisgeving verwerkt moeten zijn:
    • Wat is de wettelijke reden waarom data wordt gebruikt (zie rechtmatige redenen eerder in dit document). Indien de wettelijke reden is op basis van toestemming, dan dient ook benoemd te worden dat deze toestemming op elk moment ingetrokken mag worden;
    • Wat is de bewaartermijn van de data;
    • Benoeming van de rechten onder GDPR die de persoon in kwestie heeft;
    • Of de persoon verplicht is de data te verstrekken (dit is bijvoorbeeld het geval bij contracten)’
    • Of de data wordt gebruikt voor automatische profilering (machine learning of AI).
  • Iemand heeft het recht om op te vragen welke data over hem/haar is opgeslagen.
  • Iemand heeft het recht om incorrecte data te laten corrigeren.
  • Iemand heeft het recht om te vragen dat data verwijderd wordt (dit is geen absoluut recht, want het kan zijn dat de data niet verwijderd mag worden vanwege wetgeving of omdat sprake is van een contract).
  • Iemand heeft het recht om te vragen dat de dataverwerking stopgezet wordt.
  • Iemand heeft het recht bezwaar aan te tekenen tegen het gebruik van persoonlijke data.
  • Iemand heeft expliciet het recht om bezwaar te maken tegen automatische profilering.

blank

In de laatste versie van GDPR is er ook het recht op overdraagbaarheid van data bijgekomen, maar in de praktijk weet nog niemand goed hoe we hier handen en voeten aan moeten geven omdat er geen standaarden zijn om data van de ene naar de andere organisatie over te dragen.

Vanaf het moment dat een burger een verzoek doet op basis van de rechten die hij/zij binnen GDPR heeft, is de organisatie verplicht om binnen 30 dagen te reageren. Dit betekent dat het belangrijk is dat handelingen die nodig zijn, geautomatiseerd worden en dat er over nagedacht is in het ontwerp van software.

Plichten voor de data controller / processor

In principe gelden de verplichtingen binnen GDPR vooral voor de data controller, maar in de praktijk zullen een hoop zaken verzorgd worden door de data processor dus deze moet ook voldoen aan de wetgeving. De belangrijkste verplichtingen zijn:

  • Je bent verplicht om de verantwoordelijkheid te nemen over de data die je in beheer hebt. In de praktijk betekent dit dat je bestuurlijke organisatie en processen op orde moeten zijn.
  • Je bent verplicht om data te beveiligen. Dit gaat breder dan alleen technische beveiliging, het gaat er over dat je kunt aantonen verantwoordelijk met de toegang tot persoonlijke data om te gaan. Incidenten moeten binnen 72 uur nadat ze ontdekt zijn gemeld worden aan de instanties.
  • Voor organisaties van meer dan 250 medewerkers ben je verplicht bij te houden wie, wanneer toegang tot data heeft (gehad). Omdat deze eis vaak behoorlijk ingrijpt op software ontwerp, is mijn advies om deze eis altijd mee te nemen in onze ontwerpen, ook als de organisatie nu nog onder de norm van het aantal medewerkers valt.
  • Het is een open deur, maar het is verplicht om mee te werken met officiële instanties, voor Nederland de Autoriteit Persoonsgegevens.

blank

Naast de bovenstaande verplichtingen kan het zijn dat je als organisatie een “data protection impact assessment” moet doen. Dit is altijd verplicht als je op grote schaal automatische profilering toepast, speciale categorie data verwerkt of beelddata van publiek toegankelijke ruimte verwerkt. Als laatste, kan het zijn dat je een data protection officer in dienst moet hebben. Dit is altijd het geval als je een overheidsinstantie bent, of als je de verplichting tot een data protection impact assessment hebt. Een data protection officer (DPO) kan als rol of functie worden vervuld mits een aantal spelregels in acht worden genomen:

  • De DPO wordt geraadpleegd bij beslissingen rondom persoonlijke data;
  • De DPO heeft voldoende mogelijkheden om zijn werk te doen (in tijd en middelen);
  • De DPO heeft een beschermde status en kan onafhankelijk werken;
  • De DPO heeft kennis van zaken.

Sancties binnen GDPR

Het meest spraakmakende van de GDPR ten opzichte van vorige wetgeving, zijn de sancties op overtredingen. Die liegen er niet om met boetes van 20 miljoen tot 4% van de omzet van een organisatie. In de praktijk zijn instanties vooral betrokken om organisaties te helpen hun verantwoordelijkheid omtrent data gebruik te nemen. Tegelijk zijn er voorbeelden van boetes. Op de site https://www.timelex.eu staat een overzicht van een aantal sancties die zijn opgelegd om een beter beeld te krijgen van scenario’s waarin boetes zijn opgelegd.

Wat betekent dit voor ons als software developers?

Een gedeelte van de GDPR wetgeving heeft vooral betrekking op processen, tegelijk zijn er zaken waar we als ontwikkelaars rekening mee moeten houden bij het bouwen van onze software:

  • Zorg dat persoonsdata op te leveren zijn indien een burger een verzoek doet om zijn/haar data te ontvangen (en tegelijk dat de data niet door iedereen zomaar opgevraagd kan worden);
  • Sla alleen data op die echt nodig is;
  • Zorg dat data verwijderd of geanonimiseerd kan worden en processen die dit ook op tijd doen;
  • Zorg voor gedegen autorisatie en authenticatie;
  • Monitor en registreer data toegang en wijzigingen;
  • Wees bijzonder voorzichtig met allerhande vormen van exporteer en rapportage functies waardoor data uit systemen gehaald kan worden in bulk;
  • Versleutel gevoelige data altijd;
  • Waarborg dat data correct is, en hersteld kan worden bij calamiteiten;
  • Goede beveiliging en regelmatige pentesten zijn een must;
  • Voorkom dat data die voor verschillende doelen gebruikt wordt, en/of andere bewaartermijnen heeft, met elkaar verstrengeld raakt;
  • Ga voorzichtig om met logging waarin persoonsdata terugkomt.

Bronverwijzing

Voor dit artikel is gebruik gemaakt van de Pluralsight cursus “GDPR: The Big Picture”. Je vindt de volledige cursus op Pluralsight: https://app.pluralsight.com/library/courses/gdpr-big-picture/table-of-contents

© Auteur: Menno Jongerius © 2022 Bergler Competence Center

Lees ook…

blank

.NET 6 Update

8 december 2021
berglerGDPR voor softwaredevelopers
Lees meer

“To Manage vs To Lead”

“To Manage vs To Lead”

Onlangs werd ik geconfronteerd met de vraag wat het verschil is tussen “managing a team” en “leading a team”. Als Scrum Master van (internationale en remote) teams intrigeert me deze vraag. Het doel van dit artikel is om mijn kennis en ervaring hierover te delen.

Hoewel veel mensen de termen “manage” en “lead” door elkaar gebruiken, zijn er wezenlijk verschillen in de context en betekenis van deze termen. De verschillen zijn voor een groot deel te verklaren met de verschillen tussen de waterval methoden en “agile” methoden. Het managen van teams heeft de nadruk op controleren, delegeren en beperken van verandering. Het leiden van teams heeft de nadruk op faciliteren, beschermen en inspireren.

Perspectief: waterval en agile

Hoewel er genoeg is geschreven over transitie van waterval naar agile principes, wil ik er toch graag mijn perspectief aan toevoegen. Bij de toepassing van waterval principes (bv Prince2) wordt succes van een project bepaald door het behalen van doelstellingen scope, kosten en tijd.

Mijn ervaring is dat als ik het succes van een agile aanpak moet vaststellen, ik naar kengetallen kijk die iets zeggen over de toegevoegde waarde, kwaliteit en kaders. Hierbij stel ik als kaders de scope, kosten en tijd.

Dit artikel gaat niet over hoe toegevoegde waarde gemeten kan worden.  Ik voorzie hierover een toekomstig blog artikel wat gaat over ‘Evidence Based Management’.

De waterval is bruikbaar bij voorspelbare en minder complexe domeinen. Agile werkmethoden passen uitstekend in complexe en onvoorspelbare domeinen.  Welke werkmethode ook wordt toegepast, er is altijd een bepaalde stijl van leiderschap noodzakelijk. Men kan stellen dat de stijl van het ‘managen’ past bij waterval werkmethode. Bij een agile domein (project) past de stijl van leiden beter.

In het vervolg van dit artikel wil ik ingaan op verschillen tussen de leiderschap stijlen.

Gedrag van het team

De Engelse taal heeft twee termen die het delegeren van verantwoordelijkheid beschrijven;

  • Je bent ‘accountable’ zodra je het eigendom van het resultaat van een activiteit hebt. Je bent de opdrachtgever van de activiteit. De ‘accountable’ persoon zorgt voor uitleg van het ‘waarom’ van een activiteit en kaders waarin deze kan worden gerealiseerd
  • Je bent ‘responsible’ zodra je de activiteit uitvoert. Uit naam van de opdrachtgever wordt een activiteit uitgevoerd met een specifiek doel

De term ‘waterval’ heeft een ‘top-down’ benadering. De manager bepaalt en delegeert het werk naar zijn teamleden. Dit levert een hoge mate van controle door de manager en lage autonomie van het team. Het risico bestaat dat het team in dergelijke werkmethode een lage ‘accountability’ vertoont. Dit kan tot het volgende gedrag leiden:

  • Team leunt achterover zodra werkvoorraad opdroogt
  • Team neemt geen eigenaarschap over ontstane issues
  • Team is niet transparant in het delen van de voortgang

De ‘top-down’ benadering geeft het Team ook informatie over hoe het team functioneert.

Bij het toepassen van agile werkmethoden wordt het waarom van een activiteit door de leider toegelicht en verfijnd in samenwerking met het team. Het team neemt de ‘accountability’ op zich om de oplossingsrichting naar het doel van de activiteit te definiëren en uit te voeren. Dit levert in de praktijk het volgende gedrag op:

  • Team bepaalt zelf de volgorde van de uit te voeren activiteiten
  • Team daagt zichzelf uit om binnen de kaders van de activiteit (tijd) tot het resultaat te komen
  • Teamleden spreken elkaar aan voor hun verantwoordelijkheid van de activiteiten

Doordat teamleden elkaar aanspreken, biedt dit ruimte voor het team om ‘accountability’ te nemen en haar functioneren te verbeteren.

Gedrag van de manager en leider

Ik maak onderscheid tussen de rol van manager en leider. De manager is de persoon die een project volgens de waterval werkmethode leidt. De leider is de persoon die een agile project leidt. In de praktijk zouden beide stijlen moeten resulteren in verschillende activiteiten.

De leider

Een leider zorgt voor:

  • Bescherming van het team van afleiding die het realiseren van de doelstelling in gevaar brengt
  • De middelen die het team nodig heeft om de doelstelling te realiseren
  • Samenhang en samenwerking van het team
  • Transparante beschrijving van het waarom van de activiteiten

Dit betekent niet dat de leider geen verantwoordelijkheid heeft voor enkele klassieke ‘management taken’ zoals:

  • Bewaking van het opbranden van het budget in relatie tot de ‘burn-up’ van gewenste functionaliteiten (loopt het project op schema)
  • Bewaking van risico’s die door de organisatie of het team worden geïdentificeerd

Zorgen voor is het kernwoord. De leider faciliteert de middelen en het proces voor het team zodat deze optimaal kan functioneren.

De leider luistert eerst alvorens het team aan te spreken. De leider spreekt altijd over ‘wij’ waarbij hij uitstraalt dat er een gezamenlijke verantwoordelijkheid bestaat over de activiteit. Een leider zorgt voor voortgangsrapportage in de vorm van opgeleverde deelproducten waarbij toegevoegde waarde is getoetst. De leider rapporteert voorgang in het perspectief van ‘effectiveness’, waarbij hij kijkt naar het juiste product op het juiste moment.

Een leider delegeert het toewijzen van taken aan het team waardoor het team zelf zorgt voor de taakverdeling.

Ondanks dat een leider veel ‘accountability’ overlaat aan het team, blijft hij zelf verantwoordelijk voor het behouden van overzicht en voortgang. Net zoals de manager zorgt de leider voor de administratie van het opgeleverde werk, de inspanningen en andere kosten. De leider faciliteert de stakeholders en eventueel de Product Owner bij het opstellen van een lange termijnvisie (Roadmap) en korte termijn implementatie plan (Product Backlog). Door middel van workshops wordt kennis vergaard over het ‘waarom’ en ‘wat’ van toekomstig werk. Deze informatie is cruciaal voor een team om te komen tot het ‘hoe’, de implementatie van de oplossing.

Tijdens overleggen begeleidt de leider de werkvorm en zorgt ervoor dat er optimale bijdrage wordt geleverd door alle teamleden. De inhoud tijdens het overleg wordt door het team uitgewerkt.

De Manager

Een manager definieert en bewaakt:

  • De prioriteit van de activiteiten
  • Wie de activiteit uitvoert
  • Effectiviteit van de activiteiten
  • Veranderingen

De manager speelt een sterke rol bij het toewijzen van taken aan teamleden en volgt de voortgang van deze taken. De manager rapporteert de voortgang in de vorm van kengetallen in de context van tijd, prijs en scope. De manager stuurt aan op minimalisatie van verstoringen op de uit te voeren activiteiten. In andere woorden; de Manager bekijkt voortgang vooral vanuit het perspectief van ‘efficiency’, wordt product geleverd binnen het budget en tijd.

De manager bewaakt risico’s voor het project conform een vooraf afgesproken proces. Tijdens de definitie van het project worden deze volgens een proces van kans, effect en maatregelen opgesteld. Vaak gekoppeld aan een proces van ‘change management’. Tijdens overleggen legt de Manager veelal het proces op aan de betrokkenen en leidt hij de inhoudelijke discussie.

In het blog van Bergler Software Solutions zijn veel andere artikelen te vinden. Mijn collega’s delen hun ervaringen op het gebied van softwareontwikkeling, security en devops. Graag blijven we in de moeizame Coronatijd verbonden met elkaar!

© Auteur: Arjen Kraak © 2021 Bergler Competence Center

Lees ook…

blank

.NET 6 Update

8 december 2021
bergler“To Manage vs To Lead”
Lees meer

.NET 6 Update

.NET 6 Update

Op 9 november 2021 kwam de nieuwe versie van .NET uit. We gaven bij .NET 5 al aan dat Microsoft afscheid neemt van het fullstack framework. Deze .NET 6 release is de eerste long term support versie na dit moment, en daarmee voor een hoop organisaties de eerste serieuze versie om naar te migreren.

.NET Framework stopt? … o shit, maar wat betekent dat voor mij?

Als je kijkt naar de ondersteuning van de .NET Framework versies dan staan voor de meest recente versies nog geen eind datums genoemd:

.Net 6 Update

Van .NET Framework 4.8 garandeert Microsoft support zolang het draait op een ondersteund Windows platform. Dat plaatst de einddatum rond 2029, maar gezien de uitdaging die bedrijven hebben om hun software om te zetten naar de nieuwe versie(s), verwacht ik dat deze datum nog naar achter kan schuiven. Het geeft wel aan dat er urgentie is om je bestaande systemen om te zetten, en een gedegen vernieuwingsstrategie op te zetten.

Wat is .NET 6

blank

Met .NET 6 is er voortaan echt één platform dat voor alle doeleinden gebruikt kan worden. Een groot deel van de inspanning van Microsoft is gaan zitten in het optimaliseren van de prestaties en het stresstesten van .NET in productie scenario’s. Meer details vind je op: devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/

Gemiddeld is .NET 6 een factor 10 tot 50 keer sneller dan .NET Framework 4.8 en een factor 2 tot 10 keer sneller dan .NET 5. Voor toepassing in IOT devices is dit een spectaculaire verbetering.

Functionele verbeteringen

Op het gebied van beveiliging zijn er een groot aantal uitbreidingen en verbeteringen doorgevoerd. Zo ondersteund .NET 6 voortaan  OpenSSL 3 en ChaCha20Poly1305.

Voor IOT en mobiele apparaten worden nu ook Arm64 processoren volledig ondersteund, op alle bekende besturingssystemen. Betere support betekent in dit geval ook dat .NET 6 beter draait in container oplossingen. Daarnaast is de ondersteuning voor Windows containers uitgebreid, hoewel dat misschien meer iets is voor de echte Microsoft fanaten, want ik ken weinig praktijkvoorbeelden van organisaties die voor hun lol iets met Windows containers doen.

Met de dotnet monitor is de monitoring voor containers behoorlijk uitgebreid.

Voor Windows Forms zijn op het gebied van de toegankelijkheid en het instellen van applicatie brede templates verbeteringen doorgevoerd. Ook is het voortaan mogelijk om de gecompileerde applicatie te comprimeren zodat deze minder schijfruimte in beslag neemt.

Gezien het intensieve gebruik van Websockets in verschillende bovenliggende technieken, is er geïnvesteerd in de performance en compressie van websockets.

Blazor for the win

Een mooie uitbreiding is er op het gebied van Blazor en dan vooral de mogelijkheid om met Blazor .NET MAUI apps te schrijven. Dit betekent dat je met één technologie platform single page web applicaties en native apps oplevert. Om sneller te laden is er een prerendering optie gemaakt waarbij de website de eerste pagina alvast op de server maakt en naar de client stuurt, terwijl de assembly componenten worden gedownload.

Verbeteringen voor de developer

.Net 6 Update

Met de komst van .NET 6 komt ook de nieuwe versie van Visual Studio uit. Hierin zitten erg gave features waarvan de mooiste volgens mij de Hot Reload functie is. Deze functie maakt het mogelijk om een applicatie terwijl hij draait aan te passen. Daarnaast is Visual Studio voortaan 64 bit waardoor zelfs de grootste solutions niet meer voor geheugenproblemen zorgen. Ook op het gebied van samenwerking en personalisatie zijn veel verbeteringen doorgevoerd.

Tenslotte is natuurlijk ook C#10 uitgekomen, maar hier moest ik maar een losse blogpost aan wijden.

Conclusie

We worden dit jaar verwend met een enorm scala aan mooie nieuwe features, eigenlijk teveel om op te noemen. Hopelijk maakt dit artikel je nieuwsgierig om zelf ook eens te kijken. Je zult niet teleurgesteld zijn…

bergler.NET 6 Update
Lees meer

Rebase versus (up)merge

Rebase versus (up)merge

Als ik kijk naar de adoptie van Git in de Microsoft Stack dan kan het niet anders dan concluderen dat de meeste bedrijven die ik bezoek inmiddels de overstap hebben gemaakt van TFS flow naar Git-based source control. In die overstap zijn er een hoop basisprincipes van Git die lastig zijn als je vanuit de TFS wereld naar Git kijkt. Ik wilde er graag eentje uitpikken waarvan ik merk dat men er mee worstelt en dat is de functionaliteit van merge versus die van rebase. Ik moet eerlijk zeggen dat er overigens bij teams verschillende strategieën leven ten opzichte van het gebruik van rebase, dus het is onvermijdelijk dat ik hier mijn voorkeur promoot.

Wat is rebase in vergelijking met een merge

Voordat ik verder in de details duik is het belangrijk om goed te begrijpen wat een rebase en een merge nu eigenlijk zijn. Hiervoor is het van belang om te begrijpen dat elke commit in git een setje aan veranderingen vertegenwoordigt ten opzichte van de commit ervoor:

blank

In het voorbeeld hierboven is er een feature aangemaakt waarop een aantal commits zijn uitgevoerd. Bij het aanmaken van een feature branch, onthoudt git op basis van welke commit de feature gemaakt is en vervolgens wordt elke nieuwe commit daar aan vastgeknoopt.

blank

Maar wat gebeurt er als in de tussentijd er ook wijzigingen zijn geweest op de master branch. Voordat de feature branch terug kan worden gebracht in de master branch (meestal met een pull request), wil je deze wijzigingen lokaal testen om te valideren dat er geen impact is op de wijzigingen die je zelf aan het maken bent.

Optie 1 voer een merge uit van de master naar je feature branch

blank

Een veel gebruikte manier om deze wijzigingen te lokaal te verwerken, is door ze middels een merge naar je feature branch te halen. In dat geval maakt Git een merge-commit aan en komen de wijzigingen van de master terug in jouw eigen branch. Het nadeel van deze methode is dat de historie lastiger te lezen kan zijn vanwege de vele merge commits die op deze manier gedaan worden. Het voordeel is dat deze actie altijd veilig is, doordat bestaande branches en commits met rust worden gelaten.

Optie 2 voer een rebase uit van de master naar je feature branch

blank

Een tweede manier om de wijzigingen van de master branch in je feature branch te krijgen, is met een rebase. In dit geval zal git je feature “oppakken” en de wijzigingen van de master voor je feature zetten. Het gevolg hiervan is dat de oude commits op de feature branch “stale” worden en dat er volledig nieuwe commits geschreven worden om de project historie te herschrijven. Het voordeel van deze manier van werken is een schonere historie in Git met minder merge-commits. Het belangrijkste nadeel is dat het herschrijven van de project historie een potentieel gevaarlijke actie is.

Risico bij het uitvoeren van een rebase

Zoals je in het bovenliggende plaatje ziet, zal een rebase je volledige branch “oppakken” en verplaatsen ten opzichte van de commits op de branch die je naar je feature rebaset. Maar stel dat je feature branch gepubliceerd is en dat er andere collega’s ook op werken. In dat geval is het werk wat beiden doen uit sync en is het heel lastig om dat weer recht te trekken. Gebruik daarom geen rebase op werk dat al naar een remote branch gepubliceerd is.

Wanneer gebruik je rebase en wanneer merge

Als je aan het werk bent aan een lokale feature die je wilt gaan afronden en in de tussentijd zijn er wijzigingen gedaan die je lokaal wilt verwerken, dan is een rebase een prima manier om deze wijzigingen te integreren. In de uiteindelijke historie geeft dat een mooier overzicht en omdat de wijzigingen toch enkel lokaal staan is er geen enkel risico. Is echter je branch gepubliceerd, dan is het niet verstandig een rebase uit te voeren en verwerk je eventuele wijzigingen met een merge.

Maar wat is nu een pull request?

Dan misschien nog als toetje op de pudding: wat is nu een pull request? Je hebt een feature gemaakt en het team geeft aan dat je deze feature na afloop met een pull request terug naar de master moet brengen. Eigenlijk is een pull request hierbij een speciaal soort merge waarbij een mechanisme in werking treedt dat ontwikkelaars ondersteunt om de wijzigingen eerst te beoordelen voordat de merge definitief wordt gemaakt. Dit is een mooie manier om de wijzigingen van een ontwikkelaar te laten peer reviewen door één of meerdere andere ontwikkelaars.

Lees ook…

blank

.NET 6 Update

8 december 2021
berglerRebase versus (up)merge
Lees meer

gRPC, wat is het en wanneer gebruik je het?

gRPC, wat is het en wanneer gebruik je het?

Als je op de hoogte bent van de ontwikkelingen van .NET (Core), dan weet je waarschijnlijk dat Microsoft geen WCF-projecten meer ondersteunt. Tegelijkertijd zijn gRPC projecten toegevoegd aan het portfolio van serviceoplossingen. Maar wat is gRPC, hoe verhoudt deze technologie zich tot OpenAPI of GraphQL en wanneer zou je gRPC inzetten? Op deze vragen wil ik in deze blogpost ingaan.

API driven development in een breder perspectief

Voordat ik de details in duik van de verschillende serviceprotocollen, wil ik stilstaan bij het waarom van deze ontwikkeling. Toen ik twintig jaar geleden begon met softwareontwikkeling, was het redelijk standaard dat applicaties als monoliet werden gebouwd. Dit model was eenvoudig en bestond vaak uit een client applicatie met een database. Naarmate applicaties groter en complexer werden, ontstond de wens om de monoliet op te splitsen in kleinere blokken. Een oplossingsrichting om hiermee om te gaan, was de Service Oriented Architecture. Binnen de Microsoft stack betekende dat meestal applicaties die opgebouwd waren uit WCF-services. Daarnaast kon je met deze services relatief eenvoudig externe partners aansluiten op je applicatie landschap. Nadeel is dat het gebruikte SOAP protocol log en relatief traag is. Met de opkomst van webapplicaties en apps werd in rap tempo overgestapt op WebAPI’s. De meeste van deze API’s voldoen aan de OpenAPI standaarden en implementeren in meer of mindere mate de principes van een RESTful api.

Risico van de populariteit van WebAPI’s is in lijn met de uitspraak: als je alleen een hamer hebt, ziet elk probleem er als een spijker uit.

De laatste jaren zijn er naast de bekende OpenAPI standaarden nieuwe standaarden uitgekomen die elk hun eigen probleemgebied oplossen. Door de juiste techniek in te zetten op de juiste plek, maak je een betere softwareoplossing.

OpenAPI versus graphQL versus gRPC

blank

Naast de populaire OpenAPI standaard, zijn momenteel graphQL en gRPC opkomende alternatieven. GraphQL is vooral krachtig wanneer je de client meer specifiek data wilt laten opvragen. Het is een mooie techniek waarmee aan de hand van een schemadefinitie de client specifiek gegevens op kan vragen bij een enkel query endpoint. GraphQL ondersteunt ook mutaties waardoor je snel een rijke client kunt bouwen. De gRPC standaard is ontwikkeld om snelle en directe communicatie tussen (micro)services op te zetten. Het binaire formaat maakt de communicatie effectief en de protobuffer contracten maken het een platformonafhankelijke oplossing.

Wat is gRPC

RPC of Remote Procedure Calls zijn een van de oudste manieren om API-communicatie op te zetten. De Google implementatie ervan is een nieuwe techniek om op uniforme manier machine to machine communicatie mogelijk te maken. De basis van een gRPC service is de servicedefinitie die in een protocol buffer file is opgesteld:

blank

De definitie in deze proto file bepaalt hoe zowel de client als de server opgebouwd worden en vormt het contract tussen beide partijen. De gebruikte taal is goed gedocumenteerd door Google.

Op basis van de proto file zal Visual Studio alle benodigde code genereren om een server of client te maken. De implementatie van de code bepaal je zelf, door de gegenereerde base classes te implementeren:

blank

Ook de client wordt automatisch gegenereerd op basis van de proto file:

blank

Voorwaarden om gRPC te gebruiken

Een gRPC service draait alleen over http/2 met TLS. Wanneer je de native Kestrel server gebruikt binnen .NET, heb je standaard support voor http/2. Binnen IIS moet je extra werk doen om gRPC te kunnen hosten: zie hiervoor de Microsoft documentatie.

Belangrijkste voordelen van gRPC

  • Bijzonder lage latency
  • Optimaal om in een distributed systeem (micro)services met elkaar te laten communiceren
  • Breed ingezet door onder andere Netflix, Cloudfare, Google en Docker
  • Ondersteunt bi-directionele streaming

Wanneer gebruik je gRPC

Vrijwel alle implementaties van gRPC zijn bedoeld voor interne snelle communicatie in een distributed systeem. Een gRPC implementatie maakt het mogelijk dat twee services met elkaar communiceren met dezelfde eenvoud als wanneer ze een interne methode aan zouden roepen. Wanneer je gRPC services publiek toegankelijk wilt maken, zul je na moeten denken over de beveiliging. Een gRPC service ondersteunt token based security, maar je zult in dit geval zowel op de client als op de server extra code moeten schrijven. Een gRPC service is niet geschikt voor communicatie met web clients. Er zijn wel initiatieven op dit gebied met gRPC web, maar dat lijkt op zoeken van een oplossing voor een niet‑bestaand probleem omdat juist voor weboplossingen OpenAPI standaarden heel goed werken.

Kennismaken met gRPC

Er is goede documentatie beschikbaar over het implementeren van gRPC in .NET. De documentatie van Microsoft is een prima startpunt om je eerste eigen service op te zetten:

https://docs.microsoft.com/en-us/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-5.0&tabs=visual-studio

Daarnaast is de documentatie voor het maken van de proto file goed beschreven:

https://developers.google.com/protocol-buffers/docs/overview

© Auteur: Menno Jongerius © 2021 Bergler Competence Center

Volg ook ons webinar over gRPC op 5 oktober aanstaande! Meer informatie en gratis aanmelden >>>

Lees ook…

blank

.NET 6 Update

8 december 2021
berglergRPC, wat is het en wanneer gebruik je het?
Lees meer

GitHub actions vs Azure DevOps Pipelines

GitHub actions vs Azure DevOps Pipelines

Nadat Microsoft in 2018 GitHub heeft overgenomen was het even afwachten welke in richting GitHub zou bewegen. Zou het een separate merknaam blijven of zou het geassimileerd worden binnen de bestaande Microsoft portefeuille? Nu na 3 jaar is het veilig om te zeggen dat GitHub als merk blijft bestaan. Vrij logische keuze omdat Microsoft welliswaar zijn eigen tegenhanger heeft met Azure DevOps maar het marktaandeel van GitHub is vele malen groter. Zeker als we sec kijken naar de source control mogelijkheden. (77% voor github vs 6% voor DevOps volgens een onderzoek van JetBrains: https://www.jetbrains.com/lp/devecosystem-2020/team-tools/)

Beide services bieden veel meer dan alleen source control en hier zien we ook de verschillen. Eén van de dingen die een tijdje terug zijn geintroduceerd in GitHub zijn de CI/CD mogelijkheden in GitHub Actions. Van oudsher had Microsoft hier al veel features voor in Azure DevOps en zijn voorganger TFS. We zien hier dat GitHub meer naar Azure DevOps aan het toebewegen is. Dus reden om eens kijken naar de verschillen en eventuele overlap van mogelijkheden.

Build pipelines Classic vs Modern

blank
Zoals eerder aangegeven heeft Azure DevOps en zijn voorganger TFS al tijden mogelijkheden tot het opzetten van een CI/CD pipeline. Hier zijn grofweg 2 verschillende manieren. De inmiddels wat verouderde manier van de classic pipeline waar men een grafische interface de build en release pipeline in elkaar kan klikken.

blank
De grafische terugkoppeling is waardevol, maar er is er één groot nadeel. Deze pipeline leeft alleen in Azure DevOps en bestaat niet uit code welke in de Git repo zit. Hierdoor is het lastig om bepaalde veranderingen in de build/release pipeline af te stemmen met de code. Zo kun bijvoorbeeld een extra project toevoegen welke je apart wilt compileren binnen dezelfde build/release pipeline. Dit doe in een feature branch in je git repo. Hiervoor moet je de pipeline aanpassen en tegelijkertijd ook je code. Maar misschien is je code nog niet klaar en wil in de tussentijd ook andere branches kunnen bouwen. Dan ontstaat er een probleem.

blank
De oplossing voor dit soort problemen is het opzetten van een build/release pipeline in code en deze op te nemen in je git repo. Dan is de koppeling tussen je code en pipeline altijd 1 op 1. Dit is in Azure DevOps al enige tijd geleden introduceert met de zogenaamde moderne yaml pipelines. GitHub actions gebruikt al direct vanaf de start yaml als enige manier van opzetten van pipelines.  Voor dit vergelijk gaan we dan ook alleen kijken naar de yaml pipelines en laten de classic pipelines buiten beschouwing.

Overeenkomsten & Verschillen

Yaml scripts

Op het eerste gezicht lijken de yaml scripts van Azure DevOps pipelines en GitHub actions sterk op elkaar. Niet zo vreemd aangezien ze van dezelfde organisatie afkomstig zijn. Zo worden beide pipelines gestart middels triggers. Ze kunnen beide reageren op push events op verschillende branches en kunnen beide onderscheid maken op tags. Naast deze triggers kan men GitHub Actions pipelines starten op basis van GitHub events, dit zijn er legio en kan men b.v. een pipeline starten op basis een issue-comment – created of deleted event. Dit is niet mogelijk in Azure DevOps.  Beide oplossingen bestaan uit 1 of meerdere jobs, met daarin weer steps en tasks.  De notatie verschilt wel iets maar er zijn meer overeenkomsten dan verschillen. Er is ook documentatie beschikbaar om te migreren: https://docs.github.com/en/actions/learn-github-actions/migrating-from-azure-pipelines-to-github-actions

Agents

Naast de overeenkomsten in de syntax van yaml zijn de functionaliteit ook grotendeels overeenkomstig. Zo bieden beide platformen de mogelijkheid tot het runnen van script in een gehoste omgeving en met verschillende operating systemen zoals Linux, Windows  of MacOs. Daarnaast ook mogelijkheden om je eigen agents hiervoor te gebruiken. Het is wel zo dat Azure DevOps een eigen agents kan selecteren op basis van capabilities. Deze capabilities zijn name-value pairs die beschrijven wat een bepaalde agent kan. Zo staat daar b.v. het type van operating system en versie van de geïnstalleerde software in. Builds in Azure DevOps kunnen op basis van deze capabilities een keuze maken van beschikbare agents. In GitHub actions gaat dit op basis van labels die men als gebruiker zelf moet administreren. Dit is iets meer werk maar uiteindelijk kun je hetzelfde bereiken.

Security tools integratie

GitHub Actions heeft standaard features die een security scan op je code uitvoeren met een SAST oplossing (static application security testing). Dit is een native feature van GitHub actions en je hoeft hier geen extra  3th party tooling voor te gebruiken.  Dit kan ook in Azure DevOps maar dan moet men wel altijd gebruik maken van 3th party tooling. Daarnaast heeft GitHub Actions directe integratie met Dependabot zodat er geautomatiseerd pull requests worden aangemaakt indien een 3th party library een update heeft. Dit zijn belangrijke features voor je security beleid. Dit kan ook in Azure DevOps maar hier moet men wel zelf actie voor ondernemen.

Beschikbare standaard tasks

In Azure DevOps en GitHub Actions zijn veel verschillende standaard taken om de resultaten van de build te releasen naar veel verschillende omgevingen. Je kunt hier denken aan aan releases naar AWS, Azure, Google Cloud e.d. GitHub Actions hebben inmiddels bijna 9000 taken in marketplace staan, dit is aanzienlijk meer dan Azure DevOps (+/- 1200). Maar de belangrijkste en meest gebruikte taken zijn bij beide te vinden en zou in 99% van de gevallen voldoende moeten zijn.

Environments

Azure DevOps kent een tijdje begrippen als Environments, Stages & Templates. Hiermee is het mogelijk om per omgeving (Development, Test, Acceptance, Production) bepaalde approvals te zetten.  Je kunt hiermee bijvoorbeeld aangeven dat een acceptatie tester de release moet goedkeuren voor een release naar productie. Dit was iets was GitHub actions nog niet ondersteunde maar recent zit een soortgelijke functionaliteit ook in GitHub actions. (zie : https://docs.github.com/en/actions/reference/environments ) Deze functionaliteit is wel alleen beschikbaar in GitHub Enterprise.

Agile workflow management

Naast de build en release features biedt Azure DevOps meer functionaliteiten voor het begeleiden van je agile workflow. Denk hier aan mogelijkheden voor het maken van boards, backlogs, sprints e.d. Dit is functionaliteit die men niet in GitHub actions kan vinden maar waarvoor men dan afhankelijk is van andere tooling (b.v. Jira)

Conclusie

Beide zeer mooie en uitgebreide producten en er zijn meer overeenkomsten dan verschillen. Dus eigenlijk is keuze voor één van deze twee producten prima.  Mocht je keuze moeten maken dan is deze sterk afhankelijk van het ecosysteem waar je organisatie reeds gebruik van maakt. Zit je al in de Microsoft hoek of  wil je één product waar je hele ontwikkelproces in kunt beheren dan ligt de keuze voor Azure DevOps voor de hand. Ben je hier nog vrij om keuzes te maken of gebruik je b.v. Jira voor management van je agile workflow dan ligt dit minder voor de hand. De features die GitHub actions biedt voor integratie met security scan tooling is daar wel een sterk argument. Daarnaast lijkt GitHub actions meer momentum te hebben dan Azure DevOps en de nieuwe features volgen elkaar snel op. Dus in deze geen foute keuzes hooguit een keuze die beter aansluit bij de huidige werkwijze.

blank

Auteur: Patrick Bes © 2021 Bergler Competence Center

Lees ook…

blank

.NET 6 Update

8 december 2021
berglerGitHub actions vs Azure DevOps Pipelines
Lees meer

Hoe migreer je naar .NET 5

Hoe migreer je naar .NET 5

Met de komst van .NET5 en de aankondiging van Microsoft te gaan stoppen met .NET Framework dient zich de vraag aan hoe bestaande .NET Framework applicaties kunnen worden gemigreerd naar het nieuwe .NET5. Dit blog probeert de migratiemogelijkheden die Microsoft biedt te behandelen en de mogelijke problemen en/of valkuilen te beschrijven die daarbij kunnen optreden.

Een stukje historie (en toekomst)

Het werd al een tijd verwacht maar nu is het dan zover: er komt geen nieuwe versie meer van het .NET Framework. De laatste versie van het .NET Framework is versie 4.8. Uiteraard zullen er voorlopig nog broodnodige patches uitgebracht worden, maar voor nieuwe features moet je echt overstappen naar het nieuwe .NET(5) voorheen bekend als .NET Core.

Onderstaand plaatje toont de historie in de ontwikkeling van de diverse framework versies die door Microsoft op de markt zijn gebracht:

blank

Wanneer we inzoomen op het nieuwe .NET dan zien we dat Microsoft de volgende planning voor de releases uitgeeft:

blank

Zoals is te zien zal er ieder jaar een nieuwe versie van .NET worden uitgebracht waarbij het iedere twee jaar zal gaan om een zogenaamde LTS (Long Term Support) versie. Deze LTS versies zullen door Microsoft voor een periode van drie jaar ondersteund worden. Daarnaast zal er ieder jaar een major versie worden uitgebracht. Voor deze versies zal de ondersteuningsperiode 15 maanden zijn.

Migratiepaden

Welke mogelijke paden voor een migratie kunnen worden gevolgd? In principe wordt geadviseerd “zo klein mogelijke” stappen te nemen voor een migratie. Overigens wordt wél aangeraden om te starten met de applicatie naar de meest recente .NET Framework versie te brengen, zijnde .NET Framework 4.8.

Onderstaand plaatje geeft dan de mogelijke migratiepaden weer:

blank

Migratietools

Om je te helpen bij het migreren van applicaties van het oude .NET Framework naar het nieuwe .NET5 heb je een aantal tools tot je beschikking. Deze zijn onder te verdelen in twee categorieën:

  1. Portability analyzers

Dit zijn tools die een scan/analyse uitvoeren op je bestaande applicatie en die zijn bedoeld om inzicht te krijgen in … Een voorbeeld van zo’n analyzer is de API Portability Analyzer tool (API-port) van Microsoft. Deze tool geeft inzicht in de ondersteuning en de mate van integratie van de .NET API’s die worden gebruikt door een applicatie op verschillende .NET platformen. Denk hierbij vooral aan de 3rd party libraries die worden gebruikt.

API-port is als plug-in te installeren in Visual Studio wat het mogelijk maakt om vanuit de IDE een compatibiliteitsrapport voor de solution te genereren.

  1. Porting applicaties

Deze applicaties gaan naast de analyse ook daadwerkelijk een poging doen de applicatie te migreren naar een nieuwere versie .NET. Voorbeelden hiervan zijn het open source project try-convert (een eenvoudige CLI tool die helpt bij het migreren van .NET Framework-projecten naar .NET Core) en .NET Upgrade Assistent (waarvan try-convert een subonderdeel is)

Een diepere kijk in de tools

Zoals aangegeven onderscheiden we twee categorieën migratietools: de portability analyzers en de porting applicaties.

API-port

Naast dat API-port als CLI-tool gebruikt kan worden is deze analyzer beschikbaar als plug-in in Visual Studio. Hierdoor komt er bij selecteren van de solution een extra optie ter beschikking: “Analyze Solution Portability”

blank

Zoals gezegd zal de analyzer geen werkelijke conversie gaan proberen uit te voeren maar genereert  het een rapport met als inhoud de compatibiliteit van de diverse projecten in de solution voor diverse targets waarnaar de conversie uitgevoerd kan worden. Tevens is in detail te zien welke onderdelen van de solution niet ondersteund worden bij een eventuele migratie. Daarnaast wordt in het overzicht ook aangegeven welke 3rd party libraries niet worden herkend en/of ondersteund:

blank

API-port is met name geschikt om vooraf een beeld te krijgen tegen wat voor problemen men aan gaat lopen bij een migratie naar .NET5.

Try-convert

Net als de andere tools/analyzers wordt deze tool geïnstalleerd via .NET Core. Het is van de twee hier besproken migratietools de eenvoudige variant. Try-convert werkt via de CLI waarbij een aantal opties kunnen worden meegegeven zoals het path naar de te migreren solution/workspace en de optie om al dan niet een back-up te maken van de solution alvorens de migratie wordt uitgevoerd. In de praktijk is het echter aan te bevelen om een aparte migratie-branch te maken in de te migreren  repository zodat op eenvoudige wijze is na te gaan wat voor wijzigingen de migratietool uiteindelijk heeft doorgevoerd.

.NET Upgrade Assistent

De meest uitgebreide en door Microsoft aanbevolen migratietool is .NET Upgrade Assistent. Deze tool is nog in ontwikkeling en er worden op zeer regelmatige basis updates van uitgegeven. Ook deze tool heeft een CLI maar het grote verschil met het hiervoor genoemde try-convert is dat de gebruiker hier stapsgewijs door een aantal fases geleid wordt. Daarnaast doet de tool met name in solutions met meerdere projecten een aantal voorstellen zoals bijvoorbeeld de volgorde waarin de verschillende projecten zouden moeten worden gemigreerd (met het oog op afhankelijkheden tussen de projecten onderling). Iedere fase in het migratieproces zal worden voorzien van de nodige logging zodat de gebruiker steeds goed zicht blijft houden op mogelijke aandachtspunten en daarnaast zelf alternatieve keuzes kan maken.

De .NET Upgrade Assistent zal zo stap voor stap ieder project in de solution afwerken en zal daarbij ook de migratie/upgrade van bijvoorbeeld de NuGet packages voor zijn rekening nemen. Try-convert doet iets soortgelijks maar het voordeel wat de .NET Upgrade Assistent biedt is dat deze in zijn beslissing het target framework meeneemt. Hier schuilt echter wel een mogelijk gevaar in: omdat de .NET Upgrade Assistent zal proberen de NuGet packages te upgraden naar de meest recente versies kan het gebeuren dat je tegen nogal wat “breaking changes” aanloopt. Hier wordt door de migratietool verder geen rekening mee gehouden. De gebruiker zal dit later zelf moeten oplossen aan de hand van build errors die optreden.

Mogelijke pijnpunten/uitdagingen bij migratie

Het zal duidelijk zijn dat bij met name de meer uitgebreide solution met meerdere projecten een aantal problemen c.q. uitdagingen kunnen optreden. Het gaat dan met name om het soort project.

In het algemeen zullen er weinig problemen te verwachten zijn bij de backend libraries. Denk hierbij aan libraries zoals een datalibrary of een project wat de businesslogica bevat. Ook API’s (MVC projecten zonder Views 😉) vallen onder de projecten waarbij weinig problemen te verwachten zijn.

Iets anders wordt het als we gaan kijken naar front-end projecten zoals bijvoorbeeld een Winforms applicatie of een MVC project. Deze projecten raken de UI waar vooral met betrekking tot Razor views etc. problemen te verwachten zijn op het gebied jQuery en/of Bootstrap. Het zal daarom een afweging zijn wat met deze projecten te doen: migreren en daarna handmatig de fouten oplossen of een UI opnieuw ontwikkelen op basis van een nieuwe technologie zoals bijvoorbeeld Blazor.

Een ander mogelijk pijnpunt is de migratie van Entity Framework 6 naar EF Core. Met name de EDMX kan hier voor grote problemen zorgen. Daarnaast is het zo dat Microsoft EF6 compatible heeft gemaakt met .netstandard 2.1 waardoor er een keuze moet worden gemaakt: kiest met voor .netstandard 2.1 dan vervalt de compatibiliteit met .NET Framework 4.8. Kiest men daarentegen voor .NET Framework 4.8 dan is het niet compatible met .NET Core/.NET5. Dit is met name een lastige keuze als met kiest voor een geleidelijke overgang (waarbij men kiest voor het migreren van een aantal projecten per fase) en niet voor een “big bang” migratie.

Daarnaast is het zo dat een aantal technologieën gewoonweg niet meer beschikbaar zijn in .NET5:

  • Windows Communication Foundation (WCF)
  • Web Forms
  • Windows Workflow Foundation

Tot slot is het zo dat zich problemen kunnen voordoen met de al eerder genoemde 3rd party NuGet packages. Als stelregel kan hierbij gehanteerd worden dat wanneer een NuGet package compatible is met .netstandard dat er dan weinig problemen te verwachten zijn. Daarnaast zal het zo zijn dat met name de grotere vaak gebruikte packages al snel een .NET5 compatible versie zullen uitbrengen, vaak nog eerder dan dat Microsoft zo ver is.

Conclusie

Met de aankondiging van Microsoft te gaan stoppen met .NET Framework is het onvermijdelijk geworden na te gaan denken over een eventuele migratie naar een toekomstbestendige .NET versie zoals bijvoorbeeld .NET5. In dit blog heb ik willen aangeven wat voor mogelijkheden daar op dit moment voor op de markt zijn. Toegegeven dat het zeker nog niet de ultieme tools zijn en dat een gedegen onderzoek nodig is om uiteindelijk tot de juiste keuze te komen: migreren of greenfield ontwikkeling. Aan de andere kant: de mogelijkheden zijn er en de ontwikkelingen in migratietools volgen elkaar snel op. Aan u de keuze 😊.

Auteur: Pieter Baart © 2021 Bergler Competence Center

Lees ook…

blank

.NET 6 Update

8 december 2021
berglerHoe migreer je naar .NET 5
Lees meer

C# 9.0 nieuwe features – Record types (4-4)

C# 9.0 nieuwe features – Record types (4-4)

Met de komst van C# versie 9.0 zijn er heel veel waardevolle toevoegingen gedaan aan de programmeertaal en in deze Blog serie zullen we inzoomen op een aantal belangrijke nieuwe features. Al eerder behandeld in deze serie is deel 3 “Top-level statements”, we gaan nu verder met het laatste deel: “Record types”.

Om C# 9.0 te kunnen gebruiken dien je eerst de .NET 5 runtime of SDK te installeren. Ga hiervoor naar https://dotnet.microsoft.com/download. Na installatie zal C# 9.0 de standaard C# versie zijn bij elk nieuw project gebaseerd op .NET 5.

Waarom?

In deel 2 van deze serie is al gewezen op init-only setters. Op een eenvoudige manier kun je daarmee aangeven dat properties als immutable behandeld moeten worden.

Met het nieuwe keyword record krijg je als programmeur de mogelijkheid om snel en overzichtelijk een complete class immutable te maken. Je kunt dit record dan instantiëren, waarbij de data initieel wordt gezet en daarna niet meer te wijzigen is.

Dit levert je een aantal voordelen op.

Denk aan toepassing van deze record types in een multi-threaded applicatie. Omdat het object immutable is, met andere woorden niet kan worden benaderd om wijzigingen door te voeren, kan er geen race condition optreden waarbij thread 1 gegevens leest terwijl thread 2 gegevens schrijft. Je code kan worden vereenvoudigd zonder risico op deadlocks of nog erger, berekeningen met een onverwachte uitkomst.

Een ander groot voordeel van een immutable record is dat je de betrouwbaarheid van je unittesten kunt vergroten. Stel je een applicatie voor waarbij een “ouderwetse” DTO-class door diverse methodes in een keten als parameter wordt gebruikt. Wanneer de inhoud van deze class mutable is, zul je bij het schrijven van een test op één van die methodes uit moeten zoeken of er methodes bestaan die gegevens in jouw DTO kunnen wijzigen. Dit kan namelijk impact hebben op het aantal scenario’s dat je zult moeten testen.
Een immutable record maakt het onmogelijk dat gegevens worden gewijzigd, waardoor je veilig deze uitzoekklus over kunt slaan.

Hoe?

Declareren en instantiëren

C# 9.0 biedt twee mogelijkheden om een record te declareren. Het meest eenvoudig is de volgende manier, waarbij je positional arguments toepast:

blank

Deze methode is intuïtief en overzichtelijk. De C# compiler voegt boilerplate-code zoals een constructor met parameters en een deconstructor toe zodat je direct een Object van het type Car kunt aanmaken en gebruik kan maken van enkele handige uitbreidingen. Uit de intellisense blijkt dat de aangegeven property LengthInCm gebruikt maakt van init als setter en dus inderdaad immutabel is.
Er is géén parameterloze constructor aanwezig, je bent dus verplicht om de parameters via de constructor te vertrekken.

blank

Veel controle over Racecar heb je natuurlijk niet, nuttige zaken als het inbouwen van validatie of het aangeven van een default value is zo niet mogelijk. Daarom is ook de meer klassieke ogende methode beschikbaar waardoor je bijvoorbeeld berekende properties of methodes kunt toevoegen.

blank

Vergelijken van records

Een mooie eigenschap van een record is dat het zuiver gezien een reference type is, maar dat het zich gedraagt als een value type. Dit heeft een belangrijk effect op het vergelijken van instances van records.
Bij de vergelijking wordt namelijk – net als bij een echt value type – niet gekeken of de instances naar hetzelfde object verwijzen, maar of het type en de inhoud van de record instanties overeenkomen.

De bijgaande test brengt dit mooi in beeld.
Er worden 2 aparte instanties van PersonRecord aangemaakt en vervolgens vergeleken via de ==-operator en de AreEqual methode. Met classes zijn we gewend dat dit verschillende objecten zijn en daarom verwachten we dat de test faalt. Maar omdat records zich gedragen als value types slaagt deze test.

blank

Muteren van een record

Hoewel een record immutable is, is het wel mogelijk een kopie te maken van een instantie en daarbij kleine wijzigingen aan te brengen met behulp van het keyword with op de volgende manier:

blank

Verder?

Bij het record type krijg je nog een aantal andere methodes tot je beschikking.

ToString()

Deze methode levert automatisch de inhoud van het type en alle publieke properties.

blank

Deconstructor()

De deconstructor geeft je de mogelijkheid om op de volgende manier de gegevens uit je record te verzamelen.

blank

Lees ook…

blank

.NET 6 Update

8 december 2021
berglerC# 9.0 nieuwe features – Record types (4-4)
Lees meer

C# 9.0 nieuwe features – Top-level Statements (3-4)

C# 9.0 nieuwe features – Top-level Statements (3-4)

Met de komst van C# versie 9.0 zijn er heel veel waardevolle toevoegingen gedaan aan de programmeertaal. In deze Blog serie zullen we inzoomen op een aantal belangrijke nieuwe features. We gaan nu verder met “Top-level Statements”.

Om C# 9.0 te kunnen gebruiken dien je eerst de .NET 5 runtime of SDK te installeren. Ga hiervoor naar https://dotnet.microsoft.com/download. Na installatie zal C# 9.0 de standaard C# versie zijn bij elk nieuw project gebaseerd op .NET 5.

Waarom?

Elke .NET assembly die uitvoerbaar is, dient een entrypoint te hebben anders heeft de applicatie geen startpunt. Dit startpunt is de welbekende Main methode. Zelfs een simpele console applicatie heeft een Main methode nodig om te kunnen functioneren.

Het requirement van zo’n Main methode maakt dat C# een ietwat minder toegankelijke programmeertaal is voor beginners. Wanneer beginners de volgende code onder ogen krijgen, kan dat best intimiderend overkomen:

blank

Het enige wat bovenstaande code moet doen is de tekst “Hello World!” tonen op het scherm, maar voordat de applicatie zover is moet er dus eerst heel veel “ceremonie” plaatsvinden:

  • using
  • namespace
  • class
  • Main methode definitie (het startpunt).

De nieuwe C# 9.0 feature “Top-level Statements” maakt deze ceremonie overbodig en dus hopelijk ook wat meer toegankelijk voor beginners!

Hoe?

De volgende code is vanaf C# 9.0 uitvoerbaar geworden op zichzelf, zonder extra code:

blank

Zoals je kan zien is deze code van alle “ceremonie” ontdaan, dus geen class definitie en geen Main methode definitie meer. Je kunt je vast voorstellen dat dit veel beter te begrijpen is voor een beginner dan de eerdere voorbeeldcode.

using statements zijn gewoon nog te gebruiken om te voorkomen dat je steeds de fully qualified type namen moet specificeren:

blank

Verder?

Ondanks dat er geen Main methode is gedefinieerd, ben je nog steeds in staat om de args parameter te gebruiken om de command-line parameters uit te kunnen lezen:

blank

Wanneer de Top-level Statements het await keyword bevatten, zal de C# compiler onderwater automatisch een async entrypoint maken:

blank

De mogelijkheid bestaat nog steeds om een int waarde terug te geven, welke aangeeft wat de zogenaamde exitcode is van je applicatie.

blank

Maar?

Bij het gebruik maken van Top Level Statements zijn er wel een tweetal beperkingen waar je rekening mee moet houden.

  • Top Level Statements kunnen slechts in één bestand onder het project aanwezig zijn.
  • In principe geen nieuwe regel, maar wanneer er Top Level Statements aanwezig zijn in een project, mogen er geen andere entrypoints bestaan.

Lees ook…

blank

.NET 6 Update

8 december 2021
berglerC# 9.0 nieuwe features – Top-level Statements (3-4)
Lees meer

C# 9.0 nieuwe features – Pattern Matching (2-4)

C# 9.0 nieuwe features – Pattern Matching (2-4)

Met de komst van C# versie 9.0 zijn er heel veel waardevolle toevoegingen gedaan aan de programmeertaal. In deze Blog serie zullen we inzoomen op een aantal belangrijke nieuwe features. Al eerder behandeld in deze serie is deel 1 “Init Only Setters”, we gaan nu verder met “Pattern Matching”.

Om C# 9.0 te kunnen gebruiken dien je eerst de .NET 5 runtime of SDK te installeren. Ga hiervoor naar https://dotnet.microsoft.com/download. Na installatie zal C# 9.0 de standaard C# versie zijn bij elk nieuw project gebaseerd op .NET 5.

Waarom?

De syntax van ontwikkeltalen is al sinds jaren het onderwerp van discussies tussen ontwikkelaars. Leesbaarheid, efficiëntie en flexibiliteit is slechts een selectie van de tientallen argumenten die jouw mening vormen over het al dan niet geslaagd zijn van een syntax.
Martin Fowler geeft een – zoals we van hem gewend zijn – zeer zinvolle bijdrage in deze discussie met zijn bekende uitspraak:

Any fool can write code that a computer can understand.
Good programmers write code that humans can understand.

Met die uitspraak in het achterhoofd heeft Microsoft een aantal vereenvoudigingen aan de syntax van if en switch doorgevoerd.

Deze onderdelen worden door ons veel gebruikt om complexe condities uit te werken.
Sinds C# 7.0 helpt Pattern Matching ons om de code die we opleveren beter leesbaar en dus minder foutgevoelig te maken. Ook in C# 9.0 zijn er weer enkele nieuwe mogelijkheden toegevoegd.

Hoe?

Logical pattern

Om meer complexe condities goed leesbaar te houden is het logical pattern toegevoegd aan C# 9.0. Hiermee kunnen we gebruik maken van and, or en not in onze statements, en het herhalen van de parameter waarmee vergeleken moet worden kan achterwege worden gelaten.

blank

Dit is een krachtig mechanisme dat kan worden gebruikt in if-statements zoals in bijgaand voorbeeld. De volgorde waarin de controles worden uitgevoerd is volstrekt logisch, maar in sommige gevallen zul je toch aan deze volgorde moeten wennen. Vergeet dus niet om unittests toe te voegen met voldoende testsets om er zeker van te zijn dat je functie in alle gevallen het gewenste gedrag vertoont.

Het Logical pattern komt zelfs beter tot zijn recht wanneer dit wordt gecombineerd in switch expressions, zoals we hierna zullen zien bij het Relational Pattern.

Relational pattern

In C# 8.0 zijn switch expressions toegevoegd. Hiermee was het mogelijk om direct een returnwaarde als resultaat van een aantal voorwaarden te definiëren. De syntax bevatte veel onnodige herhalingen en was daarom nog niet in alle gevallen even leesbaar, zoals het onderstaande voorbeeld illustreert.

blank

In C# 9.0 kunnen we de bovenstaande syntax verder verfijnen door gebruik te maken van het Relational pattern. Hierdoor kunnen we rechtstreeks gebruik maken van relational operators zoals < of >=. Toepassing leidt tot het volgende resultaat:

blank

In deze syntax ligt de nadruk op de logica en het resultaat, en veel minder op het achterhalen van de juiste objecten.
We zien ook dat het gebruik van het Logical Pattern ook daadwerkelijk de leesbaarheid van de code vergroot: in één oogopslag is nu duidelijk dat er een selectie gemaakt wordt voor iemand tussen de 12 en 60.

Dit voorbeeld leent zich daarnaast om de switch expression, die in C# 8.0 al is geïntroduceerd nogmaals onder de aandacht te brengen.
Bij de switch expression staat de variabele vóór het switch keyword, de switch-onderdelen case en : zijn vervangen door de bekende =>. Als laatste is de body is geen statement meer, maar een expressie.
De expression is in het onderstaand voorbeeld uitgewerkt. Hierbij zien we dat we ons niet hoeven te beperken tot property checking, ook Type checking behoort tot de mogelijkheden.

blank

Type pattern

Met het type pattern kun je met een vereenvoudigde syntax conditie checks op type en properties uitvoeren . De nieuwe schrijfwijze in C# 9.0 is compact en overzichtelijk, zoals in onderstaand voorbeeld wordt getoond.

blank

Wanneer de parameter person niet van het type PersonRecord is ontstaat er geen exception maar wordt de evaluatie van het if-statement afgebroken. In het andere geval (person is van het type PersonRecord) wordt het resultaat bepaald op basis van de property Age van person.

Wees je er in dit voorbeeld goed van bewust dat deze code géén NullReferenceException oplevert wanneer de parameter person null is.

Verder?

Veel van onze logica in onze applicaties is vormgegeven door implementaties van if-then-else en switch statements. Na verloop van tijd kunnen deze constructies steeds complexer en onoverzichtelijker worden.
Met de nieuwe mogelijkheden kunnen we deze bestaande code relatief eenvoudig refactoren naar beter leesbare en dus beter onderhoudbare code.

Maar natuurlijk geldt zoals altijd: bedenk of deze complexe constructies gezien kunnen worden als code smell voor het overtreden van belangrijke SOLID principes, zoals het Open/Closed of Single Responsibility principe.
Overweeg in die gevallen vooral ook de toepassing van nette OO oplossingen, zoals het inzetten van encapsulation en de vele design patterns die beschikbaar zijn.

Lees ook…

blank

.NET 6 Update

8 december 2021
berglerC# 9.0 nieuwe features – Pattern Matching (2-4)
Lees meer