Laat ik hierbij eerst de complimenten geven aan de organisatie van devNetNoord. Een gratis event voor developers, flink wat sprekers, koffie, lunch en een gratis borrel na (met de bijbehorende hapjes), uitstekend georganiseerd. Ik ga er vanuit dat de organisatie weken of maanden bezig is om alles voor te bereiden en te regelen, zo'n dag vliegt dan voorbij, je krijgt een applausje uit de zaal en dan is het alweer voorbij. Dus ik hoop dat de mensen die ook aanwezig waren en het ook een prima event vonden nog even een "bedankt @devnetnoord" in de comments bij mijn post op LinkedIn toevoegen: link.
Want hopelijk is er volgend jaar weer een DEVCAMPNOORD met een aantal interessante sprekers/onderwerpen.
Want je gaat er heen met je collega's (namens TRES waren ook Jeroen en Sjaak aanwezig) en je komt nog eens wat oud-collega's tegen zoals Johan en Johannes.
Hoewel wij als bezoekers niets hoefden te betalen zijn er natuurlijk wel uitgaven en daarom ook nog even een applaus voor de sponsors. Door hun bijdragen is het mogelijk om zo'n dag te organiseren. De sponsors staan ook op de site genoemd, maar omdat er voor het volgende event er misschien nieuwe sponsors komen of omdat de pagina misschien straks er (tijdelijk) niet meer staat omdat het event afgelopen is, drop ik hier nog even de namen.
- KPN
- sopra steria
- DUO
- Gasunie
- new nexus
- vitas
- 4dotnet
- get→there
- Quintor
- eLabNext
- ChipSoft
- Bencom group
- ilionix
- arcady
- capteur
- Future Tech
- Techorama
Naast de onderstaande samenvatting heb ik tijdens de sessies ook foto's gemaakt. Deze kunnen het verhaal aanvullen, mocht je deze willen bekijken, check dan mijn slides-website.
Rond 8.00 uur rij ik naar Groningen, waar ik iets na 9.00 uur mijn auto in de parkeergarage neer kan zetten. Het ombouwen van het wegennetwerk in Groningen is een hele klus geweest, maar we hebben nu geen opstoppingen meer bij het Wilhelminaplein, het rijdt goed door. De inloop is tussen 9.00 en 10.00 uur, ik krijg mijn badge, een tas met goodies en ga naar boven voor een bakje koffie. Daarna door naar zaal 7.
Presentatie 1: The art of getting 💩 done, gepresenteerd door Henry Been
Henry woont op Texel, hij mocht dus iets eerder dan mij opstaan om te zorgen dat hij op tijd aanwezig zou zijn (wat gelukt is). Henry is iemand die niet gauw dingen opvolgt, als hij twijfels heeft gaat hij vragen stellen als "waarom dan", "het kan toch ook zo?", "dat lijkt mij geen goed idee". Zo zet hij zijn vraagtekens bij scrum. "Iedereen doet het", maar doe je het omdat het zo goed binnen jouw organisatie werkt of juist "omdat iedereen het doet"? Werkt het niet in jouw organisatie, dan zou je het juist niet moeten doen. Want developers willen bouwen/coden, niet overleggen, overleggen en nog eens overleggen. Allemaal verloren tijd (en we moeten toch declarabel zijn?). Binnen het bedrijf waar Henry werkt zijn daarom wat aanpassingen gedaan. Zo zijn de pre-refinements en refinements geschrapt. De wekelijkse "tech-debt-meeting" (we hebben hier nog oude code, wat moeten we ermee doen - elke week een uur lullen over hetzelfde: wasted time), sprint plannings en nog een aantal overleggen. De sprints zijn wel behouden (omdat features/fixes klein gehouden worden, kunnen developers ongeveer in 2 dagen een punt opleveren, dus een sprint is prima. Een backlog om alle vragen in bij te houden (ook van de manager: "kun je dit rapport voor mij maken" komt op het backlog), een sprint backlog, daily sync en sprint review. Toevoegingen zijn een fastlane (een server gaat down: dat moet eerst opgelost worden), chore duty: kun je een collega helpen, zodat hij/zij weer verder kan met zijn/haar taken en backlog outlook (waarbij ik niet meer exact weet wat hiermee bedoeld werd). Ik denk dat hij het prima kan vinden met Sander Hoogendoorn, dat is ook een (prima) spreker en een kritisch volger van dogma's zoals scrum. Henry is een fan van het "caretaker model", hier kun je daar meer over vinden. Een prima presentatie als "aftrap" van deze dag.
Presentatie 2: Infrastructure from Code: The Next Generation of Cloud Management door Erwin Staal
Ik meende dat ik Erwin al eens eerder had zien presenteren, dat bleek in 2019 bij een event van 4dotnet in Nieuwegein geweest te zijn. Hij sprak daar toen over Continuous Deployment. Vandaag gaat het over Infrastructure from Code. Je kunt in de portal van Azure alle omgevingen bij elkaar klikken. Maar dat ga je niet elke dag doen, voor 100-en omgevingen doen, want dat is foutgevoelig en behoorlijk geestdodend werk. Daar kwamen sjablonen (templates) voor om dat geautomatiseerd/gescript te kunnen doen. We zien die op de slide, Terraform en Bicep worden genoemd. Dat is infrastructure as code. Je kunt zaken doen, maar dev-oppers, devs die zelf omgevingen opzetten moeten dus ook een extra taal leren. Hoe mooi zou het zijn dat je dit "gewoon" in C# of TypeScript kunt doen? Daar worden nu al wat initiatieven voor gebouwd, Erwin laat een demo zien. Daarbij zijn een aantal onderdelen aangemaakt op basis van het script. Erwin mist daar nog wel zaken en geeft aan dat het volgens hem nog niet "productie-ready" is, maar wel iets om in de gaten te houden. Sowieso is het goed om zelf nog even de genoemde tools zelf eens langs te lopen om te kijken of je er wat mee kunt doen. Dus hier de linkjes, Bicep, Terraform, Pulumi, Backstage, Microsoft Dev Box, Radius, Nitric. Het overzicht van kant-en-klare templates voor Azure Developer CLI is een aanrader. Lees meer over dit onderwerp op de site van "infrastructure from code" zelf. Tijdens het zoeken naar Radius zag ik nog wat termen die ik eerder al gezien had en waarvan ik dacht "ik moet er wat mee doen", maar ik heb er (nog steeds) niets mee gedaan: DAPR en Copacetic.
Presentatie 3: A Season for Speed: Turning puzzles into C# performance wins door Michaël Hompus
Ik had om 13.00 uur de sessie gepland van Jorrik Klijnsma over prompt injection attacks. Maar die was gelijktijdig met de sessie van Erwin Staal, er zijn een paar presentaties omgewisseld. Toen was er namelijk ook nog een sessie over "AI powered pool met Azure Computer Vision door Sjoerd Nijhof" die mijn collega Sjaak bezocht heeft. In ieder geval, API FOMO leek me een theoretisch verhaal over API's, Better architecture without architects leek me een discussie-achtig item, dus het deel "C# performance wins" gaf mij de doorslag om de sessie van Michaël te bezoeken. Mijn collega Jeroen had hetzelfde idee.
En daar heb ik geen spijt van gehad. Een geweldige sessie!
Elk jaar doet Michaël mee aan Advent of Code. Elke dag krijg je 2 puzzels, als je de oplossing van de eerste puzzel inlevert, krijg je de 2e opdracht. Vervolgens is er een leaderboard. Degene die als eerste de juiste opdracht inlevert krijgt 100 punten, de top 100 krijgt 1 punt en de rest krijgt 0 punten. En omdat er duizenden mensen mee doen is de kans erg klein dat je in de top 100 komt. Maar.. je kunt wel je eigen private leaderboards aanmaken, om zo tegen collega's te spelen. Ik zie op het screenshot van Michaël de naam van mijn oud-klasgenoot Dirk Lemstra staan.
Eric Wastl is degene die de site/het idee uitgewerkt heeft. 200.000 mensen die er aan mee doen. Hier kun je een Youtube-interview uit 2019 met hem bekijken.
Michaël bespreekt hier de puzzel van 2020, dus als je die nog zou willen doen (je kunt alle "oude" puzzels nog steeds doen), dan ga ik nu even spoileren :)
Je had een lijst met getallen, je moet daarvan 2 getallen hebben die opgeteld 2020 opleveren, je moet die 2 getallen met elkaar vermenigvuldigen, dat is het antwoord wat je instuurt om opdracht 2 te unlocken.
Michaël heeft een redelijk simpele LINQ-query gemaakt en daarmee het antwoord gerealiseerd. Dikke prima. Voor Advent of Code is dat "goed genoeg". Maar Michaël is eens gaan kijken hoe snel zijn oplossing was én hoeveel geheugen deze gebruikte. Met benchmarking kun je daar mooie overzichten van maken, simpelweg door op je functie een attribuut [Benchmark] toe te voegen. Snelheid 484.000 nanoseconden, geheugengebruik rond 1 MB. Klinkt mij als "best snel" in de oren, maar volgens Michaël niet goed genoeg. Door de code om te zetten naar een array krijgen we een snelheid van 136.000 nanoseconden en een geheugengebruik van 10 kB. We krijgen nog een paar voorbeelden te zien (die kun je in de slides bekijken). De two-pointers-techniek wordt door Michaël behandeld, dan zitten we op 2.400 nanoseconden en 872 bytes. Uiteindelijk besluit Michaël de BitArray te gebruiken. Dat is 622 nanoseconden, 312 bytes geheugen. Als je dit vergelijkt met het begin dan is dat inderdaad "veel te traag" en neemt het "veel te veel geheugen".
We zien de eindlijst van Michaël, alle 25 dagen een opdracht, de tijd en het geheugengebruik opgeteld. Dat is 80 milliseconden (0.1 seconde) en 589 KiB. Een prachtig mooi resultaat!
Ook laat Michaël ons nog zien hoe je tekstfiltering sneller/minder geheugenintensief kunt maken. We grijpen al snel naar een Regex: 595 microseconden, 1.6 MB geheugen. Als we hier iets met een Smart Span <T> doen is het 13 microseconden, 35 kB.
Michaël vraagt wie "goto statements afkeurt", ik ben daar 1 van. In het verleden was dat "normaal" in Basic (goto 10 om terug te gaan naar ander deel van je code), in het boek Clean Code wordt het ook als "evil" beschouwt omdat je de flow van je programma verbreekt. Nu vind ik het voorbeeld van Michaël op zich wel een mogelijkheid om die optie wel te gebruiken om het gebruik van extra variabelen te vermijden.
We krijgen nog wat tips en trucs:
- gebruik % om door je variabelen te loopen, zo krijg je geen overflows.
- gebruik het in argument, dan maak je duidelijk dat de waarden niet wijzigen en wordt er geen kopie van de value-types gemaakt.
- je hoeft char arrays niet te initialiseren, dat doet het systeem al voor je met een \0 en dat is prima.
- gebruik [^1] om het laatste item van een string of array te benaderen
- als je een unieke char kunt gebruiken om een string te vergelijken, doe dat dan. bij "red", "green", "blue" wijkt de eerste letter af, dus je kunt checken op [0] met waardes r,g,b.
Ook komt Michaël nog met een lijstje met algoritmes. Kun je vast wel eens ergens gebruiken;
- Dijkstra's Algoritme (gebruikt bij het Telebuggy-project bij de opleiding Hogere Informatica aan de NHL)
- A* (A-star) algorithm
- Manhattan Distance (Taxicab Distance or City Block Distance)
- Least Common Multiple (LCM)
- Greatest Common Devisor (GCD)
- Shoelace Formula (Gauss's area formula)
- Kargers algorithm for minimum cut
Nog een lijstje van mensen die ook hun code tunen:
De code van Michaël is op zijn Github te bekijken.
Presentatie 4: What is new in .NET and C#? door Johnny Hooyberghs
Wederom een uitstekende presentatie. Hou ik bij wat er allemaal in C# en .NET verandert? Nou nee... het zou eigenlijk wel moeten. Dan is het fijn dat iemand zoals Johnny een eigen Github-repo heeft aangemaakt en daar een project in heeft die in map-structuur een groot deel van de wijzigingen en toevoegingen laat zien. Tijdens deze presentatie doorloopt Johnny zijn project en laat ons kennis maken met:
- we zien hoe een functie met 2 type parameters aangeroepen kan worden (int[] en Span<int> en hoe je via het attribuut [OverloadResolutionPriority] je kunt zorgen dat een implementatie eerder wordt aangeroepen dan de andere;
- als je data BASE64 encode, dan zitten daar soms items in die niet in een URL kunnen, daarvoor heb je nu Base64Url.
- hoe je met [^1] het laatste element selecteert, [^2] het op een-na-laatste, etc;
- hoe je met get => field en set => field = value.ToUpper() een soort impliciete private interne variabele hebt (breaking als je zelf een private variabele met naam field gebruikt);
- er nu een sorteerbare GUID is, Guid.CreateVersion7();
- een nieuw Lock-object (Lock.EnterScope);
- de BinaryFormatter is uit .NET 9 gehaald (de runtime), was niet secure. Dus gebruik je deze in code, dan krijg je in runtime een exceptie: breaking!
- coole tool: ILSpy
Check voor items de Github-repository.
Presentatie 5: Nullable Reference Types: It's Actually About Non-Nullable Reference Types door Shawn Wildermuth
Dit was één van de triggers om een kaartje te reserveren, ik had namelijk net een podcast van .NET Rocks beluisterd waarin Shawn te gast was. Een podcast uit 2007, dus "de man loopt al een tijdje mee". Ik dacht: "hij komt helemaal uit Amerika hier naartoe!", maar bij het intro vertelt hij dat hij in Den Haag woont. Dat verklaart ook dat zijn website inmiddels op een .NL-domein draait. We zien op het scherm onder andere het boek Pragmatic ADO.NET wat hij "een hele tijd geleden" heeft uitgegeven, in de begintijd van .NET. Met een voorwoord van Chris Sells, die zou ik ook nog wel eens "live" als spreker willen mee maken. In de tijdlijn die hij laat zien van 2002 tot 2024 zie je per jaar de grootste wijzigingen, dat zijn er nogal wat. Shawn vraagt zich af of wij een beetje "mee gaan met de ontwikkelingen", want in Amerika is het vaak: "ik heb het op deze manier geleerd en altijd gedaan, dus ik blijft het zo doen".
Shawn laat zien hoe variabele types niet null kunnen zijn (zonder ? teken), maar hoe Reference Types dat standaard wel zijn (zoals een string). Daar moet je dan in code elke keer een .IsNullOrEmpty(..) check op doen. Een tijd geleden (.NET 6?) had je al in de config dat nulls standaard disabled zijn. Daarmee wordt je in code gedwongen om expliciet je zaken te initialiseren of required te maken.
Shawn geeft de tip dat als je bepaalde delen van je code "een uitzondering wilt geven", bijvoorbeeld doordat het Entity Framework-code is, je dit met #nullable disable .... #nullable enable kunt patchen.
En hij noemt nog even dat hij niet AutoMapper gebruikt, maar Mapster.
Omdat Shawn graag foto's / opnames op zijn Bluesky willen ontvangen heb ik een korte clip op Youtube gezet en een Bluesky-account aangemaakt en hem daarin getagged.
Presentatie 6: 20 Years of software development, what could possibly go wrong? door Eduard Keilholz en Sander Molenkamp
Een "duo-presentatie", met de voting-software van Eduard. We zien de grafiek die we als het goed is allemaal wel eerder hebben gezien. Als je junior-developer bent is je code behoorlijk "simpel", je gaat technieken toepassen, andere zaken doen en je code begint behoorlijk complex te worden. En als het goed is eindig je weer bij simpele code :) Eduard is net als ik gestart met Basic /QuickBasic, de tijd dat je nog coole geluidjes kon programmeren die dan via je pc-speaker werden afgespeeld.
Sander laat nog even zien hoe hij vroeger in Delphi programmeerde en dat brengt (goede) herinneringen boven naar de tijd dat ik de opleiding Hogere Informatica aan de NHL deed, je Windows Forms applicatie maken: yes! We zien de "oude en vertrouwde" Linksys router (ook alweer een oudje) die door het gebruik van software een deel van de broncode moet vrijgeven omdat volgens die licentie dat verplicht was (een gang naar de rechter bracht die uitkomst).
Een bommetje wordt dan gedropt met de tweet op het scherm dat AutoMapper en MediatR commercieel gaan: het worden betaalde producten. Dat doet bij een aantal mensen (waaronder bij mij) het nekhaar omhoog gaan, want het zijn nuget-packages die zo'n beetje in elk project gebruikt worden. De vraag van Sander/Eduard is of wij (de mensen in de zaal) wel "exit-strategieën hebben".
Het is niet slim om alles zelf te gaan bouwen. Maar het is ook niet slim om voor elk stukje code externe codebibliotheken te gebruiken. Zo zien we de voorbeelden van npm-packages "left-pad", "is-odd" en "is-even". En als je daarbij de wekelijkse downloads ziet, 1.401.690 keer, dat is inderdaad "niet goed".
Naar aanleiding van deze zaken is Sander gaan nadenken over wat hij zelf gebruikt. Bij het Entity Framework krijgen veldnamen in databases een naam die met een hoofdletter beginnen. Hij gebruikt een PostgreSQL-database. Die heeft qua structuur het liefst lowercase veldnamen. Sander gebruikt daar een package voor en is eens gaan kijken op de site van het package (hij had geen problemen gehad). En zag daar best wel veel issues, dus ontstond de vraag: wil ik dit nog wel gebruiken. Handmatig alles aanpassen is niet te doen. Maar... met hulp van CoPilot die na een paar keer het trucje snapte is dat gefixt.
Eduard bespreekt de monolieten en de microservices. Een aantal jaren geleden "moest" alles op basis van microservices gebouwd worden, maar naast voordelen heeft het ook nadelen. Het is dus bij de start van een project goed nadenken over het mogelijk verloop van het project en wat er volgens jou de beste implementatie voor zou zijn.
Deze presentatie was een mooie afsluiting van een zeer geslaagde dag!
Hierna gaan we naar onderen, naar het café, waar we een beugelfles Grolsch krijgen, we nog even wat napraten en ik na een half uurtje besluit om terug naar huis te rijden. Met de matrixborden in Groningen een aantal keren vertragen, afremmen en weer door rijden, dus rond 18.15 uur ben ik weer thuis. Mijn eerste keer DEVCAMPNOORD en zeker niet de laatste keer :)
Geen "minpunten", maar een paar verzoekjes voor de volgende editie ;)
- Er komen developers die gek op code zijn. Dus wat technische (en misschien wat moeilijkere) zaken behandelen wordt vast gewaardeerd.
- Het is een bioscoop, je jas doe je uit "in je bioscoopstoel". Maar vervolgens draag je die toch bij je. Misschien de volgende keer iets met rekken en kleerhangers beneden neer zetten zodat je je jas op kunt hangen?
Dit was het originele schema en hier had ik mijn planning op ingericht;
Foyer 09:00 → 60 min Ontvangst met koffie en thee
Foyer 10:45 → 30 min Pauze
Foyer 12:00 → 60 min Lunch
Foyer 14:45 → 30 min Pauze
Café 17:00 → 30 min Afsluiting & Borrel
Zaal 7
(X) 10:00 → 45 min The art of getting 💩 done Henry Been
(O) 11:15 → 45 min Cross-platform development with .NET MAUI Anjuli Jhakry
(O) 13:00 → 45 min API FOMO: REST, gRPC or GraphQL? Roland Guijt
(X) 14:00 → 45 min What is new in .NET and C#? Johnny Hooyberghs
(X) 15:15 → 45 min Nullable Reference Types: It's Actually About Non-Nullable Reference Types Shawn Wildermuth
(X) 16:15 → 45 min 20 Years of software development, what could possibly go wrong? Eduard Keilholz, Sander Molenkamp
Zaal 8
(X) 11:15 → 45 min Infrastructure from Code: The Next Generation of Cloud Management Erwin Staal
(O) 13:00 → 45 min A Season for Speed: Turning Puzzles into C# Performance Wins Michaël Hompus
(O) 14:00 → 45 min Using GenAI on and inside your code, what could possibly go wrong? Niels Tanis
(O) 15:15 → 45 min Better architecture without architects Geert van der Cruijsen
Zaal 9
(O) 11:15 → 45 min AI-Powered Pool met Azure Computer Vision Sjoerd Nijhof
(-) 13:00 → 45 min Prompt Injection Attacks: Understanding and Mitigating Risks in LLM-Powered Web Apps Jorrik Klijnsma
(X) 13.00 → 45 min A Season for Speed: Turning puzzles into C# performance wins Michaël Hompus
(O) 14:00 → 45 min The best ways to use the latest OpenAPI features in .NET 9! Sander ten Brinke
(O) 15:15 → 45 min What my pet python taught me about Data Lakes on Azure Lisa Hoving