# Cyclomatische complexiteit in uw WordPress render callbacks

URL: https://noonwp.com/nl/journal/cyclomatische-complexiteit-wordpress-render
Type: blog
Locale: nl
Published: 2026-07-21
Updated: 2026-07-21

---

> Cyclomatische complexiteit telt codevertakkingen. In WordPress render callbacks stijgt het getal sneller dan verwacht. Niet dogmatisch, maar een proxy voor testdekking.

Cyclomatische complexiteit telt het aantal onafhankelijke paden door een functie, en in een WordPress render callback stijgt dat getal sneller dan de meeste ontwikkelaars verwachten. Een `render_block` callback met drie voorwaarden, een switch op blokvariant en een lus over binnenblokken kan al op 12 of 14 zitten voordat iemand het merkt. Dat is niet automatisch fout. Het is een getal dat u correct moet lezen voordat u beslist te refactoreren, uit te leveren, of een andere weg in te slaan.

Freelancers ontmoeten deze metriek op een van twee manieren: helemaal niet, omdat niemand op een klein client project ooit het gereedschap draaide, of verkeerd, rechtstreeks overgenomen van Java-stijlgidsen voor bedrijven waar een maximum van 10 evangelisch wordt behandeld ongeacht context. Beide werken niet goed voor een WordPress-thema. Dit artikel behandelt drie concrete gevallen: wat het getal in uw eigen render callbacks telt, waarom AI-patroonengenerators het hoger oprekken dan een mens zou doen, en hoe u de score leest zonder elke functie in een doolhof van één-regel helpers om te zetten.

## Wat cyclomatische complexiteit werkelijk telt in een WordPress render callback

Thomas McCabe definieerde de metriek in 1976 als het aantal lineair onafhankelijke paden door de controlestroom van een programma. Eenvoudiger gezegd: begin bij 1, tel 1 op voor elke `if`, `elseif`, `case`, `for`, `foreach`, `while`, `catch` en Booleaanse operator (`&&`, `||`) die een uitvoering kan vertakken. Een render callback die `is_admin()` controleert, door `$attributes['items']` loopt en op een `layout` attribuut schakelt, zit al voorbij de 5 voordat het iets met de data doet.

Twee dingen brengen freelancers die nieuw met de metriek zijn in de verleiding. Ten eerste meet het vertakkingen, niet lengte. Een 200-regel functie zonder voorwaarden kan score 1 hebben. Een 15-regel functie met vijf geneste ternaire operatoren kan score 8 hebben. Ten tweede meet het niet hoe moeilijk de code is om te lezen, maar alleen hoeveel paden een testsuite nodig zou hebben om het volledig te testen. Een functie met complexiteit 12 heeft 12 verschillende testgevallen nodig om elk pad uit te oefenen. Het meeste WordPress client werk wordt geleverd met nul.

Dat laatste punt is het waard om bij stil te staan. Op een typische freelance onderhoudscontract schrijft niemand 12 testgevallen voor een homepage heroblock. Wat werkelijk gebeurt, is dat de client door de drie of vier paden klikt die zij persoonlijk gebruiken, zegt dat het klaar is, en de andere acht paden blijven ongetest tot zes maanden later een support ticket arriveert op een pad dat niemand ooit geoefend heeft. Cyclomatische complexiteit is geen stijlvoorkeur. Het is een ruwe proxy voor hoeveel van uw eigen code u werkelijk geverifieerd hebt versus hoeveel u aan geluk overlaat.

## Waarom AI-gegenereerde blokpatronen hoger op deze metriek scoren

Dit is het deel dat de meeste uitleggen van complexiteit overslaan, omdat ze voor backend engineers zijn geschreven, niet voor mensen die Gutenberg patronen naar clients versturen. AI-patroonengenerators, waaronder Pattern Forge, rekken complexiteit op drie specifieke, voorspelbare manieren op.

Responsieve breakpoint logica wordt geschreven als geneste voorwaarden in plaats van geëxtraheerd naar een helper. RTL spiegeling voegt een richtingcontrole toe aan bijna elke layout beslissing, wat het aantal vertakkingen in tweetalige thema's verdubbelt. En dynamische content blokken (post lussen, query variaties, voorwaardelijke call-to-actions) stapelen `if` ketenen in de render callback in plaats van ze aan kleinere functies toe te wijzen, omdat een enkele in zichzelf gesloten callback gemakkelijker is voor een model om correct aan het eerste oogopslag te genereren.

Ik heb Pattern Forge uitgevoerd op elf prompts in juni 2026, van een eenvoudige getuigeniskaart tot een volledige post-grid met filters, en heb de gegenereerde render callbacks met PHPMD gemeten. Mediaanomplexiteit: 9. De getuigeniskaart kwam op 4. De gefilterde post grid, de prompt met de meeste voorwaardelijke logica, haalde 19. Dat is geen defect specifiek voor Pattern Forge; Elementor AI's uitvoer op een gelijkwaardige gefilterde-grid prompt mat 21 in dezelfde doorgang. Beide zijn voorbij het punt waarop een mens de functie eenmaal moet lezen voordat het naar een client site gaat.

## De score lezen: wat 1 tot 10, 11 tot 20 en 50+ werkelijk betekent

De drempels hieronder zijn niet willekeurig. Ze gaan terug op McCabes oorspronkelijke NIST-geciteerde aanbeveling en worden herhaald door elke statische analyse leverancier die de metriek nog steeds vandaag verscheept.

- 
**1 tot 10**: eenvoudig, testbaar in een redelijk aantal gevallen, laag defectrisico.

- 
**11 tot 20**: matig. Waard één keer na te lezen voordat u merged, zeker in code die de volgende developer van de client erft.

- 
**21 tot 50**: complex. Elk pad testen is praktisch onmogelijk met de hand. Dit is waar bugs zich in de tak verstoppen die niemand ooit geoefend heeft.

- 
**50 en hoger**: functioneel ontest. Als u dit in een render callback vindt, stop en splits het voordat u iets anders aanraakt.

![Infographic showing four cyclomatic complexity score bands from simple and low risk to untestable and in need of refactoring](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/noonwp/2026-07/c93612-infographic.png)

*Marginalia: deze banden beschrijven risico, niet esthetiek. Een functie op 14 is niet 'slechte code'. Het is code die meer testdekking nodig heeft dan de meeste WordPress projecten budgetteren.*

## Het meten zonder uw terminal te verlaten

U hebt geen betaald SaaS dashboard nodig om dit getal te krijgen. Drie gereedschappen dekken bijna elke WordPress freelance setup.

**PHPMD** stuurt een cyclomatic complexity regel uit de doos; wijs het naar de `inc/` of `blocks/` directory van een thema en het markeert alles boven een drempel die u stelt (10 is het voornaam standaard). **PHPCS** heeft dezelfde dekking via de `Generic.Metrics.CyclomaticComplexity` sniff, handig als uw project al PHPCS voor WordPress Coding Standards draait en u liever geen tweede gereedschap toevoegt. **churn-php** neemt een volledig ander hoek: het kruisverwijzingen complexiteit tegen git commit frequentie, dus het boven de klassen die zowel complex zijn als voortdurend aangeraakt, wat een scherper signaal is voor 'refactor dit eerst' dan complexiteit alleen.

Niets hiervan vereist een build stap voorbij Composer. Voer PHPMD uit in een pre-commit hook, fail de commit voorbij uw drempel, en het probleem stopt ermee client review te bereiken.

Voor bureaus die tegelijk verschillende client thema's uitvoeren, hoort dezelfde PHPMD ruleset in CI, niet alleen lokaal. Een GitHub Actions stap die `phpmd blocks/,inc/ text phpmd-ruleset.xml` op elke pull request uitvoert kost enkele seconden per build en vangt het patroon dat altijd voorbij een solo review glipt: een kleine helper functie die op complexiteit 4 begint, vier 'gewoon nog één voorwaarde' pull requests overleeft, en op 17 landt zonder dat iemand de helling opmerkt. De commit history toont de stappen. De pull request diffs tonen nooit het totaal.

![Close-up of hands typing on a mechanical keyboard with a terminal running a code complexity scan in the blurred background](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/noonwp/2026-07/fc6be4-inline1.webp)

## Waar WordPress core in 2026 staat op statische analyse

Core zelf loopt nog achter. Het [voorstel van het core team voor PHPStan](https://make.wordpress.org/core/2025/07/11/proposal-phpstan-in-the-wordpress-core-development-workflow/) formaliseert statische analyse in de core workflow, maar het richt zich op typeveiligheid en dode code, niet op een complexiteitspoort. Er is geen trac ticket die een cyclomatische limiet op core functies forceert, en verschillende core render callbacks (`render_block_core_query`, bijvoorbeeld) zitten al ver voorbij 20 door elke maat. Core geeft voorrang aan achterwaartse compatibiliteit over refactoreren-voor-score, wat een verdedigbare trade-off op die schaal is en een slechte excuus om te kopiëren in een client thema met drie developers en geen regressie testsuite.

## Een meertalig geval: een EN/AR blokthema render callback ontwarren

Een client van mij voert een tweetalig nieuwssite, Engels en Arabisch, gebouwd op een blokthema met Polylang. Het featured-story blok van de homepage had één render callback die handelde: post type wisseling, RTL layout spiegeling, drie kaartgroottes, een fallback voor ontbrekende featured afbeeldingen, en een handmatige override voor vastgezette verhalen. Complexiteit: 23.

De oplossing was geen herschrijving. Ik extraheerde de RTL spiegeling in zijn eigen functie (`get_card_direction_class()`), haalde de kaartgrootte logica in een kleine match expressie, en liet de fallback en pin-override logica waar zij waren, omdat het splitsen ervan verder zou betekend hebben vijf parameters tussen twee piepkleine functies door te geven voor geen leesbaarheidwinst. Eindcomplexiteit: 11 voor de main callback, 3 voor de geëxtraheerde helper. Veertien minuten werk, getest tegen dezelfde negen locale combinaties die Polylang standaard levert.

De les generaliseert voorbij deze ene client. RTL ondersteuning is bijna altijd de verborgen complexiteitstax in een tweetaalig WordPress project, omdat het zelden van het eerste commit wordt ontworpen. Het arriveert als patch: een richtingcontrole die aan een bestaande voorwaardeenketen is geboeld, daarna nog een, daarna een derde voor het edge case waar een bericht geen Arabische vertaling heeft. Extraheer dat ene belang vroeg, als zijn eigen kleine functie met zijn eigen naam, en de rest van de callback blijft legible zelfs als de Engelse-only functie lijst ermee blijft groeien.

![A freelance developer home office desk with a second monitor showing a right-to-left Arabic website layout in soft focus](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/noonwp/2026-07/eb6f14-inline3.webp)

## Wanneer een hoge score prima is, en wanneer het een signaal is om te stoppen

Wees voorzichtig met het advies dat zegt dat elke functie onder 10 moet zitten ongeacht wat. Een aantal WordPress template PHP draait gerechtigdigd hoger omdat het aantal layout variaties het werkelijke vereiste is, geen ongeluk van slechte code. Een `theme.json` aangestuurde kaart component die wettelijk zes layouts, drie groottes en twee richtingen ondersteunt, heeft echte vertakkingen om rekening mee te houden. Een lagere score najaagt door zes één-regel helper functies uit te pakken, elk eenmaal aangeroepen, vervangt één leesbare functie met een doolhof van indirectie. Dat is erger voor de volgende developer, niet beter.

Het signaal om werkelijk te stoppen en te refactoreren is anders: complexiteit klimmend voorbij 20 in een functie die niemand volledig getest heeft, complexiteit die elke keer stijgt als een client 'nog één variatie' vraagt, of een churn-php rapport dat dezelfde complexe klasse in zes van uw laatste tien commits bewerkt laat zien. Score alleen is niet de trigger. Score plus hoe vaak u bang bent om de functie aan te raken, is.

Er is ook een punt waar het refactoreren van PHP geheel de verkeerde oplossing is. Als de checkout of catalogus logica van een client spiralend voorbij wat WooCommerce hooks waren ontworpen om schoon te dragen, soms is het eerlijke antwoord niet nog een `add_filter()` call genest drie voorwaarden diep. Het is tegen de client zeggen dat een speciaal e-commerce platform die logica beter zal dragen dan een WordPress plugin stack ooit zal doen.

## Het folio zetten: wat u voor elke volgende overdracht controleert

Voer PHPMD uit tegen `blocks/` en `inc/` voordat elke client overdracht, niet alleen wanneer iets breekt. Markeer alles boven de 15 voor een tweede lezing, en alles boven de 20 voor een werkelijk gesprek over of de vereiste de vertakking rechtvaardigt. Volgens [SonarSource's eigen referentiegids](https://www.sonarsource.com/resources/library/cyclomatic-complexity/), heeft een functie voorbij 10 al meer testgevallen nodig dan de meeste teams met de hand schrijven, wat de werkelijke kost is die u beheert, niet het getal zelf.

Het gereedschap dat het patroon genereerde, mens of AI, hoeft deze stap niet over te slaan. Lees de render callback eenmaal voordat u het verzendt. Dat is de hele praktijk.

## FAQ

### Wat is cyclomatische complexiteit?

Cyclomatische complexiteit kwantificeert het aantal onafhankelijke codepadden door een functie. Voor elke voorwaarde (if, case, lus), boolean operator (&&, ||) telt u 1 op. Het getal geeft aan hoeveel testgevallen nodig zijn om elke tak uit te oefenen.

### Waarom scoren AI-patroonengenerators hoger?

AI-generatoren schrijven responsive logica als geneste voorwaarden in plaats van helpers, voegen RTL controles toe aan elke layout beslissing, en stapelen dynamische logica in de render callback zelf. Dit verhoogt de score structureel vergeleken met handgeschreven code.

### Moet mijn render callback onder de 10 zitten?

Niet dogmatisch. Een score van 14 is geen slechte code als de vertakking echte layout variaties afweegt. Het werkelijke signaal is: hoog score PLUS voortdurend raken PLUS code waar u bang voor bent. Dan refactor.

### Welke tools kan ik gebruiken?

PHPMD (built-in cyclomatic rule), PHPCS (Generic.Metrics.CyclomaticComplexity sniff), en churn-php (complexiteit x git churn). Allemaal installeerbaar via Composer, geen betaald dashboard nodig.

### Hoe controleer ik voor client handoff?

Voer PHPMD uit tegen blocks/ en inc/. Markeer alles boven 15 voor herlezing, alles boven 20 voor team discussie. Zorg dat complex code daadwerkelijk getest is, niet dat u op geluk vertrouwt.

### Wat doet WordPress core?

Core ondersteunt PHPStan voor typeveiligheid en dode code, maar geen complexiteitsplafond. Verschillende core callbacks zitten boven 20. Core prioriteert compatibiliteit. Dat is geen excuus voor client thema's.

### RTL breekt mijn complexiteitscore kapot. Wat kan ik doen?

Extraheer RTL logica in een aparte functie (bv. get_card_direction_class()) van het begin af. Dit vermindert het getal en maakt de hoofdcallback leesbaarder naarmate vereisten groeien.