Mediazone · Blog

SonarQube en MCP: De Complete Gids voor Code Kwaliteit

· Kanaalduiker

Deel 1: SonarQube Uitgelegd voor Iedereen

De Metafoor van de Bouwkeuring

Stel je voor dat je een huis bouwt. Je kunt twee dingen doen. Je kunt bouwen totdat het klaar is en dan een inspecteur laten komen die zegt "dit moet allemaal opnieuw want het voldoet niet aan de brandveiligheidseisen." Of je kunt elke dag een inspecteur laten meekijken die zegt "die draad moet je anders leggen" voordat je de muur dichtmaakt.

SonarQube is die dagelijkse inspecteur, maar dan voor code. Het kijkt naar elke regel die je schrijft en zegt of het veilig is, of het onderhoudbaar is, en of het werkt zoals verwacht.

De Drie Pijlers van Code Kwaliteit

SonarQube kijkt naar drie dingen. Ten eerste bugs, dat zijn fouten die ervoor zorgen dat je programma crasht of verkeerde resultaten geeft. Ten tweede vulnerabilities, dat zijn beveiligingslekken waardoor hackers kunnen binnenkomen. Ten derde code smells, dat zijn stukken code die technisch werken maar moeilijk te onderhouden zijn.

In een gemiddelde enterprise codebase vindt SonarQube honderden tot duizenden van zulke issues. Dat klinkt als veel, maar het mooie is dat je nu weet waar ze zitten in plaats van er in productie achter te komen.


Deel 2: Typische Voorbeelden uit de Praktijk

Voorbeeld 1: De Vergeten Variabele

Een van de meest voorkomende issues is de ongebruikte variabele. De code ziet er dan ongeveer zo uit:

public class OrderController : ControllerBase
{
    private readonly IOrderService _orderService;
    private readonly ILogger<OrderController> _logger;
    private readonly IConfiguration _configuration;  // <-- WORDT NOOIT GEBRUIKT
    private readonly string _apiKey;
    // ... meer velden
}

SonarQube markeert dit als CRITICAL met de boodschap "Remove this unread private field '_configuration' or refactor the code to use its value."

Waarom is dit belangrijk? Op het eerste gezicht lijkt een ongebruikte variabele onschuldig. Maar het vertelt een verhaal. Ofwel is de developer vergeten om de configuratie te gebruiken en mist er functionaliteit, ofwel was er ooit functionaliteit die is verwijderd maar de variabele is blijven hangen. In beide gevallen maakt het de code verwarrend voor de volgende developer die ernaar kijkt.

Dit probleem komt in vrijwel elke codebase voor, vaak tientallen keren. Het suggereert een patroon waar dependencies worden geïnjecteerd maar niet gebruikt, mogelijk door refactoring die niet volledig is afgerond.

Voorbeeld 2: De God Method

Een ander veelvoorkomend probleem is de methode met extreme Cognitive Complexity. SonarQube staat maximaal 15 toe, maar in de praktijk vind je methodes met complexiteit van 30, 50, of zelfs meer dan 100.

Cognitive Complexity is een maat voor hoe moeilijk code is om te begrijpen. Elke if-statement, elke loop, elke geneste conditie voegt complexiteit toe. Een methode met complexiteit boven de 100 betekent dat er zoveel vertakkingen en beslissingen in zitten dat geen mens het in één keer kan bevatten.

Dit is niet alleen een esthetisch probleem. Complexe code is moeilijker te testen omdat er zoveel paden doorheen lopen. Het is moeilijker te debuggen omdat je niet kunt voorspellen welk pad de code neemt. En het is moeilijker aan te passen omdat elke wijziging onverwachte bijeffecten kan hebben.

De oplossing is om de methode op te splitsen in kleinere, gefocuste stukken. In plaats van één methode die alles doet, krijg je meerdere methoden die elk één ding goed doen. Dit heet het Single Responsibility Principle.

Voorbeeld 3: Te Veel Dependencies

Een derde veelvoorkomend patroon is de constructor met te veel parameters:

public class ReportGeneratorService(
    ILogger<ReportGeneratorService> logger,
    IDatabaseConnection databaseConnection,
    IEmailService emailService,
    IPdfGenerator pdfGenerator,
    IStorageService storageService,
    INotificationService notificationService,
    IImageOptimizer imageOptimizer,
    ICacheService cacheService,
    IConfiguration configuration,
    HttpClient httpClient,
    IMetricsService metricsService)

SonarQube staat maximaal 7 parameters toe en markeert dit als een probleem.

Dit is een teken van wat we een "God Class" noemen. Een class die te veel verantwoordelijkheden heeft. De oplossing is om verantwoordelijkheden te scheiden. Misschien moet de PDF generatie een aparte service zijn. Misschien kan de email en notificatie functionaliteit gecombineerd worden in een NotificationService.

Voorbeeld 4: De Parameter Naam Mismatch

Een subtielere issue is wanneer een parameter genaamd "username" heeft maar de interface definieert deze als "email". SonarQube zegt "Rename parameter 'username' to 'email' to match the interface declaration."

Dit lijkt klein maar kan grote gevolgen hebben. Als iemand de interface leest, verwacht die dat er een email wordt meegegeven. Als die persoon dan de implementatie bekijkt, ziet die een username. Zijn dit dezelfde dingen? Is het een email in username formaat? Of is het een echte username die later naar een email wordt vertaald?

Deze ambiguiteit leidt tot bugs. Iemand roept de methode aan met een username terwijl er een email verwacht wordt, of andersom.


Deel 3: Branches, Pull Requests en Decoratie

Wat is een Branch?

In de metafoor van een boom is de stam je productie code. Als je direct aan de stam gaat zagen, valt de boom om en liggen je gebruikers plat. Daarom werk je aan een tak, een branch.

Een branch is een complete kopie van je codebase waar je veilig kunt experimenteren. Je kunt dingen kapot maken, rare ideeën uitproberen, en het maakt niet uit want niemand anders heeft er last van.

Als je een nieuwe feature bouwt, maak je een branch aan met bijvoorbeeld de naam "feature/user-authentication". Je doet al je werk daar, en als het klaar en getest is, voeg je het samen met main of master.

Het Probleem van de Gratis Versie

In de gratis Community Edition van SonarQube kun je alleen de main branch analyseren. Je doet je werk op een feature branch, je voegt het samen met main, SonarQube scant het, en dan pas zie je de problemen.

Maar nu zit de slechte code al in main. Je moet ofwel een nieuwe commit maken om het te fixen, wat je git history vervuilt, ofwel je accepteert de problemen en gaat door, wat technische schuld opbouwt.

Met Branch Analysis in de betaalde versie wordt elke branch apart gescand. Je zit nog op je feature branch en SonarQube zegt al "op regel 47 heb je een security probleem." Je fixt het voordat het ooit main bereikt.

Pull Request Decoratie Uitgelegd

Een Pull Request is het formele verzoek om je branch samen te voegen met main. Je zegt tegen je team "ik heb iets gebouwd, kijk er eens naar." In GitHub of Azure DevOps krijg je dan een pagina waar je alle wijzigingen ziet en waar teamleden commentaar kunnen geven.

Pull Request Decoration betekent dat SonarQube automatisch commentaar plaatst op die pagina. Niet een algemeen rapport ergens in een hoekje, maar inline commentaar op de exacte regels waar problemen zitten.

Stel je voor dat je een Pull Request opent voor een OrderController wijziging. Binnen een minuut verschijnt er een commentaar van SonarQube op regel 23 die zegt "deze _configuration variabele wordt niet gebruikt." Je teamgenoot hoeft dit niet zelf te ontdekken. De machine heeft het al gevonden.

Dit verandert de dynamiek van code reviews fundamenteel. Zonder decoratie moet een senior developer elke regel handmatig doorlopen om dit soort problemen te vinden. Met decoratie doet de machine het saaie werk en kan de senior zich focussen op architectuur, business logica, en het grotere plaatje.

Er is ook een psychologisch effect. Als je weet dat SonarQube publiekelijk op je PR gaat reageren, ga je extra opletten voordat je iets indient. Niet omdat je gestraft wordt, maar omdat niemand graag die rode commentaren ziet waar het hele team bij is.


Deel 4: Security Rapporten en Compliance

Wat is OWASP?

OWASP staat voor Open Web Application Security Project. Het is een internationale non-profit organisatie die al meer dan twintig jaar onderzoek doet naar hoe webapplicaties worden gehackt. Ze publiceren de beroemde OWASP Top 10, een lijst van de tien meest voorkomende en gevaarlijke security problemen in webapplicaties.

De huidige top 10 bevat dingen als Broken Access Control, waar gebruikers toegang krijgen tot data die ze niet mogen zien. Cryptographic Failures, waar gevoelige data niet goed versleuteld is. Injection, waar aanvallers kwaadaardige code kunnen invoeren via input velden. En Security Misconfiguration, waar standaard wachtwoorden niet zijn veranderd of debug modes aan staan in productie.

Deze lijst is niet zomaar een mening. Het is gebaseerd op analyse van duizenden echte hacks en security incidenten. Als je applicatie kwetsbaar is voor een OWASP Top 10 item, dan is het een kwestie van tijd voordat iemand het uitbuit.

Wat is SANS?

SANS Institute is een andere grote speler in de security wereld. Waar OWASP zich focust op webapplicaties, heeft SANS een bredere scope. Ze trainen security professionals, ze doen incident response bij grote hacks, en ze houden bij welke aanvallen er in de echte wereld plaatsvinden.

Hun CWE Top 25, de Common Weakness Enumeration, is vergelijkbaar met de OWASP Top 10 maar dan voor alle software, niet alleen webapplicaties. Het bevat zaken als buffer overflows, integer overflows, en race conditions die vooral in systeemprogrammering voorkomen.

Waarom Rapporten Belangrijk Zijn

In de gratis versie van SonarQube krijg je wel security waarschuwingen. Je ziet "mogelijke SQL injection" of "ontbrekende input validatie." Nuttig, maar niet gestructureerd.

De betaalde versie genereert complete rapporten die exact mappen op de OWASP en SANS categorieën. Je krijgt een document dat zegt "OWASP A03 Injection: gevonden op 3 locaties" met precieze file namen en regelnummers.

Dit is cruciaal voor compliance. Als een auditor langskomt, vraagt die niet "heb je aan security gedacht?" maar "ben je OWASP compliant?" Als je een contract wilt met een bank, zorginstelling of overheidsorganisatie, moeten je systemen aantoonbaar voldoen aan deze standaarden.

Het verandert ook hoe je prioriteert. In plaats van een overweldigende lijst van honderden waarschuwingen, krijg je een gestructureerd overzicht. "We hebben nul kritieke A01 problemen, twee medium A03 problemen, en vijf lage A07 problemen." Je weet precies waar je staat en wat prioriteit moet krijgen.

Voor managers en stakeholders is dit communicatie-goud. Zeg tegen een CEO dat je "47 code smells" hebt en je krijgt een lege blik. Zeg dat je "94% OWASP compliant bent en de resterende 6% staat gepland voor volgende sprint" en iedereen begrijpt het.


Deel 5: MCP - Het Model Context Protocol Volledig Uitgelegd

De Fundamentele Vraag: Hoe Praat een AI met de Buitenwereld?

Laten we beginnen bij het begin. Een AI model zoals Claude is getraind op tekst. Het kan tekst lezen, het kan tekst schrijven, en dat is het. Als je Claude vraagt "wat staat er in mijn database?", dan kan Claude dat niet zomaar opzoeken. Claude heeft geen ogen om naar je scherm te kijken, geen handen om op je toetsenbord te typen, en geen netwerk verbinding om met je database te praten.

Dit is waar MCP om de hoek komt kijken. MCP staat voor Model Context Protocol. Het is een standaard, ontwikkeld door Anthropic, die beschrijft hoe AI modellen kunnen communiceren met externe systemen. Denk aan het als een universele taal die AI's en tools kunnen spreken om samen te werken.

De Anatomie van een MCP Server

Een MCP server is een programma dat ergens draait en wacht op verzoeken van AI assistenten. Het heeft drie hoofdcomponenten.

Ten eerste de Transport laag. Dit bepaalt hoe berichten worden verstuurd. Meestal is dit via standard input en output, wat betekent dat de MCP server als een subprocess draait en communiceert via tekst streams. Dit is simpel, betrouwbaar, en werkt overal.

Ten tweede de Protocol laag. Dit definieert het formaat van de berichten. Een verzoek heeft een bepaalde structuur, een antwoord heeft een bepaalde structuur, en beide partijen moeten zich aan deze structuur houden. Het is vergelijkbaar met hoe HTTP werkt voor websites, maar dan specifiek ontworpen voor AI interactie.

Ten derde de Implementatie laag. Dit is de daadwerkelijke code die iets nuttigs doet. In het geval van de SonarQube MCP server is dit code die verbinding maakt met de SonarQube API, queries uitvoert, en resultaten teruggeeft.

Het Flow Diagram: Van Vraag tot Antwoord

Laten we stap voor stap door een typische interactie lopen.

┌─────────────────────────────────────────────────────────────────────────────┐
│                        MCP COMMUNICATIE FLOW                                │
└─────────────────────────────────────────────────────────────────────────────┘

     GEBRUIKER                 CLAUDE                  MCP SERVER              SONARQUBE
         │                        │                        │                        │
         │  "Wat zijn de          │                        │                        │
         │   SonarQube issues?"   │                        │                        │
         │───────────────────────>│                        │                        │
         │                        │                        │                        │
         │                        │  Tool Call:            │                        │
         │                        │  search_sonar_issues   │                        │
         │                        │───────────────────────>│                        │
         │                        │                        │                        │
         │                        │                        │  HTTP GET              │
         │                        │                        │  /api/issues/search    │
         │                        │                        │───────────────────────>│
         │                        │                        │                        │
         │                        │                        │  JSON Response         │
         │                        │                        │  {issues: [...]}       │
         │                        │                        │<───────────────────────│
         │                        │                        │                        │
         │                        │  Tool Result:          │                        │
         │                        │  {issues: [...]}       │                        │
         │                        │<───────────────────────│                        │
         │                        │                        │                        │
         │  "Er zijn 71 kritieke  │                        │                        │
         │   issues gevonden..."  │                        │                        │
         │<───────────────────────│                        │                        │
         │                        │                        │                        │

Eerst stelt de gebruiker een vraag in natuurlijke taal. "Wat zijn de SonarQube issues in mijn project?" Deze vraag komt bij Claude terecht.

Claude analyseert de vraag en herkent dat dit een vraag is die niet beantwoord kan worden met alleen kennis. Er is externe data nodig. Claude kijkt welke tools beschikbaar zijn en ziet dat er een SonarQube MCP server is met een functie genaamd "search_sonar_issues".

Claude roept deze tool aan met de juiste parameters. In dit geval het project naam en eventueel filters voor severity. Dit verzoek gaat naar de MCP server.

De MCP server ontvangt het verzoek en vertaalt het naar een HTTP call naar de SonarQube API. De server weet waar SonarQube draait, hoe de authenticatie werkt, en welke endpoints beschikbaar zijn.

SonarQube verwerkt de query en stuurt een JSON response terug met alle gevonden issues. Elk issue bevat informatie zoals het bestand, de regel, de severity, en een beschrijving van het probleem.

De MCP server ontvangt deze response en formatteert het naar het MCP protocol formaat. Dit gaat terug naar Claude.

Claude ontvangt de data en kan nu een menselijk leesbaar antwoord formuleren. "Er zijn 71 kritieke issues gevonden. De meest voorkomende zijn ongebruikte variabelen en te complexe methodes."

Waarom Niet Gewoon Direct de API Aanroepen?

Je zou kunnen denken, waarom al deze complexiteit? Waarom laat je Claude niet gewoon direct HTTP calls maken naar SonarQube?

Het antwoord zit in veiligheid en abstractie.

Veiligheid eerst. Als Claude direct HTTP calls zou maken, zou het potentieel overal naartoe kunnen connecten. Naar je interne servers, naar externe services, overal. De MCP server fungeert als een poortwachter. Het definieert precies welke operaties toegestaan zijn en welke niet. Je kunt een MCP server configureren om alleen read operaties toe te staan, of alleen bepaalde projecten, of alleen tijdens kantooruren.

Dan abstractie. SonarQube heeft een complexe API met tientallen endpoints, authenticatie tokens, pagination, en allerlei edge cases. De MCP server abstraheert dit allemaal weg. Claude hoeft niet te weten hoe SonarQube pagination werkt. Claude vraagt gewoon "geef me alle issues" en de MCP server handelt de details af.

De Architectuur in Detail

┌─────────────────────────────────────────────────────────────────────────────┐
│                         SYSTEEM ARCHITECTUUR                                │
└─────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────┐
│                              DEVELOPER MACHINE                               │
│                                                                              │
│  ┌────────────────┐     ┌────────────────┐     ┌────────────────────────┐   │
│  │                │     │                │     │                        │   │
│  │   VS Code +    │────>│  Claude Code   │────>│    MCP Server          │   │
│  │   Claude Code  │<────│  Extension     │<────│    (SonarQube)         │   │
│  │                │     │                │     │                        │   │
│  └────────────────┘     └────────────────┘     └───────────┬────────────┘   │
│                                                            │                │
│                                                            │ HTTP/HTTPS     │
│                                                            │                │
│  ┌─────────────────────────────────────────────────────────▼────────────┐   │
│  │                        DOCKER CONTAINER                               │   │
│  │  ┌────────────────────────────────────────────────────────────────┐  │   │
│  │  │                    SonarQube Server                             │  │   │
│  │  │                                                                 │  │   │
│  │  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐ │  │   │
│  │  │  │   Web UI    │  │  REST API   │  │   Analysis Engine       │ │  │   │
│  │  │  │  :9000      │  │  /api/*     │  │   (Rules, Scanners)     │ │  │   │
│  │  │  └─────────────┘  └─────────────┘  └─────────────────────────┘ │  │   │
│  │  │                                                                 │  │   │
│  │  └────────────────────────────────────────────────────────────────┘  │   │
│  │                                    │                                  │   │
│  │                                    │                                  │   │
│  │  ┌─────────────────────────────────▼──────────────────────────────┐  │   │
│  │  │                    PostgreSQL Database                          │  │   │
│  │  │                    (Issues, Metrics, History)                   │  │   │
│  │  └────────────────────────────────────────────────────────────────┘  │   │
│  └───────────────────────────────────────────────────────────────────────┘   │
│                                                                              │
└──────────────────────────────────────────────────────────────────────────────┘

De gebruiker werkt in VS Code met de Claude Code extensie. Dit is de interface waar je je vragen typt en antwoorden ziet.

De Claude Code extensie communiceert met het Claude AI model. Dit is waar de intelligentie zit. Claude begrijpt je vraag, bepaalt welke tools nodig zijn, en formuleert het antwoord.

Als Claude data nodig heeft van SonarQube, stuurt het een verzoek naar de MCP server. De MCP server draait als een apart proces op je machine. Het is specifiek geconfigureerd om met jouw SonarQube installatie te praten.

De MCP server maakt HTTP calls naar de SonarQube server. In een typische setup draait SonarQube in een Docker container op poort 9000. De server heeft een web interface voor mensen en een REST API voor machines.

SonarQube slaat alle data op in een PostgreSQL database, ook in Docker. Hier zitten de scan resultaten, de history van issues over tijd, metrics, en configuratie.

MCP Hello World: Een Simpele Server Bouwen

Om te begrijpen hoe MCP werkt, bouwen we een minimale "Hello World" MCP server in TypeScript/Node.js. Dit voorbeeld laat de kernconcepten zien.

Stap 1: Project Setup

mkdir mcp-hello-world
cd mcp-hello-world
npm init -y
npm install @modelcontextprotocol/sdk

Stap 2: De Server Code (index.ts)

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

// Maak een nieuwe MCP server
const server = new Server(
  {
    name: "hello-world-server",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// Definieer beschikbare tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "say_hello",
        description: "Zegt hallo tegen een persoon",
        inputSchema: {
          type: "object",
          properties: {
            name: {
              type: "string",
              description: "De naam van de persoon",
            },
          },
          required: ["name"],
        },
      },
      {
        name: "get_time",
        description: "Geeft de huidige tijd terug",
        inputSchema: {
          type: "object",
          properties: {},
        },
      },
    ],
  };
});

// Implementeer de tool handlers
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  switch (name) {
    case "say_hello":
      return {
        content: [
          {
            type: "text",
            text: `Hallo, ${args?.name}! Welkom bij MCP! 👋`,
          },
        ],
      };

    case "get_time":
      return {
        content: [
          {
            type: "text",
            text: `De huidige tijd is: ${new Date().toLocaleString("nl-NL")}`,
          },
        ],
      };

    default:
      throw new Error(`Onbekende tool: ${name}`);
  }
});

// Start de server met stdio transport
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Hello World MCP server gestart!");
}

main().catch(console.error);

Stap 3: Configureer in Claude Code

Voeg dit toe aan je ~/.claude/claude_desktop_config.json:

{
  "mcpServers": {
    "hello-world": {
      "command": "npx",
      "args": ["ts-node", "/pad/naar/mcp-hello-world/index.ts"]
    }
  }
}

Stap 4: Test het!

Herstart Claude Code en vraag:

  • "Zeg hallo tegen Jan" → Server roept say_hello aan met name="Jan"
  • "Hoe laat is het?" → Server roept get_time aan

Wat gebeurt er onder de motorkap?

┌─────────────────────────────────────────────────────────────────────────────┐
│                    MCP HELLO WORLD FLOW                                      │
└─────────────────────────────────────────────────────────────────────────────┘

User: "Zeg hallo tegen Jan"
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLAUDE analyseert vraag:                                                     │
│ - Dit lijkt op een begroeting                                               │
│ - Ik heb een "say_hello" tool beschikbaar                                   │
│ - De tool verwacht een "name" parameter                                     │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ TOOL CALL via stdin:                                                         │
│ {                                                                            │
│   "method": "tools/call",                                                    │
│   "params": { "name": "say_hello", "arguments": { "name": "Jan" } }         │
│ }                                                                            │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ MCP SERVER verwerkt:                                                         │
│ - Ontvangt JSON via stdin                                                   │
│ - Roept say_hello handler aan                                               │
│ - Formatteert response                                                      │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ RESPONSE via stdout:                                                         │
│ { "content": [{ "type": "text", "text": "Hallo, Jan! Welkom bij MCP! 👋" }] │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
User ziet: "Hallo, Jan! Welkom bij MCP! 👋"

Dit simpele voorbeeld toont de drie kernconcepten van MCP:

  1. Tools definiëren - Via ListToolsRequestSchema
  2. Tools implementeren - Via CallToolRequestSchema
  3. Transport - Communicatie via stdin/stdout (StdioServerTransport)

Met deze basis kun je elke externe API, database, of service integreren met Claude!

De Tools die de MCP Server Biedt

De SonarQube MCP server biedt een verzameling tools die Claude kan gebruiken. Elke tool heeft een naam, een beschrijving, en parameters.

De search_sonar_issues tool zoekt naar issues in een project. Je kunt filteren op severity, op bestandsnaam, op rule type, en meer. Dit is de meest gebruikte tool.

De get_project_quality_gate_status tool vraagt de Quality Gate status op. Dit vertelt of het project voldoet aan de geconfigureerde kwaliteitseisen.

De search_my_sonarqube_projects tool lijst alle projecten op die beschikbaar zijn. Handig als je meerdere projecten hebt en wilt weten welke er zijn.

De show_rule tool geeft gedetailleerde informatie over een specifieke regel. Als je wilt weten waarom S4487 belangrijk is, vraag je deze tool om uitleg.

De get_component_measures tool haalt metrics op zoals code coverage, duplicatie percentage, en aantal regels code.

Een Praktijkvoorbeeld Stap voor Stap

Laten we een concreet voorbeeld doorlopen van wat er gebeurt als je vraagt "fix de ongebruikte variabelen in mijn project."

┌─────────────────────────────────────────────────────────────────────────────┐
│                    PRAKTIJKVOORBEELD: FIX ONGEBRUIKTE VARIABELEN            │
└─────────────────────────────────────────────────────────────────────────────┘

STAP 1: Gebruiker stelt vraag
─────────────────────────────────────────────────────────────────────────────
"Fix de ongebruikte variabelen in mijn project"
                    │
                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLAUDE ANALYSEERT:                                                          │
│ - Dit is een taak die actie vereist                                        │
│ - Ik moet eerst weten WELKE variabelen ongebruikt zijn                     │
│ - Daarvoor heb ik SonarQube data nodig                                     │
│ - Tool: search_sonar_issues met filter op regel S4487                      │
└─────────────────────────────────────────────────────────────────────────────┘
                    │
                    ▼
STAP 2: MCP Tool Call
─────────────────────────────────────────────────────────────────────────────
{
  "tool": "search_sonar_issues",
  "parameters": {
    "projects": ["my-project"],
    "rules": ["csharpsquid:S4487"]
  }
}
                    │
                    ▼
STAP 3: MCP Server verwerkt
─────────────────────────────────────────────────────────────────────────────
┌─────────────────────────────────────────────────────────────────────────────┐
│ MCP SERVER:                                                                 │
│ 1. Ontvangt verzoek                                                        │
│ 2. Bouwt SonarQube API URL:                                                │
│    http://localhost:9000/api/issues/search?projects=my-project             │
│    &rules=csharpsquid:S4487                                                │
│ 3. Voegt authenticatie header toe                                          │
│ 4. Maakt HTTP GET request                                                  │
│ 5. Parseert JSON response                                                  │
│ 6. Formatteert naar MCP protocol                                           │
└─────────────────────────────────────────────────────────────────────────────┘
                    │
                    ▼
STAP 4: SonarQube Response
─────────────────────────────────────────────────────────────────────────────
{
  "issues": [
    {
      "component": "OrderController.cs",
      "line": 23,
      "message": "Remove unused field '_configuration'",
      "severity": "CRITICAL"
    },
    {
      "component": "EmailService.cs",
      "line": 16,
      "message": "Remove unused field '_logger'",
      "severity": "CRITICAL"
    },
    // ... nog meer
  ]
}
                    │
                    ▼
STAP 5: Claude ontvangt data en plant acties
─────────────────────────────────────────────────────────────────────────────
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLAUDE PLANT:                                                               │
│ - 17 bestanden hebben ongebruikte variabelen                               │
│ - Per bestand: open file, zoek de regel, verwijder de variabele            │
│ - Check of er geen andere references zijn                                   │
│ - Verwijder ook uit constructor als nodig                                   │
└─────────────────────────────────────────────────────────────────────────────┘
                    │
                    ▼
STAP 6: Claude voert fixes uit
─────────────────────────────────────────────────────────────────────────────
Voor elk bestand:
  1. Read tool: lees het bestand
  2. Analyseer de code rondom de ongebruikte variabele
  3. Edit tool: verwijder de field declaratie
  4. Edit tool: verwijder de constructor parameter
  5. Edit tool: verwijder de assignment in constructor
                    │
                    ▼
STAP 7: Claude rapporteert
─────────────────────────────────────────────────────────────────────────────
"Ik heb 17 ongebruikte variabelen verwijderd uit de volgende bestanden:
 - OrderController.cs: _configuration verwijderd
 - EmailService.cs: _logger verwijderd
 - ..."

Dit voorbeeld laat zien hoe de verschillende lagen samenwerken. De gebruiker spreekt natuurlijke taal. Claude vertaalt dit naar tool calls. De MCP server vertaalt tool calls naar API requests. SonarQube levert de data. En Claude gebruikt die data om daadwerkelijke wijzigingen te maken in de code.

Waarom Dit Revolutionair Is

Voorheen moest een developer zelf naar de SonarQube interface navigeren, de issues doorklikken, elk bestand handmatig openen, de fix uitdenken, en de code aanpassen. Dit kostte uren voor een project met tientallen issues.

Nu zeg je "fix de ongebruikte variabelen" en een paar minuten later is het gedaan. De AI begrijpt wat je wilt, haalt de nodige informatie op, en voert de actie uit. Jij hoeft alleen te reviewen of het resultaat correct is.

Dit is geen toekomstmuziek. Dit is wat we vandaag al kunnen met de combinatie van SonarQube, MCP, en Claude Code.


Deel 6: De Technische Setup Uitgelegd

De Docker Compose Configuratie

Om SonarQube lokaal te draaien gebruik je Docker Compose. Hier is een typische configuratie:

version: "3.8"

services:
  sonarqube:
    image: sonarqube:community
    container_name: sonarqube
    depends_on:
      - sonarqube-db
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://sonarqube-db:5432/sonar
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: sonar
    volumes:
      - sonarqube_data:/opt/sonarqube/data
      - sonarqube_extensions:/opt/sonarqube/extensions
      - sonarqube_logs:/opt/sonarqube/logs
    ports:
      - "9000:9000"
    networks:
      - sonarnet

  sonarqube-db:
    image: postgres:15
    container_name: sonarqube-db
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
      POSTGRES_DB: sonar
    volumes:
      - postgresql:/var/lib/postgresql
      - postgresql_data:/var/lib/postgresql/data
    networks:
      - sonarnet

networks:
  sonarnet:
    driver: bridge

volumes:
  sonarqube_data:
  sonarqube_extensions:
  sonarqube_logs:
  postgresql:
  postgresql_data:

De image sonarqube:community is de officiële gratis versie van SonarQube. Het is een complete installatie met web interface, analysis engine, en REST API.

De depends_on zorgt ervoor dat de database eerst start voordat SonarQube opstart. SonarQube kan niet werken zonder database.

De environment variabelen configureren de database connectie. SonarQube moet weten waar de database is en hoe het moet authenticeren.

De volumes zorgen voor persistente opslag. Als je de container herstart, blijven je scan resultaten en configuratie behouden.

De port mapping 9000:9000 maakt de web interface bereikbaar op localhost:9000.

Het Scannen van een Project

Om een project te scannen gebruik je de dotnet sonarscanner (voor .NET projecten). Dit is een tool die je code analyseert en de resultaten naar SonarQube stuurt.

┌─────────────────────────────────────────────────────────────────────────────┐
│                         SCAN WORKFLOW                                        │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────┐
│ dotnet sonarscanner │
│ begin               │
│ /k:"project-key"    │─────────────────┐
│ /d:sonar.host.url=  │                 │
│  localhost:9000     │                 │
└─────────────────────┘                 │
                                        │
         Initialiseert scan context     │
         Configureert analyzers         │
                                        ▼
                            ┌───────────────────────┐
                            │                       │
                            │    dotnet build       │
                            │                       │
                            └───────────┬───────────┘
                                        │
         Tijdens build:                 │
         - Roslyn analyzers draaien     │
         - Issues worden verzameld      │
         - Metrics worden berekend      │
                                        ▼
                            ┌───────────────────────┐
                            │ dotnet sonarscanner   │
                            │ end                   │
                            └───────────┬───────────┘
                                        │
         Upload naar SonarQube:         │
         - Source code references       │
         - Gevonden issues              │
         - Code metrics                 │
         - Coverage data (indien        │
           beschikbaar)                 │
                                        ▼
                            ┌───────────────────────┐
                            │   SONARQUBE SERVER    │
                            │                       │
                            │ - Verwerkt upload     │
                            │ - Slaat op in DB      │
                            │ - Berekent trends     │
                            │ - Update Quality Gate │
                            └───────────────────────┘

De scanner werkt in drie fasen. Eerst begin, dan build, dan end.

In de begin fase wordt de scan context geïnitialiseerd. De scanner weet nu dat hij moet opletten tijdens de build en issues moet verzamelen.

Tijdens de build fase draaien de Roslyn analyzers mee. Dit zijn de tools die daadwerkelijk je code analyseren en problemen vinden. Ze zijn geïntegreerd in het .NET build proces.

In de end fase worden alle verzamelde gegevens geüpload naar de SonarQube server. De server verwerkt de data, slaat het op in de database, en berekent trends en Quality Gate status.

Het Scannen van React/Next.js Projecten

Voor JavaScript en TypeScript projecten (React, Next.js, Vue, Angular, etc.) gebruik je de sonar-scanner CLI in plaats van de dotnet sonarscanner. Dit kan op drie manieren:

Optie 1: Docker (aanbevolen voor eenmalige scans)

docker run --rm \
  -e SONAR_HOST_URL="http://host.docker.internal:9000" \
  -e SONAR_TOKEN="sqp_xxxxxxxxx" \
  -v "$(pwd):/usr/src" \
  sonarsource/sonar-scanner-cli \
  -Dsonar.projectKey=mijn-react-app \
  -Dsonar.sources=src \
  -Dsonar.exclusions="**/node_modules/**,**/*.test.ts,**/*.spec.ts"

Optie 2: NPM package (voor CI/CD integratie)

npm install -D sonarqube-scanner

# In package.json scripts:
"scripts": {
  "sonar": "sonar-scanner"
}

# Run met:
npm run sonar

Optie 3: sonar-project.properties bestand

Maak een sonar-project.properties in de root van je project:

sonar.projectKey=mijn-react-app
sonar.projectName=Mijn React App
sonar.projectVersion=1.0

sonar.sources=src
sonar.tests=src
sonar.test.inclusions=**/*.test.ts,**/*.test.tsx,**/*.spec.ts

sonar.exclusions=**/node_modules/**,**/*.test.ts,**/*.spec.ts,**/coverage/**

sonar.host.url=http://localhost:9000
sonar.token=sqp_xxxxxxxxx

# TypeScript specifiek
sonar.typescript.lcov.reportPaths=coverage/lcov.info

Dan run je simpelweg sonar-scanner (of de Docker variant zonder de -D parameters).

Workflow voor React/Next.js:

┌─────────────────────────────────────────────────────────────────────────────┐
│                    REACT/NEXT.JS SCAN WORKFLOW                              │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────┐
│ npm run build       │
│ npm run test --     │
│   --coverage        │────────────────────┐
└─────────────────────┘                    │
                                           │
         Genereert:                        │
         - coverage/lcov.info              │
         - ESLint output (optioneel)       │
                                           ▼
                            ┌───────────────────────┐
                            │                       │
                            │    sonar-scanner      │
                            │    (of Docker)        │
                            │                       │
                            └───────────┬───────────┘
                                        │
         Analyseert:                    │
         - TypeScript/JavaScript        │
         - JSX/TSX componenten          │
         - CSS/SCSS                     │
         - Test coverage                │
                                        ▼
                            ┌───────────────────────┐
                            │   SONARQUBE SERVER    │
                            │                       │
                            │ - Security issues     │
                            │ - Code smells         │
                            │ - Bugs                │
                            │ - Coverage rapport    │
                            └───────────────────────┘

Deel 7: De Gratis versus Betaalde Versie

Wat Krijg Je Gratis?

De SonarQube Community Edition is verrassend compleet. Je krijgt analyse voor meer dan 30 programmeertalen inclusief C#, JavaScript, Python, Java, en vele anderen. Je krijgt duizenden regels die zijn geschreven door security experts en senior developers. Je krijgt bug detectie, vulnerability detectie, en code smell detectie.

Je kunt onbeperkt projecten analyseren. Je kunt het lokaal draaien zonder cloud kosten. Je krijgt een web interface om resultaten te bekijken. En met de MCP integratie kun je het direct vanuit je IDE gebruiken met AI assistentie.

Voor een solo developer of klein team is dit meer dan genoeg om je code kwaliteit drastisch te verbeteren.

Wat Moet Je Voor Betalen?

Branch Analysis is betaald. Als je een team hebt waar meerdere developers tegelijk aan verschillende features werken, wil je dat elke branch apart wordt geanalyseerd.

Pull Request Decoration is betaald. Als je wilt dat SonarQube automatisch commentaar plaatst op je GitHub of Azure DevOps PRs, moet je betalen.

OWASP en SANS rapporten zijn betaald. Als je audits moet doorstaan of compliance moet aantonen, heb je deze gestructureerde rapporten nodig.

Portfolio management is betaald. Als je tientallen of honderden projecten hebt en een overzicht wilt van de code kwaliteit van je hele organisatie, is dat een betaalde feature.

De Verborgen Waarde van de MCP Integratie

Hier komt het interessante. Met de MCP integratie heb je eigenlijk een eigen vorm van "decoration" gecreëerd. In plaats van dat SonarQube commentaar plaatst op GitHub, heb je Claude die direct in je IDE de issues ophaalt en bespreekt.

Je kunt zeggen "fix alle ongebruikte variabelen" en Claude kan de lijst ophalen via MCP, elk bestand openen, de problematische regel vinden, en een fix voorstellen. Het is een andere workflow dan PR decoration, maar het resultaat is hetzelfde: snellere feedback loops en betere code.

De betaalde features zijn vooral waardevol in enterprise omgevingen met grote teams en strikte compliance eisen. Voor een klein team of solo developer kun je met de gratis versie plus MCP integratie al heel ver komen.


Deel 8: Hoe Dit Je Codebase Optimaliseert

De Traditionele Aanpak

Zonder continue code analyse ziet de workflow er zo uit. Een developer schrijft code. De developer doet een code review met een collega. De collega ziet de meeste bugs maar mist sommige subtiele issues. De code wordt gemerged. Maanden later crasht de applicatie in productie door een edge case die niemand had bedacht. Of erger, er is een security breach omdat er een SQL injection mogelijkheid zat in een input veld.

De SonarQube Aanpak

Met SonarQube in je CI/CD pipeline wordt elke push geanalyseerd. De pipeline kan zelfs geconfigureerd worden om te falen als er kritieke issues zijn. De developer krijgt feedback voordat de code in productie komt.

Maar er is nog steeds een vertraging. Je pusht code, de pipeline draait, SonarQube analyseert, en dan pas zie je de resultaten. Misschien vijf tot tien minuten later. Je bent al met iets anders bezig. De context switch om terug te gaan naar die code kost tijd en mentale energie.

De MCP Aanpak

Met de MCP integratie kun je vragen "analyseer deze code" terwijl je nog aan het schrijven bent. Je krijgt feedback binnen seconden, niet minuten. Je context switch is minimaal want je bent nog met dezelfde code bezig.

Je kunt ook proactief zijn. Voordat je een PR opent, vraag je "zijn er SonarQube issues in de files die ik heb gewijzigd?" Je fixt ze direct, je opent de PR, en die komt schoon binnen.

Vergelijking van Feedback Loops

┌─────────────────────────────────────────────────────────────────────────────┐
│                    FEEDBACK LOOP VERGELIJKING                               │
└─────────────────────────────────────────────────────────────────────────────┘

TRADITIONEEL (zonder SonarQube):
────────────────────────────────────────────────────────────────────────────
Schrijf code ──> Push ──> Code Review ──> Merge ──> Deploy ──> Bug in Productie
                                                                      │
Feedback tijd: DAGEN tot WEKEN ◄──────────────────────────────────────┘


MET SONARQUBE IN CI/CD:
────────────────────────────────────────────────────────────────────────────
Schrijf code ──> Push ──> CI Build ──> SonarQube Scan ──> Resultaten
                                                              │
Feedback tijd: 5-15 MINUTEN ◄─────────────────────────────────┘


MET MCP + CLAUDE CODE:
────────────────────────────────────────────────────────────────────────────
Schrijf code ──> "Check issues" ──> Resultaten + Fixes
                                          │
Feedback tijd: SECONDEN ◄─────────────────┘

Het verschil is dramatisch. Van dagen tot weken naar seconden. Dit is niet alleen tijdwinst, het is een fundamentele verandering in hoe je code schrijft. Je krijgt feedback terwijl de code nog vers in je geheugen zit. Je hoeft niet terug te keren naar code die je een week geleden schreef.

Een Concrete Workflow

Stel je voor dat je werkt aan een OrderController. Je voegt een nieuwe feature toe. Voordat je commit, vraag je Claude "check de SonarQube issues voor OrderController.cs."

Claude haalt de issues op via MCP. Hij ziet dat er een ongebruikte _configuration variabele is, een hardcoded URI, en wat herhaalde string literals. Claude legt uit wat elk probleem betekent en hoe je het kunt fixen.

Je maakt de fixes. Je vraagt opnieuw. Nu zijn de issues weg. Je commit met vertrouwen wetende dat de code schoon is.

Dit is de kracht van de integratie. Het is niet een apart systeem waar je naartoe moet navigeren. Het is ingebouwd in je development workflow.


Deel 9: Typische Issue Verdeling in Enterprise Codebases

Overzicht van Issues

Een gemiddeld enterprise project bevat honderden tot duizenden issues verdeeld over verschillende categorieën. Dit is normaal en niet iets om van te schrikken.

Typische verdeling:

┌─────────────────────────────────────────────────────────────────────────────┐
│                    TYPISCHE ISSUE VERDELING                                 │
└─────────────────────────────────────────────────────────────────────────────┘

SEVERITY:
──────────────────────────────────────────────────────────────────────────────
BLOCKER     ▓▓ (~1-5)
HIGH        ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (~50-100)
MEDIUM      ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (~200-400)
LOW         ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (~300-500)
INFO        ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (~200-400)

TOP REGELS (C#):
──────────────────────────────────────────────────────────────────────────────
S4487 (unused field)     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (zeer frequent)
S3776 (complexity)       ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (frequent)
S107 (too many params)   ▓▓▓▓ (occasioneel)
S1144 (unused setter)    ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (frequent)
S3459 (unassigned prop)  ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (frequent)

Waarom Quality Gate "OK" Kan Zijn Ondanks Veel Issues

De standaard Quality Gate in SonarQube kijkt naar nieuwe code, niet bestaande code. Zolang je geen nieuwe kritieke issues introduceert, blijft de gate groen.

Dit is een bewuste keuze in SonarQube. Het idee is dat je bestaande technische schuld niet in één keer kunt oplossen, maar je kunt wel voorkomen dat het erger wordt. Nieuwe code moet schoon zijn, oude code kun je geleidelijk verbeteren.


Deel 10: Out of the Box Denken

AI-Gestuurde Code Review Pipeline

Stel je een toekomst voor waar elke Pull Request automatisch wordt geanalyseerd door een combinatie van SonarQube en AI. SonarQube vindt de technische issues. De AI interpreteert ze, legt uit waarom ze belangrijk zijn, en stelt concrete fixes voor.

De PR krijgt automatisch een commentaar met een samenvatting. "Deze PR introduceert 2 nieuwe issues: een mogelijke null reference op regel 45 en een te complexe methode op regel 120. Klik hier voor voorgestelde fixes."

De developer klikt, ziet de suggesties, accepteert ze met één druk op de knop, en de code is schoon.

Proactieve Technische Schuld Rapportage

Elke week krijg je automatisch een rapport. "Deze week zijn er 23 nieuwe issues bijgekomen en 15 opgelost. De trend is negatief. Top 3 probleem gebieden zijn de Services folder met 45 issues, de Controllers folder met 32 issues, en Program.cs met 5 issues."

De AI kan zelfs prioriteren. "Als je deze week één ding aanpakt, focus dan op de ReportService. De complexiteit van 138 in de hoofdmethode is een tikkende tijdbom. Hier is een refactoring plan in vijf stappen."

Learning Mode

Nieuwe developers in het team kunnen SonarQube gebruiken als leerplatform. Ze zien een issue, vragen de AI "waarom is S107 belangrijk?", en krijgen een uitgebreide uitleg over het Single Responsibility Principle en waarom te veel constructor parameters een code smell is.

Dit transformeert SonarQube van een tool die problemen meldt naar een mentor die uitlegt en onderwijst.

Pre-Commit Hooks met AI

Voordat code überhaupt in Git belandt, kan een hook checken of er kritieke SonarQube issues zijn. Niet door de hele scan te draaien, maar door de gewijzigde files te checken tegen bekende patronen.

Als er iets kritiek is, blokt de commit. De developer krijgt direct feedback in de terminal. Geen wachten op CI/CD, geen context switch, directe actie.

De Ultieme Integratie

┌─────────────────────────────────────────────────────────────────────────────┐
│                    DE TOEKOMST: VOLLEDIGE INTEGRATIE                        │
└─────────────────────────────────────────────────────────────────────────────┘

                              ┌─────────────────────┐
                              │    DEVELOPER        │
                              │    schrijft code    │
                              └──────────┬──────────┘
                                         │
                    ┌────────────────────┼────────────────────┐
                    │                    │                    │
                    ▼                    ▼                    ▼
           ┌────────────────┐   ┌────────────────┐   ┌────────────────┐
           │   REAL-TIME    │   │   PRE-COMMIT   │   │   CI/CD        │
           │   IDE FEEDBACK │   │   HOOK CHECK   │   │   PIPELINE     │
           │                │   │                │   │                │
           │ Claude + MCP   │   │ Git Hook +     │   │ SonarQube      │
           │ analyseert     │   │ Snelle check   │   │ volledige scan │
           │ tijdens typen  │   │ voor commit    │   │ na push        │
           └───────┬────────┘   └───────┬────────┘   └───────┬────────┘
                   │                    │                    │
                   └────────────────────┼────────────────────┘
                                        │
                                        ▼
                              ┌─────────────────────┐
                              │   KWALITEIT OP      │
                              │   DRIE NIVEAUS      │
                              │                     │
                              │ 1. Tijdens coderen  │
                              │ 2. Voor commit      │
                              │ 3. Na push          │
                              └─────────────────────┘

Dit is de ultieme setup. Drie verdedigingslagen tegen slechte code. Elke laag vangt dingen die door de vorige zijn geglipt. De kans dat een serieus probleem in productie belandt wordt exponentieel kleiner.


Deel 11: Unit Testing en AI - Het Einde van een Tijdperk?

Wat is Unit Testing en Waarom Doen We Het?

Unit testing is het schrijven van kleine testjes die controleren of individuele stukjes code correct werken. Stel je hebt een functie die twee getallen optelt. Dan schrijf je een test die zegt "als ik 2 en 3 invoer, moet er 5 uitkomen." Als dat klopt, is de test groen. Als er 6 uitkomt, is de test rood en weet je dat er iets mis is.

Het idee is simpel maar de praktijk is complex. Voor elke functie die je schrijft, schrijf je meerdere tests. Wat gebeurt er met negatieve getallen? Wat als iemand null invoert? Wat als de input een string is in plaats van een nummer? Elke edge case krijgt zijn eigen test.

In een enterprise omgeving kan dit oplopen tot duizenden tests. Een project met 50.000 regels code kan makkelijk 20.000 regels test code hebben. Sommige teams hanteren een regel dat er meer test code moet zijn dan productie code.

De Traditionele Unit Test Workflow

┌─────────────────────────────────────────────────────────────────────────────┐
│                    TRADITIONELE TEST WORKFLOW                               │
└─────────────────────────────────────────────────────────────────────────────┘

Developer schrijft functie
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ STAP 1: Bedenk alle scenarios                                               │
│ - Happy path (normale invoer)                                               │
│ - Edge cases (grenzen, null, leeg)                                         │
│ - Error cases (ongeldige invoer)                                            │
│ - Integration scenarios                                                     │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ STAP 2: Schrijf voor elk scenario een test                                  │
│ - Setup (maak test data aan)                                                │
│ - Execute (roep de functie aan)                                             │
│ - Assert (controleer het resultaat)                                         │
│ - Teardown (ruim op)                                                        │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ STAP 3: Mock dependencies                                                   │
│ - Database connecties                                                       │
│ - External APIs                                                             │
│ - File system                                                               │
│ - Time/date functies                                                        │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ STAP 4: Debug failing tests                                                 │
│ - Waarom faalt deze test?                                                   │
│ - Is het de code of de test?                                                │
│ - Zijn de mocks correct?                                                    │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
Tijd besteed: 2-4 uur voor een middelgrote feature

Dit proces is tijdrovend. Een ervaren developer besteedt vaak evenveel tijd aan tests als aan de feature zelf. Sommige developers besteden zelfs meer tijd aan tests, vooral bij complexe business logica.

Hoe AI Unit Testing Transformeert

Met AI assistentie verandert dit proces fundamenteel. In plaats van zelf elk scenario te bedenken en elke test te schrijven, kun je zeggen "schrijf unit tests voor deze service."

┌─────────────────────────────────────────────────────────────────────────────┐
│                    AI-GESTUURDE TEST WORKFLOW                               │
└─────────────────────────────────────────────────────────────────────────────┘

Developer schrijft functie
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Developer: "Schrijf unit tests voor OrderService.CalculateTotal"            │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ AI ANALYSEERT:                                                              │
│ - Leest de functie code                                                     │
│ - Identificeert input parameters                                            │
│ - Detecteert dependencies die gemockt moeten worden                        │
│ - Bepaalt edge cases op basis van code flow                                │
│ - Genereert test scenarios automatisch                                     │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ AI GENEREERT:                                                               │
│ - 5-15 test methods                                                         │
│ - Mocks voor alle dependencies                                              │
│ - Assertions voor return values                                             │
│ - Edge case tests (null, empty, boundary)                                  │
│ - Exception tests                                                           │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Developer: Review en run tests                                              │
│ - Kloppen de assumptions?                                                   │
│ - Missen er business-specifieke scenarios?                                  │
│ - Voeg handmatig toe waar nodig                                            │
└─────────────────────────────────────────────────────────────────────────────┘
         │
         ▼
Tijd besteed: 15-30 minuten voor dezelfde feature

De tijdsbesparing is enorm. Wat voorheen uren kostte, kost nu minuten. De AI bedenkt automatisch edge cases die een mens misschien zou vergeten. De AI schrijft de boilerplate code die bij elke test hetzelfde is. De AI mockt dependencies correct op basis van de interfaces.

Een Concreet Voorbeeld

Stel je hebt deze service:

public class OrderService
{
    private readonly IOrderRepository _repository;
    private readonly IDiscountService _discountService;
    private readonly ILogger<OrderService> _logger;

    public async Task<decimal> CalculateTotalAsync(Order order)
    {
        if (order == null)
            throw new ArgumentNullException(nameof(order));

        if (order.Items == null || !order.Items.Any())
            return 0;

        var subtotal = order.Items.Sum(i => i.Price * i.Quantity);
        var discount = await _discountService.GetDiscountAsync(order.CustomerId);

        return subtotal * (1 - discount);
    }
}

Traditioneel zou je zelf 8-10 tests moeten schrijven voor:

  • Null order
  • Empty items list
  • Null items list
  • Single item
  • Multiple items
  • With discount
  • Without discount
  • Zero quantity
  • Negative price (edge case)
  • Customer not found

Met AI zeg je simpelweg "schrijf tests voor CalculateTotalAsync" en je krijgt alle tests gegenereerd, inclusief de mocks voor IOrderRepository, IDiscountService, en ILogger.

SonarQube en Test Coverage

Hier komt SonarQube weer om de hoek kijken. SonarQube meet niet alleen code kwaliteit, maar ook test coverage. Het vertelt je welk percentage van je code gedekt wordt door tests.

┌─────────────────────────────────────────────────────────────────────────────┐
│                    SONARQUBE TEST COVERAGE FLOW                             │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────┐     ┌─────────────────────┐     ┌─────────────────────┐
│   Source Code       │     │   Unit Tests        │     │   Coverage Report   │
│   OrderService.cs   │────>│   OrderServiceTests │────>│   coverage.xml      │
└─────────────────────┘     └─────────────────────┘     └──────────┬──────────┘
                                                                   │
                                                                   ▼
                                                        ┌─────────────────────┐
                                                        │   SonarQube         │
                                                        │                     │
                                                        │   Coverage: 78%     │
                                                        │   Lines covered: 45 │
                                                        │   Lines missed: 12  │
                                                        │                     │
                                                        │   Uncovered:        │
                                                        │   - Line 34-36      │
                                                        │   - Line 52         │
                                                        │   - Line 67-70      │
                                                        └─────────────────────┘

De AI + SonarQube combo is krachtig. Je vraagt de AI om tests te schrijven. Je runt ze met coverage. SonarQube vertelt je welke regels niet gedekt zijn. Je vraagt de AI om extra tests voor die regels. Je herhaalt tot je de gewenste coverage hebt.

De Eerlijke Waarheid: Werk Dat Verdwijnt

Laten we eerlijk zijn. Dit maakt bepaald werk overbodig.

Een junior developer die voorheen twee dagen besteedde aan het schrijven van unit tests voor een feature, ziet die taak nu in een uur gedaan worden. Een QA engineer die handmatig test scenarios bedacht, ziet de AI dit sneller en vollediger doen.

Dit is niet hypothetisch. Dit gebeurt nu. Teams die AI-gestuurde testing adopteren rapporteren 60-80% tijdsbesparing op test schrijven. Dat is niet een kleine optimalisatie. Dat is een fundamentele verschuiving in hoe werk wordt verdeeld.

De vraag is niet of dit gebeurt, maar hoe we ermee omgaan.


Deel 12: De Menselijke Kant - Blauwe Persoonlijkheden en Verandering

Het DISC Model Even Uitgelegd

In de psychologie gebruiken we vaak het DISC model om persoonlijkheden te beschrijven. Vier kleuren, vier types.

Rode persoonlijkheden zijn dominant, resultaatgericht, ongeduldig. Ze willen winnen en snel vooruit.

Gele persoonlijkheden zijn enthousiast, creatief, sociaal. Ze houden van nieuwe ideeën en inspireren anderen.

Groene persoonlijkheden zijn stabiel, ondersteunend, teamgericht. Ze waarderen harmonie en helpen graag.

Blauwe persoonlijkheden zijn analytisch, precies, kwaliteitsgericht. Ze houden van structuur, regels, en dingen correct doen.

Waarom Blauwe Persoonlijkheden Hier Moeite Mee Kunnen Hebben

De blauwe persoonlijkheid heeft eigenschappen die perfect passen bij traditionele software ontwikkeling. Ze zijn nauwkeurig. Ze controleren alles dubbel. Ze schrijven uitgebreide documentatie. Ze testen grondig. Ze volgen processen.

En nu komt er een AI die zegt "ik kan dat ook, en sneller."

Dit raakt aan de kern van hun professionele identiteit. De waarde die ze brachten, de zorgvuldigheid die ze toonden, de precisie waar ze trots op waren, wordt nu door een machine gedaan.

Het is begrijpelijk dat dit weerstand oproept. Het is niet irrationeel. Het is menselijk.

De Bezwaren Die Je Zult Horen

"De AI begrijpt de business context niet." Dit is waar. De AI kent je domein niet zoals een mens dat kent. Maar de AI kan leren. En voor veel technische taken is domeinkennis niet de bottleneck.

"AI-gegenereerde tests missen edge cases." Dit is soms waar, soms niet waar. AI mist soms domein-specifieke edge cases. Maar AI vindt vaak technische edge cases die mensen missen, zoals null checks en boundary conditions.

"Je kunt AI niet vertrouwen met kritieke code." Dit is een valide zorg. Maar het argument is niet dat AI alles alleen doet. Het argument is dat AI het zware werk doet en mensen reviewen. Vier ogen blijven vier ogen.

"Als we stoppen met zelf tests schrijven, verleren we het." Dit is interessant. Het is waar dat vaardigheden atrofiëren als je ze niet gebruikt. Maar we zijn ook gestopt met handmatig sorteren toen we sorteeralgoritmes kregen. We zijn gestopt met handmatig compileren. Sommige vaardigheden zijn het waard om te behouden, andere niet.

De Ongemakkelijke Waarheid

Hier is wat ik eerlijk moet zeggen, ook al is het oncomfortabel.

De rol van de software developer is aan het veranderen. Niet verdwijnen, maar veranderen. De waarde verschuift van "ik kan code typen" naar "ik kan problemen oplossen." De waarde verschuift van "ik ken de syntax" naar "ik begrijp het domein." De waarde verschuift van "ik schrijf tests" naar "ik bepaal wat getest moet worden."

Dit is niet de eerste keer dat dit gebeurt. Toen IDE's auto-complete kregen, verdween de waarde van "ik ken alle functienamen uit mijn hoofd." Toen Stack Overflow kwam, verdween de waarde van "ik heb alle error codes gememoriseerd." Toen cloud computing kwam, verdween de waarde van "ik kan servers fysiek beheren."

Elke keer paste de industrie zich aan. Elke keer vonden mensen nieuwe manieren om waarde toe te voegen.

Wat Blijft, Wat Verdwijnt

┌─────────────────────────────────────────────────────────────────────────────┐
│                    DE VERSCHUIVING IN DEVELOPER WAARDE                      │
└─────────────────────────────────────────────────────────────────────────────┘

WAT VERDWIJNT (of sterk vermindert):
──────────────────────────────────────────────────────────────────────────────
- Boilerplate code schrijven
- Standaard unit tests typen
- Syntax opzoeken
- Simpele bug fixes
- Code formatting
- Documentatie schrijven voor standaard patronen
- CRUD operaties implementeren

WAT BLIJFT (en belangrijker wordt):
──────────────────────────────────────────────────────────────────────────────
- Architectuurbeslissingen nemen
- Business requirements begrijpen
- Edge cases identificeren die domeinkennis vereisen
- AI output reviewen en valideren
- Complexe problemen decomponeren
- Stakeholders adviseren
- Ethische overwegingen maken
- Systemen integreren
- Mentoren en kennis overdragen

De blauwe persoonlijkheid hoeft niet te verdwijnen. Maar de manifestatie van die persoonlijkheid verandert. De precisie verschuift van "ik typ elke regel perfect" naar "ik review elke AI-suggestie kritisch." De grondigheid verschuift van "ik schrijf elke test" naar "ik valideer dat alle scenarios gedekt zijn."

Een Boodschap voor de Sceptici

Als je dit leest en weerstand voelt, wil ik je iets vragen. Denk terug aan de laatste keer dat je een junior developer hielp. Je keek naar hun code, je zag de fouten, je legde uit waarom het anders moest. Je deelde je ervaring en kennis.

De AI maakt die rol niet overbodig. De AI versterkt die rol. Nu kun je drie juniors begeleiden in plaats van één, omdat de AI het repetitieve werk doet. Nu kun je je focussen op de moeilijke vragen, de architectuurkeuzes, de domeinkennis.

De vraag is niet of je vervangen wordt door AI. De vraag is of je AI gaat gebruiken om jezelf te versterken, of dat je achter blijft terwijl anderen dat wel doen.

De Toekomst, Eerlijk Gezegd

Is dit de toekomst? Ja. Onmiskenbaar.

De combinatie van statische analyse (SonarQube), AI assistentie (Claude), en protocol standaarden (MCP) creëert een nieuwe manier van werken die objectief beter is dan de oude manier. Snellere feedback. Minder fouten. Hogere productiviteit.

Teams die dit adopteren zullen teams die dit niet doen voorbijstreven. Niet omdat ze betere programmeurs zijn, maar omdat ze slimmer werken.

De blauwe persoonlijkheid die zegt "ik wil het zelf doen, dat is de enige manier om kwaliteit te garanderen" zal merken dat hun definitie van kwaliteit moet evolueren. Kwaliteit is niet langer "ik heb elke regel zelf geschreven." Kwaliteit is "het systeem werkt, is veilig, is onderhoudbaar, en is op tijd opgeleverd."

En ja, dit is ongemakkelijk. Verandering is ongemakkelijk. Maar ongemak is geen argument tegen de waarheid.


Deel 13: Conclusie

De Kern van het Verhaal

SonarQube is een automatische code reviewer die duizenden regels kent en nooit moe wordt. De gratis versie bevat 95% van de intelligentie. De betaalde versie voegt integratie en rapportage toe.

MCP is de brug die AI en externe tools verbindt. Het maakt het mogelijk voor Claude om direct met SonarQube te communiceren, data op te halen, en actie te ondernemen.

AI-gestuurde unit testing transformeert een taak van uren naar minuten. Niet door corners te cutten, maar door het repetitieve werk te automatiseren terwijl de mens focust op wat echt menselijk inzicht vereist.

De combinatie van deze drie elementen brengt software development naar een nieuw niveau. Niet een beetje beter. Fundamenteel anders.

Voor Developers

Begin met de gratis versie en de MCP integratie. Draai SonarQube lokaal in Docker. Scan je project. Vraag de AI om de resultaten te interpreteren en tests te genereren. Fix de kritieke issues eerst. Maak er een gewoonte van om AI te gebruiken als versterker, niet als vervanging.

Wees niet bang om te experimenteren. De developers die nu leren werken met AI zullen de senior developers van morgen zijn. Degenen die weigeren zullen merken dat de industrie zonder hen verder gaat.

Voor Teams

Overweeg de betaalde versie als je branch analysis en PR decoration wilt. Maar onderschat de waarde van de MCP integratie niet. Het geeft je veel van dezelfde voordelen via een andere weg.

Praat met je team over de verandering. Erken dat het ongemakkelijk is. Erken dat rollen zullen verschuiven. Maar focus op de kansen, niet alleen de bedreigingen. De team members die het snelst adapteren kunnen helpen de anderen mee te nemen.

Voor de Blauwe Persoonlijkheden

Je precisie is niet overbodig geworden. Je oog voor detail is niet waardeloos. Maar de manier waarop je die eigenschappen toepast moet evolueren.

Je nieuwe rol is niet "elke regel zelf schrijven." Je nieuwe rol is "elke AI-suggestie kritisch evalueren." Je nieuwe rol is niet "elke test handmatig typen." Je nieuwe rol is "valideren dat de gegenereerde tests alle scenarios dekken."

Dit is niet minder waardevol. Dit is anders waardevol. En eerlijk gezegd, het is interessanter werk. Minder typen, meer denken.

De Onvermijdelijke Waarheid

De toekomst is niet "AI of mensen." De toekomst is "AI en mensen, samen."

De vraag is niet of je deze tools gaat gebruiken. De vraag is wanneer. En hoe langer je wacht, hoe groter de achterstand die je moet inhalen.

Dit document is niet geschreven om je bang te maken. Het is geschreven om je te informeren. Wat je met die informatie doet, is aan jou.

Maar als je mij vraagt "is dit de toekomst?", dan is mijn antwoord: ja. Zonder twijfel. Zonder voorbehoud.

De combinatie van statische analyse, AI assistentie, en protocol standaarden creëert een nieuwe manier van werken. Teams die dit adopteren zullen teams die dit niet doen voorbijstreven.

En dat is niet erg. Dat is vooruitgang. Dat is hoe de industrie altijd heeft gewerkt. Het enige verschil is de snelheid waarmee het nu gebeurt.


Appendix: Quick Reference - MCP Tool Commands

Via Claude Code kun je vragen:

Issues opvragen:

  • "Wat zijn de SonarQube issues in mijn project?"
  • "Toon alleen de kritieke issues"
  • "Welke issues zitten er in [bestandsnaam]?"

Project status:

  • "Wat is de Quality Gate status?"
  • "Hoeveel issues zijn er per severity?"
  • "Welke projecten zijn er in SonarQube?"

Uitleg vragen:

  • "Waarom is regel S4487 belangrijk?"
  • "Wat betekent Cognitive Complexity?"
  • "Leg uit wat een God Class is"

Actie ondernemen:

  • "Fix de ongebruikte variabelen"
  • "Refactor deze methode om de complexiteit te verlagen"
  • "Verwijder de hardcoded URLs"

Referenties en Verdere Lezing

SonarQube

Model Context Protocol (MCP)

OWASP & Security


Dit document beschrijft de integratie van SonarQube met het Model Context Protocol (MCP) voor AI-gestuurde code kwaliteitsverbetering.