ndepend: bouw je spaghetti-code of zit er structuur in?

Ingediend door Dirk Hornstra op 25-aug-2021 19:44

In podcast 163 heeft Scott Hanselman een gesprek met Patrick Smacchia over metrieken (link). Ik hoor bij de "bouwers" en ik probeer dat "zo netjes mogelijk" te doen. Met de collega's hebben we niet voor niets "Clean Code" van uncle Bob behandeld. We hebben een bepaalde structuur hoe we zaken opzetten. Maar ik heb bij een eigen project, waar ik de basis van iemand anders gebruikt heb, wat in de loop van de tijd uitgegroeid is tot een groot pakket, het idee dat er redelijk wat wildgroei ontstaan is. Kun je zaken nog vinden? Heeft het nog een logische structuur?

Wij werken met .NET en het voordeel daarvan is dat je met nuget-bibliotheken kunt werken. Heeft iemand een module gemaakt voor het maken en verwerken van JSON (Newtonsoft JSON, Microsoft nu zelf ook met System.Text.Json), dan gebruik je dat, want dat ga je niet allemaal zelf bouwen. Hetzelfde geldt voor een ORM, het koppelen van database-objecten met objecten in je code, gebruik de Automapper en je kunt door. En zo gebruik je steeds meer "externe bronnen" om jouw code werkend te krijgen. Maar dat geeft je dus ook verplichtingen, want naast het feit dat er fouten/bugs/security-gaten in jouw code kunnen zitten, kan dat ook in die externe code zitten. Dus je moet niet alleen je eigen code up-to-date houden, maar ook die "externe" code regelmatig bijwerken.

Dit is niet alleen voorbehouden aan .NET (C# e.d.), maar ook aan PHP-projecten. Als je een Wordpress-website hebt, kijk eens hoeveel plug-ins je gebruikt. Standaard is Akismet geïnstalleerd. jQuery wordt in de sjablonen vaak nog standaard toegevoegd. Ik vermoed dat dit eigenlijk wel voor alle programmeertalen/pakketten geldt. Je kunt niet alles zelf maken, dus als iemand anders het al uitgewerkt heeft, waarom zou je het niet gebruiken?

Maar goed, terug naar .NET. In die uitzending met Scott werd één tool genoemd: ndepend (website). Op de website staat een animerende afbeelding met wat gegevens. Het totaal aantal coderegels is "leuk om te zien" en kan een indicatie geven over de complexiteit van het project, maar het hoeft niet veel te zeggen. Als je een goede verdeling met classes, zaken verdeeld over meerdere bestanden (zoals je dat met partial classes kunt doen), dan lijkt het meer, maar het hoeft daardoor niet ingewikkelder te zijn dan een project met minder code.

Je ziet de coverage, dus welk deel van je code getest wordt. Dat is wel een goede indicatie. Als er heel veel "simpele dingen in code gebeuren", die hoef je niet te testen, maar als er kritische zaken zijn die goed moeten gaan, dan moet je daar ook testen voor hebben. Je ziet een "graph" met afhankelijkheden, welke classes zijn afhankelijk van elkaar? Als er heel veel afhankelijkheden zijn, mogelijk ook nog circulaire afhankelijkheden (dus class A heeft een object van type B, die objecten van type C heeft die weer objecten van type A gebruikt), dan maak je jouw code gevoelig voor fouten bij aanpassingen. Ook zie je "debt", voor zover ik het kan zien is dat een indicatie dat je iets op een "makkelijke manier" heb opgelost, het niet duurzaam is en je later waarschijnlijk tegen grenzen aan gaat lopen en de boel moet ombouwen/refactoren.

Op de site kun je een trial-versie van 14 dagen downloaden. Als je een betaalde versie wilt kopen, dat kost je 400 euro (voor 1 jaar voor de developer editie). Zo te zien moet je dus elk jaar betalen, als je het op een build-machine installeert ben je het dubbele kwijt. De vraag is dus of de tool zoveel toevoegt dat je die prijs ervoor wilt betalen. Op deze pagina kun je duidelijke screenshots zien van  wat het pakket te bieden heeft: link.

Het pakket kan zeker wat bieden. Als je een heel groot project hebt, misschien met meerdere mensen aan werkt, weet jij nog waar wat staat? Dat blok code wat niet meer uitgevoerd wordt, omdat een bepaalde controle nu altijd 100% "false" terug geeft, jij hebt geen idee. Dit pakket wel, die zegt: "dat is dode code". En dode code moet je verwijderen, want het vertroebelt je beeld op het totale project.

Ook zie ik iets van "rapportage". En dat is nog een extra motivatie om het project te gebruiken. Het is eigenlijk best wel vreemd dat je websites, web-applicaties en allemaal andere software maakt voor je klanten en dat ze eigenlijk allemaal op je "blauwe ogen" vertrouwen dat je goede software oplevert. Wat weet zo'n klant ervan? Helemaal niets. Ze zien alleen de "buitenkant" en dat werkt allemaal perfect (of niet, maar dan heb je vast ook geen tevreden klant(en)...). Maar het kan best zijn dat er modules gebouwd zijn door stagiairs of afstudeerders, die hun diploma nog niet gehaald hebben en ook nog niet die x aantal jaar ervaring gehad hebben waarbij ze een aantal keer gestruikeld zijn en weten: dit moet ik niet in code doen, want dit levert problemen op.

Als je naar het ziekenhuis gaat en een chirurg snijdt je galblaas eruit, dan weet je dat hij/zij de papieren en vaardigheden heeft om dit te kunnen en mogen doen. Hetzelfde geldt voor je bakker en slager die aan hun muren de certificaten en diploma's hebben van keuringen, waarbij hun suikerbrood of leverworst uitgeroepen zijn tot "lekkerste hapje van 2020". Maar de IT-branche blijft wat dat betreft nog wel een beetje in de wild-west / cowboy - sferen hangen. Een verkoper met een goed praatje, redelijke prijzen, ontwerpen die er goed uit zien en je zet je krabbel. ISO-certificering kan hier bij helpen, maar ik heb hier dus nog wel 2 aanbevelingen;

Bij het vorige bedrijf waar ik werkte, waren een aantal klanten die werkten met Escrow. Hierbij geef je als IT-bedrijf jouw software aan de Escrow-organisatie. Gaat het IT-bedrijf failliet, dan is het bedrijf niet hun website/applicaties kwijt, maar is de broncode nog in eigen bezit en kan het ergens anders onder gebracht worden. De continuïteit van jouw bedrijf wordt dus niet afhankelijk van het feit of je IT-partner wel of niet financieel gezond is.

En als ik een bedrijf was met een grote website/web-applicatie wat voor het bedrijf belangrijk is, dan zou ik vragen om een rapport met een overzicht van de onderliggende code. Is deze veilig? Is het "goed gebouwd"? Zoals je auto regelmatig een APK keuring krijgt en je een bevestiging krijgt dat je veilig je kilometers kunt maken (of niet!), zo zou je dit ook een jaarlijks terugkerende actie kunnen maken. Met hierbij de opmerkingen dat je als klant wel voor het rapport moet betalen. Het bedrijf moet hier acties voor doen (en het is ook redelijk dat een dergelijke tool als ndepend doorberekend wordt aan de klanten). Het is een investering, maar zorgt ook voor een beter product. Hetzelfde geldt voor de bevindingen die hieruit voortvloeien, als er zaken aangepast moeten worden, testen moeten uitgebreid worden, afhankelijkheden moeten verminderd worden, het IT-bedrijf kan dat doen, maar ook die uren zullen betaald moeten worden. De medewerker of medewerkers die dit gaan bouwen kosten geld, of ze nu bezig zijn met nieuwbouw, onderzoek of onderhoud. Nog (te) vaak denken bedrijven dat er "even" iets aangepast moet worden en dat het "heel simpel is". Wat aan de buitenkant simpel lijkt, kan onder de motorkap ingrijpende aanpassingen vergen, bij een goede oplevering moet een aanpassing via een OTAP-straat gecontroleerd en gevalideerd worden. Dat kost tijd, medewerker(s) die dit uit moeten voeren en die hebben een uurtarief, zo simpel is het.

Goed, eerst de 14-dagen versie van ndepend zelf maar eens testen. Ik ga die niet installeren op mijn "werk-pc", op de site van Microsoft een Windows 10 Enterprise virtual machine gedownload (20 GB, inclusief Visual Studio 2019) die geldig is tot 12 september: link. Hier de versie voor Virtual Box gedownload. Daarna de 14-dagen versie gedownload en geïnstalleerd: link. Vervolgens mijn project van het werk en een eigen project (mijn Fitbit-connector applicatie) gevalideerd.

Op de download-pagina het zip-bestand gedownload (18.5 MB), vervolgens die uitgepakt. In de map staat een README bestand. Daarin staat dat je een aantal applicaties hebt. Zo heb je de installer voor Visual Studio: NDepend.VisualStudioExtension.Installer.exe. Maar ook VisualNDepend.exe, een losse applicatie waarbij je Visual Studio niet hoeft op te starten. Ook NDepend.Console.exe, een command-line executable, waarmee je rapportages kunt maken. Documentatie hierover kun je hier vinden: link. En als klap op de vuurpijl NDepend.PowerTools.exe, een aantal kleine programma's die open-source zijn en de werking van de API van Ndepend tonen. Broncode daarvan wordt ook meteen meegeleverd en je kunt hier de documentatie lezen: link.

Ik begin met de VisualNDepend, dan hoef ik Visual Studio niet te laden. Hierin open ik het project van TRES wat we voor " intern gebruik"  gebouwd hebben. Het dashboard zegt dat er 138.664 IL instructies zijn. Dan de statistieken, van de "Quality Gates" krijg ik 8 items die "passed"  zijn, maar 3 failed items. Bij rules zijn 100 OK, maar 9 zijn critical en 54 zijn "violated". Bij de "Issues"  heb je 129 high, 614 medium en 166 low. Ok, kijken wat de oorzaken zijn;

Voorkom dat types "te groot zijn" (3 stuks),  voorkom dat methodes te groot en complex zijn (6 stuks), voorkom functies met teveel parameters (3 stuks), namespaces die van elkaar afhankelijk zijn (23 stuks), voorkom statische velden die niet read-only zijn (13 stuks), de naam van een interface zou met een I moeten beginnen (1 stuks), attribute-class namen zouden moeten eindigen met Attribute (2 stuks), voorkom dat je verschillende types met dezelfde naam hebt (8 stuks), roep niet zelf de Dispose aan in een class (1 stuks). 

Als ik de 54 regels bekijk die ik overtreden heb, dan krijg je een lijstje. Als je class niet public is, declareer je functies dan ook niet public (77 stuks). Als je een class hebt, declareer de constructor. Of maak er een static class van (57 stuks). Mogelijk 16 "dode types". Als je een class met disposable velden hebt, dan moet die class ook disposable zijn, 14 stuks. 

En zo heb je nog een hele lijst. Classes die geen afgeleide classes hebben zouden "sealed"  moeten zijn. De UI-laag die database-acties doet, je moet dat niet willen. Duidelijk is dat er veel te verbeteren is. Hierna mijn eigen "fitbit-applicatie" onder de loep genomen. Quality Gates, 1 fail, Rules, 7 critical, 27 violated, Isues, 35 high, 119 medium, 22 low. Het aantal issues ligt een stuk lager, maar het project is dan ook een stuk kleiner/minder complex.

Uiteindelijk ga je doorklikken en wordt Visual Studio geopend, het integreren in Visual Studio lijkt dus handiger/sneller te werken. De installer uitgevoerd en mijn eigen project geopend. Hierna in de menubalk via Extensions - nDepend - en hier de menu-optie aanklikken om nDepend aan dit project toe te voegen. Daarna heb je allemaal opties hier beschikbaar. Gekozen voor "Issues and Depth". Hier kun je op zaken doorklikken en de aanpassingen doorvoeren, mocht je dat willen. Wel zie ik bijvoorbeeld de {get; set;}-acties die zorgen voor lowercase functienamen en daardoor een melding geven. Niet elke melding is dus iets waar je wat mee moet doen.

We gebruikten vroeger altijd FxCop. Daarin stonden bepaalde regels die je code in een bepaald stramien drukten. Ik zie dat dit uitgefaseerd is, link. Ik krijg dit zo snel niet werkend.

NDepend is een prima tool. Nu gebruiken we waar ik werk ook "Resharper". Tijdens development krijg je al tips e.d., maar de "rest" had ik nog niet bekeken. Ik ben vandaag via Extensions - Resharper - Inspect - Code Issues in Solution gaan kijken wat dit mij oplevert. Nou, een hele hoop. Je kunt filteren op bestandstype (misschien boeit css en javascript je niet en wil je alleen de C# code valideren), ik krijg dan deze lijst:

  • C# Compiler Errors; 59;
  • Common Practices and Code Improvements; 1.612;
  • Compiler Warnings; 43;
  • Constrains Violations; 1.480;
  • Css Errors; 11;
  • Formatting; 1;
  • Javascript Errors; 23;
  • Language Usage Opportunities; 121;
  • Potential Code Quality Issues; 13.224;
  • Redundancies in Code; 816;
  • Redundancies in Symbol Declarations; 1.035;
  • Spelling Issues; 70.312;
  • Strict Mode Violations; 3;
  • Syntaxt Style; 1.013;


Ik gebruikte nog heel veel LinqQuery.Where(rec => rec.voorwaarden).FirstOrDefault() terwijl je al lange tijd dit kunt doen: LinqQuery.FirstOrDefault(rec => rec.voorwaarden).
Er waren wat if - else controles, waarbij de "else" overbodig was, omdat je in de if al via een return uit de functie sprong. Dus die else { ... } er omheen kan weg.

Ook kwam ik ergens een token tegen wat ik om de werking te testen "even" fixed ingesteld had. Dat had ik weg willen halen, maar stond er nog in, in het verleden ingecheckt. De validatie geeft (terecht) aan dat de parameter in de functie-aanroep al overschreven wordt voordat de waarde wordt uitgelezen. En in Razor-templates gebruikte ik classes die verwijderd waren en dus een server-fout zouden geven als je die aan zou roepen. Resharper kun je bij Jetbrains kopen, ook 400 euro per jaar (voor 1 developer): link.

Mijn advies is dus om een tool te gebruiken, welke, dat moet je zelf maar beoordelen. Resharper kun je als 30-dagen trial versie downloaden, nDepend heeft een trial voor 14 dagen. Want toegevoegde waarde heeft het zeker, het controleert je code, het valideert syntax, geeft je adviezen.