Webblog

Jaarprogramma 2021

Jaarprogramma 2021

Jaarprogramma 2021

We kijken terug op een bewogen 2020. Toen we het competence center programma voor afgelopen jaar samenstelden gingen we uit van gezellige sessies op kantoor en in Houten. Hoe anders is de praktijk gelopen. Gelukkig hebben we afgelopen jaar gezien dat we ook online hele toffe sessies konden organiseren. De kennis sessies in Houten werden online sessies via YouTube, en met veel succes want aan het einde van het jaar hadden we maar liefst 450 aanmeldingen voor onze sessies over Docker en Kubernetes. Dat had in de ruimte in Houten nooit gepast. Ook de interne opleidingen kregen een ander karakter waarbij we op het ene scherm de Team sessie actief hadden om op het andere scherm de opdrachten uit te voeren. Iets minder persoonlijk, maar zeker werkzaam.

Zoals elk jaar hebben we samen met het team van Lead developers gekeken naar de thema’s die we dit komende jaar willen behandelen. Daarnaast is er nieuws op het vlak van ons opleidingsprogramma: komend jaar faciliteren we voor alle medewerkers een Pluralsight abonnement waar we onze doelen uit het opleidingsprogramma in opnemen. Je kunt dan denken aan zaken als SOLID development, automatisch testen, maar ook het opkrikken van algemene C# kennis. We verwachten dat we hiermee een hele mooie toevoeging doen aan het ondersteunen van onze software developers. Meer informatie volgt in de loop van het eerste kwartaal. Dan nu de thema’s voor het Competence Center programma van 2021:

Migratiepaden naar .NET 5

Met de komst van .NET 5 beweegt Microsoft voor het eerst in de geschiedenis definitief weg van het fullstack .NET framework. De nieuwe versie is gebaseerd op .NET Core. Wat betekent dit voor bestaande producten en welke strategieën zijn er om te migreren? Op deze vragen gaan we samen in.

Azure DevOps

We hebben de afgelopen jaren al best wat aandacht besteed aan Azure DevOps. Tegelijk gaan de ontwikkelingen van dit platform erg hard, en hebben we gemerkt dat er bij collega’s behoefte is om eens stil te staan bij zaken waar je in het dagelijks werk misschien niet altijd tegenaan loopt. Enerzijds nog eens wat dieper in Git duiken, maar vooral ook kijken naar de CI/CD pipelines en planningen.

Een introductie in gRPC

Een van de technologieën die is geïntegreerd in .NET Core is gRPC. Omdat dit protocol een prima alternatief is voor de WCF services die niet meer beschikbaar zijn in .NET Core, is er alle reden om deze technologie te bestuderen.

Een introductie in Blazor

Met de komst van Blazor introduceert Microsoft haar visie op single page front-end development op basis van C#. Hierbij wordt gebruik gemaakt van web assembly, een standaard van W3C die door alle grote browsers ondersteund wordt. We zullen zeker stilstaan bij de roerige wereld van de front-end development en welke strategie hier het beste bij past. Duidelijk is in ieder geval dat er een risico is dat in de front-end weer monolitische applicaties ontstaan die in de toekomst lastig te onderhouden zijn. Hoe verhoudt Blazor zich in dit speelveld en hoe kun je ook in de front-end met deze technologie kleine micro clients maken die samen toch als één applicatie voelen.

Bergler hackaton

Juist omdat we elkaar het laatste jaar zo weinig hebben gezien, is het idee ontstaan om komend jaar eens iets nieuws te proberen. Op zaterdag 29 mei organiseren we een hackaton waar onze collega’s op een leuke manier nieuwe technieken kunnen uitproberen, gezellig samen kunnen komen en voor de eeuwige developer roem mogen strijden. Ik hoop dat dit een groot succes mag worden en dat we nog vele soortgelijke events mogen organiseren.

… En nog veel meer

Los van de bovenstaande hoofdthema’s worden er nog vele kleinere sessies georganiseerd. Voor het volledig programma verwijs ik graag naar onze flyer.

Met vriendelijke groet,
Menno Jongerius

berglerJaarprogramma 2021
Lees meer

Authenticatie in ASP .NET Core 3.1

Authenticatie in ASP .NET Core 3.1

Authenticatie in ASP .NET Core 3.1

Authenticatie en autorisatie worden vaak in één adem genoemd en zijn in zekere zin ook onlosmakelijk aan elkaar verbonden. Toch hebben ze ieder hun specifieke verantwoordelijkheid. Met behulp van authenticatie kunnen gebruikers van een webapplicatie zich identificeren om toegang te krijgen tot de applicatie. Met autorisatie kunnen ze toegang krijgen tot specifieke functies en functionaliteit van een webapplicatie.

ASP.NET Core Identity is een zogenaamd membership system dat gebruikt wordt bij het bouwen van ASP.NET Core-webapplicaties, inclusief lidmaatschap, inloggen en gebruikersgegevens. ASP.NET Core Identity maakt het mogelijk om inlogfuncties toe te voegen aan een webapplicatie en maakt het eenvoudig om gegevens over de ingelogde gebruiker toe te passen.

ASP.NET Core Identity maakt authenticatie voor één enkele applicatie mogelijk. Het heeft zoals aangegeven redelijk wat features “out-of-the-box”. Wanneer je authenticatie op een meer gecentraliseerde en geïsoleerde manier wilt gebruiken voor meerdere client applicaties is het beter te kijken naar een token service met OAuth 2.0 and OpenID Connect implementatie zoals IdentityServer.

In dit artikel wordt één van de manieren beschreven waarop binnen ASP.NET Core 3.1 authenticatie kan worden geregeld met behulp van Identity Core. Het uitgebreidere IdentityServer behoort niet tot de scope van dit artikel.

De volgende items zullen aan de orde komen:

  • Opzetten ASP.NET Core Identity framework (EF Core 3.1 & migrations)
  • Registratie van nieuwe gebruikers
  • In-/uitloggen van gebruikers
  • Account Lockout mechanisme
  • Custom validatie naast de al in Identity aanwezige default validatie

Opzetten ASP.NET Core Identity framework

Er bestaan in Visual Studio diverse templates die kunnen worden gebruikt bij het opzetten van een Identity Core framework. In alle gevallen is de basis een context die is afgeleid van IdentityDbContext. Dit is de base class voor de EF Core database context die gebruikt wordt voor Identity en waaraan het User objecttype wordt meegegeven:

In de OnModelCreating methode kan een verdere configuratie van de objecten plaatsvinden zoals het verplicht maken van velden of het initiëren van de tabellen met bepaalde default data.

Daarnaast is in bovenstaande code snippet een DbSet aangemaakt die gebruikt gaat worden als IdentityUser object (en die is afgeleid van de IdentityUser base class).

Het registreren van de Identity DB context service en de setup voor het gebruik van (in dit geval) SQL Server gebeurt in de ConfigureServices methode van startup.cs:

Na het uitvoeren van de diverse EF Core migration commando’s is er in SQL Server een Identity database aangemaakt met daarin een aantal standaard Identity tabellen (welke allemaal de prefix ‘AspNet’ hebben):

In de volgende paragrafen zullen de betekenis en functie van diverse velden uit m.n. de AspNetUsers tabel verder aan de orde komen. Voor dit artikel zijn de volgende tabellen en hun onderlinge relatie van belang:

Om de Identity Core functionaliteit beschikbaar te maken in de applicatie zijn tot slot twee zaken nodig in de startup.cs:

  1. Het registreren van de services voor het ASP.NET Core Identity framework (in de ConfigureServices methode):
  1. Het toevoegen van de authenticatie middleware (in de Configure methode):

Registratie van nieuwe gebruikers

Om nieuwe Identity Users te registreren wordt gebruik gemaakt van de UserManager class. Deze class bevindt zich in de namespace Microsoft.AspNetCore.Identity en wordt d.m.v. dependecy injection in een controller geïnjecteerd:

Om een nieuwe gebruiker te registreren is het noodzakelijk naast een gebruikersnaam en/of emailadres ook een wachtwoord op te geven. Met behulp van deze gegevens kan een gebruiker door de applicatie geauthentiseerd worden.

Er kan m.b.t. authenticatie gekozen worden voor de combinatie gebruikersnaam/wachtwoord of emailadres/wachtwoord. Wanneer voor de laatste optie wordt gekozen is het aan te raden tijdens het registreren van de services voor het ASP.NET Core Identity framework de optie mee te geven dat gevalideerd moet worden dat het emailadres van de nieuw toe te voegen Identity User uniek is (User.RequireUniqueEmail = true).

Voor de eerste optie geldt by design dat het Identity framework valideert dat de gebruikersnaam van de nieuw toe te voegen Identity User uniek is.

Registratie gebeurt vervolgens in een POST action in de controller:

De return value van deze (async) functie is van het type IdentityResult en bevat een boolean flag Succeeded die aangeeft of de actie geslaagd is of niet. Indien de actie niet succesvol was bevat de property Errors de fout(en) die is/zijn opgetreden bij de CreateAsync actie.

Het wachtwoord wordt (indien de operatie succesvol was) volgens een hashing algoritme encrypted opgeslagen in de database. Daarnaast worden enkele velden automatisch gevuld zoals het NormalizedUserName en het NormalizedEmail veld.

In-/uitloggen van gebruikers

Zoals aangegeven worden gebruikers geauthentiseerd op basis van een gebruikersnaam/wachtwoord of emailadres/wachtwoord combinatie. Het ASP.NET Core Identity framework biedt hiervoor twee mogelijkheden die ieder een verschillend doel dienen:

  1. CheckPasswordAsync

Deze methode hasht het opgegeven wachtwoord en vergelijkt het met de bestaande wachtwoordhash (zoals dat bijvoorbeeld is opgeslagen in de database)

  1. PasswordSignInAsync

Deze methode doet naast het controleren van het wachtwoord veel meer:

  • Controleert of inloggen is toegestaan. Als de gebruiker bijvoorbeeld een bevestigde e-mail moet hebben voordat hij zich mag aanmelden, retourneert de methode Failed
  • Roept UserManager.CheckPasswordAsync op om te controleren of het wachtwoord correct is. Wanneer een mislukte inlogpoging (wachtwoord is niet correct en de Lockout optie is enabled) het geconfigureerde maximum aantal mislukte aanmeldingspogingen overschrijdt wordt het account van de gebruiker geblokkeerd
  • Als de optie two-factor authentication is ingeschakeld voor de gebruiker, stelt deze methode de cookie in en retourneert TwoFactorRequired
  • Maakt een ClaimsPrincipal aan en persisteert dit via een cookie

 

Wanneer bevestigde e-mails en lockout geen vereiste zijn dan volstaat het om de CheckPasswordAsync methode uit de UserManager class te gebruiken. De SignInManager class is gekoppeld aan de cookie-authenticatie.

De volgende code snippet toont een manier om door middel van emailadres/wachtwoord combinatie authenticatie van een gebruiker te doen:

Analoog aan bovenstaande code snippet kan een gebruiker worden geauthentiseerd via zijn/haar gebruikersnaam.

In de volgende paragraaf wordt uitgebreider ingegaan op het Lockout mechanisme waarmee restricties kunnen worden gesteld aan het aantal pogingen dat een gebruiker mag doen om zichzelf bij een applicatie te authentiseren.

Account Lockout mechanisme

Het ASP.NET Core Identity framework biedt standaard een aantal belangrijke beveiligingsfuncties die het authenticatieproces van extra checks te voorzien. Denk hierbij aan:

  • Two-Factor Authentication (met behulp van SMS of email)
  • Account Lockout
  • Account Confirmation

Account Lockout is een belangrijke functie van het ASP.NET Core Identity framework. Het blokkeert het account van de gebruiker als deze een bepaald aantal keren een verkeerd wachtwoord invoert. Dit kan worden gespecificeerd door het maximale aantal mislukte pogingen (default 5x) en de lockout-tijd (default 5 minuten) te configureren in startup.cs:

De volgende code snippet toont het gebruik van het Lockout mechanisme: een mogelijkheid om het aantal inlogpogingen te beperken tot een opgegeven maximum. Zoals in de vorige paragraaf aangegeven is het hiervoor noodzakelijk gebruik te maken van de SignInManager.PasswordSignInAsync methode. Door de parameter lockoutOnFailure te activeren (true), wordt de lockout-functionaliteit ingeschakeld.

Custom validatie

Naast de standaard al aanwezige validatie in het ASP.NET Core Identity framework is het mogelijk eigen validatie toe te voegen zoals bijvoorbeeld het controleren op emaildomein of het uitsluiten van de mogelijkheid dat gebruikersnaam en wachtwoord identiek zijn. De volgende code snippets tonen enkele mogelijke custom validatie’s.

Het opnemen van de (extra) custom validatie’s gebeurt in startup.cs:

Auteur: Pieter Baart © 2020 Bergler Competence Center

berglerAuthenticatie in ASP .NET Core 3.1
Lees meer

Agile werken en denken in relatie tot ISO 27001 (of welke geformaliseerde certificering dan ook)

Agile werken en denken in relatie tot ISO 27001 (of welke geformaliseerde certificering dan ook)

Als Scrum Master ben ik onlangs betrokken geweest bij het verkrijgen van een ISO 27001 certificering voor mijn eindklant.
Het hebben van een ISO 27001 certificering als organisatie betekent dat het voldoet aan de privacy- en securityrichtlijnen die zijn gedocumenteerd door ISO: https://www.iso.org/standard/54534.html.

De certificering omvat richtlijnen voor de volgende gebieden:

  • Kantoor toegangsbeveiliging
  • Werkplek beveiliging
  • Infrastructuur (netwerk & telefonie) beveiliging
  • Applicatie en data beveiliging

De richtlijnen concentreren zich vooral op de werkprocessen en minder op (technische) oplossingen. Het verwijst echter wel naar andere standaarden. Bijvoorbeeld op het gebied van applicatie & data beveiliging, verwijst het naar OWASP richtlijnen.

De perceptie van iedere vorm van certificering is dat het bureaucratie introduceert die wordt vastgelegd in uitgebreide documentatie die (bijna) niemand leest. Ik hoop met dit artikel te beschrijven dat deze perceptie enige nuance verdient.

De nuance wil ik aanbrengen door middel van het doorlopen van het ‘Agile Manifesto’ (https://agilemanifesto.org/iso/nl/manifesto.html). Hoewel het Manifesto al twee decennia geleden is opgesteld, is tegenwoordig het voor bedrijven nog steeds het handvat voor softwareontwikkeling. Het Manifesto heeft 4 kernwaarden:

  • Mensen en hun onderlinge interactie boven processen en hulpmiddelen
  • Werkende software boven allesomvattende documentatie
  • Samenwerking met de klant boven contractonderhandelingen
  • Inspelen op verandering boven het volgen van een plan

Discussie over deze kernwaarden heb ik nogal eens waarbij het idee leeft dat zodra ‘agile’ wordt gewerkt, er anarchie is over de software implementatie en bewaking. Ook dit verdient nuance.

Mensen en hun onderlinge interactie

Het voorbereiden op een ISO-audit vereist een nauwe samenwerking tussen afdelingen en medewerkers om de processen in kaart te brengen. Deze ‘agile’ waarde komt juist tot zijn kracht op het moment dat processen worden beschreven die ondersteunend zijn aan de medewerkers. Een Scrum ritueel als bijvoorbeeld Sprint Review kan hierbij faciliteren. Doordat mensen samenwerken komen tekortkomingen en kansen boven drijven. ISO-richtlijnen geeft hierbij handvatten voor aandachtsgebieden. Kortom, als we deze kernwaarde beschouwen, versterken ISO en Agile elkaar.

Werkende software

Om tot werkende software te komen zijn nu eenmaal binnen een team afspraken noodzakelijk die beschrijven hoe code de ‘softwarefabriek’ doorloopt. Hierbij is cruciaal dat vooraf acceptatiecriteria zijn opgesteld en dat deze bij oplevering worden getoetst. ISO stelt geen voorwaarden welke stappen de ‘softwarefabriek’ moet bevatten. Echter, het stelt voorwaarden dat vooraf wordt nagedacht over de gevolgen voor de gebruiker of organisatie op het gebied van gegevens beveiliging. Het team heeft hiervoor velden in Azure DevOps geïmplementeerd om de gevolgen op beveiliging en privacy te documenteren (‘Security and privacy by design’). Het vooraf opstellen van de verwachte gevolgen voorkomt bevindingen later in de ‘softwarefabriek’.

Veel teams hebben een platform om hun software te documenteren. Vaak bevat dit platform ook een beschrijving van hun ‘softwarefabriek’. Het ontwikkelteam heeft ervoor gekozen de documentatie te borgen in hun ‘eigen’ omgeving; Azure DevOps. Deze heeft een Wiki. Op deze manier is de impact voor het team minimaal omdat het geen andere omgeving eigen hoeft te maken. Voor de softwareontwikkelaars is code eigenlijk de documentatie.

De Wiki die in het ontwikkelteam gebruikt bevat niet meer documentatie dan de samenhang van onderdelen in het landschap. UML-modellen worden niet vereist en ook niet gebruikt omdat deze te weinig actueel blijven. De Wiki helpt nieuwe teamleden tijdens het inwerkproces.

Daarnaast is de integratie met het volgen van de softwareontwikkeling naadloos. In de documentatie zijn gegevens als bijvoorbeeld openstaande bugs online beschikbaar bij de documentatie.

Samenwerking met de klant

Vooral op het gebied van vooraf nadenken over gevolgen op privacy en beveiliging komt het team nader tot de klant. Hierbij wordt het discussiëren over een wens met dubieuze gevolgen niet uit de weg gegaan. Het heeft de organisatie geholpen om voor grotere user stories (‘Epics’) een “Data Protection Impact Assessment” op te stellen. Net zoals bij de vorige kernwaarde, geeft dit eerder in het ontwikkelproces heldere verwachtingen over de gevolgen en daarmee de maatregelen die erbij horen.

Inspelen op verandering

ISO stelt geen eisen over het te volgen ontwikkelproces. Als Scrum Master faciliteer ik de werkvormen en rituelen van het Scrum Framework. Het is een kwestie van documenteren hoe deze werkvormen in dagelijkse operatie worden uitgevoerd. Uitkomst van een Retrospective worden opgenomen in de Product Backlog. Bevindingen en opmerkingen tijdens een demo worden als ‘bevinding’ opgenomen in de Product Backlog.

Zolang de werkvormen en de workflow van de organisatie zijn gedocumenteerd, is deze kernwaarde eenvoudig te beschrijven conform ISO-richtlijnen. Het is eigenlijk niet meer dan ‘prove what you have written down’. Azure DevOps biedt hiervoor uitstekende tracking gereedschappen waarbij vanaf user story tot en met productie oplevering alles is te herleiden.

Conclusie

Eerlijk is eerlijk, vooraf was ik sceptisch over het te volgen traject. Echter, juist de kernwaarden van het Agile Manifesto hebben de organisatie geholpen om pragmatisch en gestructureerd zich voor te bereiden op de ISO-certificering. Als Scrum Master had ik het belang dat de gevolgen voor het ontwikkelteam werden beperkt. Dat is gelukt; geplande opleveringen en kwaliteit hebben geen nadelige gevolgen ondervonden.

Ik kan melden dat de organisatie met vlag en wimpel het ISO 27001 certificaat heeft gehaald. Wil je meer weten hoe ik dit het met de organisatie en het team heb aangepakt? Ik ben bereikbaar via akraak@bergler.nl, 076 – 572 02 00 of info@bergler.nl.

Auteur: Arjen Kraak © 2020 Bergler Competence Center

berglerAgile werken en denken in relatie tot ISO 27001 (of welke geformaliseerde certificering dan ook)
Lees meer

Python, een korte introductie (voor C# ontwikkelaars)

Python, een korte introductie (voor C# ontwikkelaars)

Python is een ontwikkeltaal die al enige tijd sterk in opkomst is. Als ‘T-shaped’ software ontwikkelaar kunnen we hier niet langer om heen. Dit is voor ons ook de aanleiding geweest om eens een blik te werpen op deze taal. In dit artikel willen we een globale introductie geven van Python de ontwikkeltaal en daarnaast de kenmerkende verschillen met C# aanstippen.

Hoe is het ontstaan
“Python is een programmeertaal die begin jaren 90 ontworpen en ontwikkeld werd door Guido van Rossum, destijds verbonden aan het Centrum voor Wiskunde en Informatica (daarvoor Mathematisch Centrum) in Amsterdam. De taal is mede gebaseerd op inzichten van professor Lambert Meertens, die een taal genaamd ABC had ontworpen, bedoeld als alternatief voor BASIC, maar dan met geavanceerde datastructuren. Inmiddels wordt de taal doorontwikkeld door een enthousiaste groep, tot juli 2018 geleid door Van Rossum. Deze groep wordt ondersteund door vrijwilligers op het internet. De ontwikkeling van Python wordt geleid door de Python Software Foundation. Python is vrije software.
Python heeft zijn naam te danken aan het favoriete televisieprogramma van Guido van Rossum, Monty Python’s Flying Circus.”
Bron: https://nl.wikipedia.org/wiki/Python_(programmeertaal)

Toepassingsgebieden
Python is geschikt voor een breed scala aan, zo niet alle, toepassingsgebieden. De voornaamste toepassingsgebieden waar Python momenteel wordt gebruikt zijn:

  • (BI) Data science
  • (ML) Machine Learning
  • (AI) Artificial Intelligence
  • (IOT) Internet Of Things

Andere toepassingsgebieden zijn o.a.:

  • Web applicaties
  • Web (REST) API’s
  • Desktop applicaties
  • OS scripting

Kenmerken
In onderstaande tabel worden enkele kenmerken van de Python programmeertaal opgesomd met daarnaast de C# programmeertaal als tegenhanger:

Dynamically typed versus statically typed

In een ‘dynamically typed’ programmeertaal zoals Python, is het niet noodzakelijk om variabelen met een bepaald type van te voren te declareren. Een variabele kan zelfs tijdens de uitvoering van het programma van type wisselen. In een ‘statically typed’ programmeertaal zoals bijvoorbeeld C#, dienen de variabelen van te voren, als zijnde van een bepaald type, te worden gedeclareerd.
De onderstaande code is correct in Python, maar zal compiler fouten opleveren in C#:

Python:

Deze code zal zonder problemen worden uitgevoerd en print de tekst “Hello world” in de console.

Figuur 1- Dynamically typed voorbeeld

C#:

Deze code zal niet compileren en zal dus niet worden uitgevoerd.


Figuur 2- Strongly typed voorbeeld

Duck typed vs Strongly typed

De term ‘Duck typing’ is voortgekomen uit de zin “If it looks like a duck and quacks like a duck, it is a duck” en wordt voornamelijk toegepast in dynamische programmeertalen. Bij duck typing gaat men ervan uit dat je geen type nodig hebt om een bestaande methode op een object uit te voeren, zolang de methode zelf maar aanwezig is. De volgende python code is een voorbeeld van Duck typing en compileert zonder problemen:


Figuur 3- Duck typing in dynamische taal

Het probleem komt pas boven water tijdens de uitvoering van het programma (run time):


Figuur 4- Runtime error

Omdat C# een strongly typed programmeer taal is zal zulke code direct leiden tot een compiler error, omdat de compiler niet het juiste type van de objecten kan bepalen:


Figuur 5- Compile error

Indentation based vs syntax based

Python is ‘Indentation based’ de code van een Python programma is gestructureerd d.m.v. ‘indentation’ (inspringen), terwijl de code van een C# programma gebaseerd is op een vastgelegde syntax. Om binnen Python aan te geven dat een stukje code bij elkaar hoort en gezien dient te worden als 1 code blok gebruik je ‘indentation’. De scheiding van de verschillende code blokken wordt aangegeven door 1 of meerdere lege regels.


Figuur 6- Frame class in Python gebaseerd op ‘indentation’

In een op syntax gebaseerde programmeertaal, zoals C# worden de code blokken gedefinieerd doordat de verschillende code regels omsloten zijn door een bepaald symbool, in C# zijn dit de accolades {}.


Figuur 7- Frame class in C# gebaseerd op syntax

Object georiënteerd

Zowel Python als C# zijn programmeer talen waarin je object georiënteerd kunt programmeren. Een van de kenmerken van object georiënteerd programmeren is overerving. Dit kan in Python als wel in C# gerealiseerd worden. De volgende code snippets geven een voorbeeld van een Persoon class en een Student class, waarbij de Student class afgeleid is (overerft) van de Persoon class.

Overerving in Python:

Figuur 8- Voorbeeld overerving in Python

Overerving in C#:

Figuur 9- Voorbeeld overerving in C#

Programmeer-oefening Python

Voor onze interne competence center avond (pizza-avond) hadden we een oefening voorbereid, waarmee onze collega’s aan de slag konden om zo wat eerste ervaringen op te doen met programmeren in Python. Deze oefening is gebaseerd op de wel bekende ‘Bowling kata’.
Mocht je interesse zijn gewekt om eens met Python aan de slag te gaan, dan kan je deze oefening hier vinden:
Bowling Kata programmeer oefening.

In het readme.md bestand vind je een beschrijving van de oefening en hoe je hiermee aan de slag kunt gaan.
Veel plezier op je Python ontdekkingsreis!

Auteur: Marcel Slegt © 2020 Bergler Competence Center

berglerPython, een korte introductie (voor C# ontwikkelaars)
Lees meer

Zeven tekenen van rottende software

Zeven tekenen van rottende software

Hopelijk begin je een software ontwikkeling met een redelijk tot goed idee hoe de toekomstige software er uit moet zien. Een helder beeld hebben van de toekomstige software is belangrijk voor jezelf en voor je team. Als je geluk hebt, overleeft dit beeld het tot de eerste release. Maar na verloop van tijd gebeurt er iets, de software begint langzaam maar zeker te ruiken als een stuk bedorven vlees.

Hoewel geen enkele ontwikkelaar dit wil, is het een realiteit die ik maar bij al te veel ontwikkelaars tegenkom. In de loop van de tijd is onder druk van deadlines, wijzigende functionaliteit, wijzigende teamsamenstelling de software langzaam maar zeker steeds ondoorzichtiger geworden. In dit document ga ik in op zeven tekenen van software rot en wat je kunt doen om dit zoveel mogelijk te voorkomen.

Rigiditeit
Rigide software is software die moeilijk aan te passen is. Een op het eerste gezicht simpele aanpassing stuurt resulteert in een cascade van gevolgschade in diverse modules. Hoe meer plekken geraakt worden door aanpassingen, hoe meer rigide het systeem is. Veel ontwikkelaars herkennen hoe een simpele aanpassing een waterval van ellende over ze heen stort waardoor ze steeds meer code moeten aanpassen en de wijziging veel langer duurt dan oorspronkelijk was ingeschat. Als ze dan gevraagd wordt waarom hun inschatting zoveel te laag was, volgt het traditionele antwoord “het was een stuk complexer dan ik had verwacht.”

Breekbaarheid
De breekbaarheid van een systeem wordt bepaald door de kans dat een wijziging op één plek op vele andere plekken onverwachte fouten introduceert. Soms kan het voorkomen dat er fouten optreden op plekken die niet logischerwijs gerelateerd zijn aan de aangebrachte wijziging.

Immobiliteit
Een ontwerp is immobiel wanneer het componenten bevat die voor andere systemen nuttig zouden zijn, maar niet geïsoleerd kunnen worden omdat het risico en de kosten om ze uit het originele systeem te halen gewoonweg te groot zijn.

Viscositeit
Als er een wijziging in software moet worden aangebracht kan dit meestal op meerdere manieren. Sommige manieren zijn in lijn met het ontwerp en de architectuur van de software en andere niet (ook wel hacks genoemd). Een systeem heeft een hoge viscositeit wanneer een aanpassing in lijn met de architectuur meer tijd kost dan een hack. Naast de viscositeit van de software is er ook nog de viscositeit van de ontwikkelomgeving in zijn geheel. Wanneer het uitvoeren van geautomatiseerde tests heel veel tijd kost, is het waarschijnlijk dat de ontwikkelaar een wijziging doorvoert zonder de juiste testen op te zetten.

Nodeloze herhaling
Of ook wel het knippen en plakken van code genoemd. Meestal wordt dit veroorzaakt doordat het systeem niet de juiste abstracties implementeert en niet conform design patterns als SOLID is opgezet. Vaak is het een teken dat er te weinig tijd (of ervaring) binnen een team is om na te denken over architectuur. Wat overblijft, is veelal procedurele code die weliswaar functioneert, maar lastig te onderhouden is.

Duidelijkheid
De duidelijkheid van een module bepaald in hoeverre het eenvoudig is voor een ontwikkelaar om een module te begrijpen. Code die met de tijd doorontwikkeld is, heeft de neiging om steeds minder duidelijk te zijn.

Nodeloze complexiteit
Dit is misschien wel een van de lastigste punten om aan te pakken. Gepassioneerde ontwikkelaars zullen in hun inzet om de overige zes tekenen van software rot te voorkomen, mogelijk in de valkuil van deze zevende stappen. Een goed software ontwerp is lichtgewicht, flexibel, eenvoudig om te begrijpen en bovenal eenvoudig om aan te passen.

Omgaan met rottende software
Helaas is er geen “silver bullet” als het gaat om software rot. Ervaren ontwikkelaars zullen misschien minder snel in valkuilen stappen dan minder ervaren ontwikkelaars, maar uiteindelijk maken we allemaal fouten.

Er zijn wel een aantal zaken die helpen om software rot te voorkomen:

  • Zorg dat de software voldoende afgedekt is door automatische testen
  • Zorg bij iedere wijziging en nieuwe feature voor voldoende tijd om te refactoren
  • Peer review elkaars code
  • Pair program wanneer je een ingewikkeld stuk moet opzetten
  • Zorg voor heldere coding guidelines voor het team
  • Maak architectuurbeslissingen altijd met meerdere ontwikkelaars samen

“Last-but-not-least” zoals een collega van mij vaak mooi weet te zeggen: “perfect is the enemy of good”. Probeer niet de perfecte architectuur te maken, die bestaat niet, en waarschijnlijk wordt je systeem al snel nodeloos complex.

Auteur: Menno Jongerius © 2020 Bergler Competence Center

berglerZeven tekenen van rottende software
Lees meer

Kan Cloud Native On-Premises zijn?

Kan Cloud Native On-Premises zijn?

Nee, dit gaat niet over het On-Premises thuiswerken met behulp van Cloud Diensten in onheilspellende tijden van het Coronavirus. Dit gaat over vraag “kun je Cloud Native zijn met een On Premises serverpark?” Vreemde vraag leek mij. Volgens Wikipedia is Cloud Native een softwareontwikkeling aanpak die maximaal de mogelijkheden van Cloud Computing gebruikt. Dit strookt niet direct met een On Premises aanpak. Vanwaar dan toch deze vraag? Dit is naar aanleiding van het rapport van VMWare “The State of Kubernetes 2020.

Dit is het nieuwste onderzoeksrapport van VMWare onder een aantal grote organisaties naar de status van Kubernetes. Het rapport heeft wat verrassende uitkomsten zoals dat 64% van de ondervraagden Kubernetes On-Premises draaien, wat meer is dan vergelijkbare rapporten. Dit heeft waarschijnlijk te maken met het type organisaties dat VMWare in dit onderzoek heeft ondervraagd. Het zijn namelijk alleen organisatie met 1000 of meer medewerkers. Organisaties van deze omvang hebben wellicht zelf al veel infrastructuur staan, waardoor de switch naar de cloudproviders minder snel van belang is.

Het ligt voor de hand dat in het kader van de bovenstaande uitslag de onderstaande quote in het rapport is opgenomen:

“Cloud native isn’t about where you operate, it’s how you operate.”

(Joe Beda, Principal Engineer, VMware and co-creator of Kubernetes)

Dit is een uitspraak waar ik even van op mijn hoofd moest krabben. Is het zo dat de manier waarop je werkt bepaalt of je cloud native bent en niet de plek? Om dit te kunnen beantwoorden moet ik eerst antwoord hebben op de vraag:

Wat is eigenlijk cloud native?
Als we praten over cloud native dan is de Cloud Native Computing Foundation direct de organisatie waar je aan zult denken. Met de gang naar de cloud is het makkelijker geworden om open source projecten van verschillende bronnen te adopteren, waardoor je organisatie meer kan focussen op business logica en minder op het technische loodgieterswerk. De CNCF heeft als doel om deze open source projecten te beoordelen zodat jij als organisatie enige zekerheid hebt voor de continuïteit en dat je geen vendor lock-in hebt. Dit zijn projecten waarmee je comfortabel de cloud in kunt. Hiervoor heeft het CNCF een overzicht van al hun projecten op 1 plek: https://landscape.cncf.io/.

Het CNCF is de autoriteit op het gebied van cloud native en hebben ook de definitie voor cloud native opgesteld. Vrij vertaald is het ongeveer:
Cloud native technologieën geven organisaties de mogelijkheid om moderne schaalbare applicaties te ontwikkelen en te runnen, in dynamische omgevingen zoals de public, private en hybride clouds. Het gebruik van containers, service meshes, microservices, immutable infrastructuur en declaratieve API’s bevestigen deze aanpak.
Dan terug naar de vraag kan Cloud Native On-Premises zijn. Het antwoord zit hem in de Private Cloud definitie.

Private Cloud (!)= On-Premises
Private clouds kunnen er in vele verschijningsvormen zijn. Zo zijn er private hosted clouds waarbij niet gedeelde dedicated hardware door een cloud provider beschikbaar is gesteld. Of een internal hosted private cloud waarbij de omgeving op de interne infrastructuur van de organisatie geplaatst is. In dit laatste geval kan men spreken van een On-Premises omgeving.
Als men in een dergelijke omgeving gebruik maakt van cloud native projecten zoals door het CNCF worden ondersteund (bijv. Kubernetes) dan kan men spreken over Cloud Native op een On-Premises omgeving.

Wenselijk?
De vraag blijft dan: is het wenselijk om een Cloud Native On-Premise oplossing te ontwikkelen? Dit kan in veel gevallen een prima oplossing zijn. Door geen gebruik te maken van de public cloud kan men b.v. lastige vraagstukken voor legal & compliance ontwijken. Het kan een prima startpunt zijn om met cloud native projecten kennis te maken. Uiteindelijk kan het ook als startpunt functioneren om een hybrid cloud scenario te ontwikkelen.

Het heeft ook een keerzijde, zo ontneem jezelf de mogelijkheid tot het gebruik van managed public cloud diensten. Denk bijvoorbeeld aan AKS, GKE of EKS (managed Kubernetes), Azure SQL of Cosmos DB. Dit zorgt voor meer onderhoud op dergelijke producten of ze kunnen überhaupt niet On Premises worden afgenomen.
Dit zijn overwegingen die moeite waard zijn om te bekijken maar, uiteindelijk is het hebben van een cloud native strategie in een On Premise omgeving prima mogelijk.

Bronnen:
https://k8s.vmware.com
https://www.cncf.io
https://www.capgemini.com
https://github.com

Auteur:
Patrick Bes, Bergler Competence Center © 2020

berglerKan Cloud Native On-Premises zijn?
Lees meer

Threat Modeling

Threat Modeling

In het huidige software ontwikkelingslandschap is het steeds sneller opleveren van software een belangrijk issue. Organisaties moeten mee in de DevOps beweging om hun concurrentiepositie te behouden of te verbeteren. Om dit goed en veilig te kunnen doen is het van belang om zo vroeg mogelijk in het ontwikkelproces al feedback te verzamelen, om snel te kunnen bijsturen, threat modeling is een methode om zwakheden in applicaties snel te herkennen zodat hierop kan worden ingespeeld. Dit vatten we vaak samen in de zogenaamde Shift Left beweging. Shift Left is een verzameling van kwaliteitsborging methodieken zoals o.a. unittesting, performancetesting & componenttesting.

Naast deze belangrijke testfeedback is ook op het gebied van security een van belang dat men zo vroeg mogelijk een helder beeld heeft van de potentiele security risico’s. De wolf in schaapskleren moet al vroeg worden geïdentificeerd. Hiervoor zijn er al tientallen geleden jaren methodieken bedacht, welke helaas vaak over het hoofd worden gezien. DevOps is een manier om een kortere “time to market” te bewerkstelligen, maar daarnaast ook een lager faalpercentage bij opleveringen. Het beperken van security issues in productie is hier natuurlijk ook onderdeel van. Threat Modeling is bij uitstek een methodiek om bij dit laatste te helpen.

Threat Modeling in 5 stappen

Deze methodiek bestaat uit 5 stappen die zich herhalen binnen de Software Applicatie LifeCycle. Het herhalende karakter past ook prima in het herhalende karakter van DevOps,. Of bij het gebruik van deze methodiek wellicht wel DevSecOps, omdat security nu een prominentere rol krijgt. De stappen die men met threat modeling kan ondernemen zijn:

Define: Vastleggen van de securityeisen.
Niet in elke app zullen de securityeisen gelijk zijn. Indien er met persoonlijke data wordt gewerkt zullen er vast eisen zijn vanuit wetgeving c.q. beleid van uit de organisatie zelf. Zorg ervoor dat deze duidelijk zijn.

Diagram: Het maken van een applicatiediagram
Om inzicht te krijgen in de potentiële dreigingen is het makkelijk om de flow van de betreffende applicatie te modelleren. Dit kan men doen in specifieke Threat modeling tooling zoals bijvoorbeeld Thread Dragon: https://threatdragon.org/login.

Hierin kan men de applicatie weergeven via een eenvoudige Data Flow Diagram bestaande uit Processen, Stores, Actors en/of DataFlows zoals hier weergegeven.

Identity: Het identificeren van de potentiële bedreigingen
Na het opstellen van het diagram kan men met Trust boundaries koppelvlakken aangeven waar men risico’s herkend. Het model kan na deze stap er als volgt uit zien (De groene stippellijnen representeren de Trust Boundaries):

Mitigate: Het mitigeren van de bedreigingen
In 1999 hebben Praerit Garg and Loren Kohnfelder bij Microsoft het STRIDE Model ontwikkeld. Met dit model kan men per trust boundary de specifieke kwetsbaarheden classificeren. STRIDE is een acroniem voor:

Men kan nu per trust boundary inventariseren welke onderdelen van STRIDE hier een bedreiging vormen. In het eerdere voorbeeld kunnen wij aangeven dat Spoofing Identity tussen de browser en webapplicatie een potentieel risico is. Dit risico kan in dit geval bijvoorbeeld gemitigeerd zijn door het gebruik van een signed authenticatie token. Zo kan men met threat modeling alle trust boundaries langs lopen en aan de hand van STRIDE de risico’s inventariseren en bepalen of deze adequaat zijn gemitigeerd.

Validate: Het valideren of alle bedreigingen zijn gemitigeerd
Na het mitigeren van de potentiële bedreigingen is het nog steeds van belang dat men valideert of er toch geen security leaks of kwetsbaarheden in de applicatie zijn geslopen. Het hebben van geautomatiseerde security scans, dependency checks in de pipeline en real time is nog steeds van belang. Daarnaast kunnen er, nu inzichtelijk is waar de potentiele grootste risico’s zitten, abuse cases worden opgesteld. Op basis hiervan kunnen weer specifieke test scenario’s worden bedacht om de gemitigeerde bedreigingen te valideren.

Tot slot
Het kan goed zijn om deze threat model techniek in je DevOps proces op te nemen. Hierdoor kunnen potentiële security leaks al vroegtijdig worden geïdentificeerd en kan hierop worden geacteerd. Het neemt initieel niet veel extra tijd in beslag en kan veel opleveren. Het vergroot in ieder geval de security awareness bij alle betrokkenen en dat is altijd winst.

Auteur: Patrick Bes © Bergler Competence Center 2020

berglerThreat Modeling
Lees meer

Domain Driven Design (DDD) in gewoon Nederlands

Domain Driven Design (DDD) in gewoon Nederlands

Introductie naar Domain Driven Design (DDD)

Als Lead Developer ben ik betrokken bij het opmaken van business cases, uitwerken van ideeën en het implementeren van softwareoplossingen. Een steeds vaker terugkomend thema is dat mijn relaties hun applicatie landschap willen moderniseren zonder opnieuw het wiel te willen uitvinden.

berglerDomain Driven Design (DDD) in gewoon Nederlands
Lees meer

Valkuilen in async/await

Valkuilen in async/await

Het is inmiddels alweer behoorlijk wat jaren geleden dat Microsoft async/await introduceerde in het .NET Framework. Het gebruik van async/await heeft het mogelijk gemaakt om met heel weinig code asynchroon te programmeren. Helaas betekent dit niet dat het eenvoudig is om asynchroon te programmeren, en ik heb mijzelf meermalen in de voet geschoten doordat ik te kort door te bocht wilde gaan. Bij deze wat valkuilen waar ik tegenaan ben gelopen, maar eerst even de twee belangrijkste redenen om asynchroon te programmeren.

Waarom async/await een goede zaak is

Er zijn eigenlijk twee belangrijke redenen om async/await toe te passen. In webapplicaties zal de webserver (afhankelijk van de gekozen technologie) maar een beperkt aantal threads tegelijk in een workerprocess afhandelen. Dit betekent dat bij een groot aantal gelijktijdige verzoeken de webserver processen in de wacht gaat zetten. Door gebruik te maken van async/await, wordt de calling thread van het workerprocess vrijwel direct vrijgegeven, terwijl een background thread de bulk van het werk uitvoert. In client applicaties (Windows en apps) zijn asynchrone processen vooral van belang omdat de UI-thread wordt vrijgegeven en de applicatie dus goed blijft reageren op de gebruiker, terwijl processen op de achtergrond worden afgehandeld. Elke langlopende taak (database, I/O of zware berekening) leent zich om in een asynchrone taak af te handelen.

Valkuil 1: Deadlocks

In het voorbeeld hieronder wordt het resultaat van een taak uitgevraagd. Stel dat dit een asynchrone methode is, die zelf ook gebruik maakt van async/await, dan creëer je een deadlock. Dat komt omdat het aanroepen van Result, de UI-thread in de wacht zet totdat het resultaat van de methode terugkomt. Als de methode zelf een await commando gebruikt, zal deze een thread opstarten en na afloop het werk willen teruggeven aan de UI-thread. Dat kan echter niet omdat deze UI-thread aan het wachten is op het resultaat van de functie die hij nu zelf zou moeten uitvoeren.

Ofschoon dit fenomeen vooral voor zal komen in een Windows applicatie of app, is het niet uit te sluiten dat deadlocks voorkomen in een webapplicatie wanneer je zelf de asynchrone taken beheert en niet gebruik maakt van de asynchrone controllers van ASP.NET.

Oplossing

Zorg dat de methode nadat deze gereed is, wordt opgevolgd door een nieuwe asynchrone taak die het resterende werk uitvoert. In de praktijk is het aan te raden om een class op te zetten die alle uitkomsten van een taak correct afhandelt, want er komt nogal wat bij kijken om alle foutafhandeling en cancellation scenario’s in te bouwen.

Valkuil 2: UI werk op een niet-UI-thread

In het voorbeeld hierboven werd het resultaat van een taak gebruikt in op een label de content te veranderen. Dit gaat fout in Windowsapplicaties en apps wanneer een andere thread dan de UI-thread deze code uitvoert.

Oplossing

Stuur het werk dat naar de UI-thread moet via de Dispatcher naar de UI-thread. Deze is toegankelijk vanaf een window/usercontrol of via het Application object. In de praktijk schijf ik er altijd een proxy met interface voor, zodat ik de code ook kan unittesten.

Valkuil 3: incorrecte/geen foutafhandeling

Binnen een async/await context worden fouten netjes doorgegeven aan de aanroepende thread. Wanneer je aan het einde van de call-chain aankomt, is het heel gemakkelijk om de foutafhandeling te vergeten.

Bovenstaande code zal zonder problemen draaien, maar indien er in de ExecuteAsync een fout plaatsvindt zal deze niet zichtbaar worden in de aanroepende thread. Gebruik om dezelfde reden geen async void (tenzij je zeker weet wat je doet), maar retourneer altijd een taak zodat eventuele fouten afgehandeld kunnen worden. Wanneer je de code aanpast naar ExecuteAsync().Wait() zal er wel een fout optreden, echter dan krijg je weer deadlock problemen.

Oplossing

Schrijf, zoals in een eerder voorbeeld, een juiste continuatie taak waarin eventuele fouten worden afgehandeld.

Schrijf wat er moet gebeuren wanneer er een fout optreedt (bij voorkeur wat charmanter dan MessageBox.Show).

Valkuil 4: await alleen als het nodig is

In het bovenstaande voorbeeld wordt de ReadFileAsync methode aangeroepen. De aanroepende methode zal bij het await keyword een nieuwe thread opstarten om het asynchrone werk op te pakken. De ReadFileAsync methode zal nogmaals een thread opstarten bij het await keyword. Deze laatste is onnodig omdat de waarde van ReadToEndAsync in deze methode niet gebruikt wordt. In dit geval is het beter om geen async/await te gebruiken, maar rechtstreeks een Task te retourneren.

Oplossing

Geef een taak terug zodat er slechts een thread opgestart wordt bij de eerste await. Let wel op dat je in dit geval de boundaries van de code goed in acht neemt. De using statements moeten hier binnen de taak liggen en niet erbuiten anders zijn deze objecten al opgeruimd terwijl de taak nog draait.

Valkuil 5: start niet onnodig threads op

Los van de zaken die in bovenstaande code niet juist zijn, zoals het niet afhandelen van fouten en onhandig aanmaken van de HttpClient, wordt er voor elke parallelle actie nu een extra thread gemaakt voor het uitvoeren van de post. Dat betekent een thread vanuit de task parallel library en een vanuit async/await.

Oplossing

Bij een groot aantal url’s is de beste oplossing om wel de task parallel library te gebruiken, maar hierbinnen de post synchroon te houden. Bij een klein aantal url’s kun je beter een lijst van taken retourneren waar je de code op laat wachten.

Auteur: Menno Jongerius, Bergler Competence Center © 2020

berglerValkuilen in async/await
Lees meer

Stoornissen van teams, impact op de kernwaarden van het Agile gedachtengoed

Stoornissen van teams, impact op de kernwaarden van het Agile gedachtengoed

De Scrum Master van een team houdt zich onder andere bezig met het welzijn en functioneren van het ontwikkelteam. Welke signalen moet je herkennen en waarom zijn deze belangrijk? Mijn ervaring in de rol van Scrum Master gebruik ik om deze vraag via dit blog artikel te beantwoorden.

Patrick Lencioni heeft een boek geschreven over de “5 dysfunctions of a team”. In de stijl van De Phoenix Project beschrijft hij een fictief team in Silicon Valley die onvoldoende presteert. Het boek hanteert de volgende stoornissen in het gedrag van het team:

  • Ontbreken van vertrouwen tussen de teamleden
  • Bang om conflicten aan te gaan
  • Ontbreken van motivatie
  • Ontwijken van verantwoordelijkheid
  • Onvoldoende aandacht voor resultaat

Het is de taak voor de Scrum Master of coach om dit gedrag te herkennen. Daarover gaat dit blog artikel.

Waarom leidt dit gedrag tot het falen van Agile & Scrum toepassingen in organisaties. Veel organisaties komen namelijk in de verleiding om het raamwerk van Scrum en het Agile denken de schuld te geven bij het ontbreken van resultaat. Eigenlijk moet de oorzaak worden gezocht in de basale principes van teamwork en menselijke interacties.

Het agile gedachtengoed is gebaseerd op de volgende principes:

  • Inspectie, de opgeleverde software is altijd de interpretatie van het ontwikkelteam van de verzameling van user story’s. Interpretaties zijn aannames deze moeten altijd worden gevalideerd. Bij softwareprojecten wordt dit gedaan door het testen van de oplevering op verschillende niveaus van detail (unit testen, integratie testen, acceptatie testen, etc.)
  • Aanpassing, het resultaat van de inspectie moet worden toegepast op het product in ontwikkeling. Het gaat hierbij niet alleen om het verhelpen van bevindingen, maar ook over het ontwikkelproces. Veranderen is dus nodig om het product te verbeteren en de snelheid van het beschikbaar krijgen ervan te optimaliseren
  • Transparantie, het ontwikkelteam moet altijd de voortgang van de ontwikkeling kunnen presenteren aan de stakeholders. Hierdoor worden verwachtingen uitgewisseld, verrassingen voorkomen en oplossingen voor leerpunten zichtbaar gemaakt

Het beantwoorden van de vraag waarom stoornissen een bedreiging zijn voor een succesvolle toepassing van agile gedachtengoed doe ik middels de introductie van de “Agile stoornis matrix”.


Tabel 1: Bedreigingen van stoornissen op de pijlers van Agile werken en denken

Het doel van de bovenstaande tabel is om inspiratie te geven voor herkenning van gedrag en gebeurtenissen in het veld en het gevolg daarvan op agile werken en denken. Ongetwijfeld zijn er meer voorbeelden te bedenken. Graag verneem ik de reacties hierop. Ook sta ik open voor constructieve feedback over dit onderwerp en de inhoud van dit artikel.

Bron: The Great Scrum Master by Zuzana Sochova
Bron: The 5 dysfunctions of a team by Patrick Lencioni

Auteur: Arjen Kraak, Bergler Competence Center © 2019

berglerStoornissen van teams, impact op de kernwaarden van het Agile gedachtengoed
Lees meer