Dat is begrijpelijk, want ze hebben allebei iets te maken met geldige en ongeldige keuzes. Toch werken ze anders, en dat verschil wordt belangrijk zodra een product complexer wordt. Ik ben zelf lang vooral vanuit regels en parametrische CAD beginnen denken. Dat voelt ook heel natuurlijk: als dit gebeurt, doe dan dat. Sinds ik met constraint-based configuratie werk, kijk ik daar genuanceerder naar. Niet omdat constraints altijd beter zijn, maar omdat ze een ander soort probleem oplossen.

Een domain zegt wat mogelijk is

Een domain is voor mij het eenvoudigste niveau.

Het zegt gewoon welke waarden een parameter mag aannemen. Dat kan een bereik zijn, zoals een breedte tussen 600 en 2400 mm, of een beperkte set keuzes zoals RVS304 en RVS316. Een domain maakt dus nog geen keuze en legt ook nog geen logica op. Het geeft alleen aan wat in principe mogelijk is.

Daar begint configuratie vaak mee.

Een expression berekent iets

Niet elke relatie in een productmodel is meteen een rule of een constraint.

Soms volgt een waarde gewoon uit andere waarden. Als de pootlengte gelijk is aan de werkhoogte min de dikte van het werkblad, dan is dat gewoon een berekening. Ik zie dat als een expression. Er moet niets gezocht of beslist worden; de waarde volgt rechtstreeks uit het model.

Dat lijkt banaal, maar het helpt om een systeem leesbaar te houden. Als je elke eenvoudige afleiding als rule of constraint behandelt, maak je het model al snel zwaarder dan nodig.

Een rule werkt in een richting

Een klassieke rule is meestal directioneel.

Je start van een voorwaarde en zet dan een gevolg. Als de breedte groter is dan 1800 mm, voeg je een middensteun toe. Als de brandklasse EI60 is, krijgt het deurblad een bepaalde dikte. Dat soort logica is krachtig en vaak ook heel begrijpelijk. In parametrische CAD en iLogic heb ik daar veel mee gewerkt, en ik gebruik dat vandaag nog altijd waar de relatie duidelijk één richting uitgaat.

Voor engineering automation is dat vaak perfect.

Een constraint zegt wat waar moet blijven

Een constraint werkt anders.

Die zegt niet noodzakelijk wat eerst of laatst moet gebeuren, maar legt een relatie vast die geldig moet blijven. De totale breedte moet bijvoorbeeld de som zijn van linker marge, deurbreedte en rechter marge. Of het vereiste koppel moet lager liggen dan wat de gekozen motor aankan. Of een plaatlengte mag de maximale plooilengte niet overschrijden.

Op dat moment ben je minder een procedure aan het beschrijven en meer een toestand die altijd moet kloppen. Dat wordt vooral interessant wanneer verschillende keuzes elkaar tegelijk beïnvloeden en de gebruiker niet in één vaste volgorde door het product gaat.

Waarom dat bij complexe producten belangrijk wordt

Bij een eenvoudig product kom je vaak heel ver met rules.

Maar neem een sterk configureerbare deur. Dan beïnvloeden deurtype, opbouw, materiaal, brandveiligheid, sloten en staalframe elkaar allemaal. Je kan dat uiteraard met if/then-logica modelleren, maar na verloop van tijd ontstaat er een netwerk waarin uitzonderingen op uitzonderingen stapelen en de volgorde van uitvoering belangrijk wordt.

Dan wordt het moeilijker om nog te zien of je het product modelleert, of gewoon een script aan het schrijven bent dat toevallig een product representeert.

Constraint-based configuratie probeert dat anders aan te pakken. Je beschrijft de relaties die geldig moeten blijven, en laat het systeem mee uitzoeken welke combinaties nog kunnen.

Constraints zijn geen wondermiddel

Dat betekent niet dat constraints altijd de beste oplossing zijn.

Sommige dingen zijn gewoon directioneel en dus duidelijker als rule. Andere volgen rechtstreeks uit een berekening en horen thuis als expression. En als een parameter maar een beperkt aantal mogelijke waarden heeft, volstaat een goed domain.

Ik probeer het daarom liever zo te bekijken:

  • een parameter beschrijft iets aan het product;
  • een domain zegt welke waarden mogelijk zijn;
  • een expression berekent een directe afleiding;
  • een rule legt een richting vast;
  • een constraint bewaakt een relatie die altijd moet kloppen.

Dat lijkt misschien een theoretisch onderscheid, maar in een groter model helpt het enorm. Het maakt sneller duidelijk waarom een bepaalde waarde bestaat en welk soort logica erop werkt.

Rules voor automatisering, constraints voor wederzijdse afhankelijkheid

In CAD-automatisering zijn rules vaak heel natuurlijk.

Een model heeft een duidelijke input, daarna worden maten berekend, onderdelen aan- of uitgezet en tekeningen gegenereerd. Dat is meestal een vrij voorspelbare stroom. Daar hoeft niet per se een solver tussen te zitten, en meestal is een eenvoudig deterministisch model dan beter dan een slim model dat niemand nog begrijpt.

Bij CPQ is dat anders.

De gebruiker kan eerst materiaal kiezen, daarna maat, daarna uitvoering — of net in een andere volgorde. Eén keuze kan de mogelijke waarden van een andere parameter beperken, en sommige opties kunnen elkaar tegelijk beïnvloeden. Op dat moment wordt het belangrijk dat het productmodel niet volledig afhangt van de volgorde waarin de interface vragen stelt.

Dat is ook wat ik interessant vond toen ik met Tacton begon te werken. Het model voelt dan minder als een script en meer als een samenhangend systeem.

De UI is niet het productmodel

Dat is nog een belangrijk onderscheid.

Een configurator mag aan de buitenkant heel lineair aanvoelen. Je kan perfect een duidelijke flow hebben met eerst type, dan afmetingen, dan materiaal en dan opties. Maar dat betekent niet dat het onderliggende model ook lineair moet zijn. De interface is hoe je de gebruiker door het product leidt. Het productmodel erachter moet de echte relaties en beperkingen bevatten.

Dat maakt het later ook veel makkelijker om dezelfde productkennis in een andere interface, API of engineeringtool te gebruiken.

Mijn voorkeur: combineren

Ik geloof daarom niet zo in één zuivere aanpak.

Voor mij werkt een combinatie het best: expressions waar iets gewoon berekend wordt, rules waar de richting logisch is, constraints waar keuzes elkaar wederzijds beperken, en domains om duidelijk te maken wat überhaupt kan. Als daarboven ook nog een heldere productstructuur staat, blijft het geheel veel leesbaarder.

Dat klinkt misschien minder spectaculair dan “alles constraint-based”, maar het is voor mij praktischer.

Het doel is niet de slimste solver bouwen.

Het doel is dat het productmodel ook binnen vijf jaar nog begrijpelijk is.