In mijn vorige column, toen deze hete zomer nog moest beginnen, liet ik zien hoe je gestructureerde data heel intuïtief kunt voorstellen in een licht aangepast ‘object-oriented’-model. Ik heb toen beloofd om te laten zien hoe makkelijk het is zo’n structuur te manipuleren.
Door Henk Jan Pels, gepensioneerd universitair hoofddocent bedrijfskundige informatica (TU Eindhoven), en onafhankelijk consultant, gespecialiseerd in Product Data Management. H.J.PELS@PHI-KPE.NL
Wat kun je hiervoor beter als voorbeeld nemen dan de oerstructuur in productdata: de BoM (Bill of Materials). Voor een simpele BoM grijp ik terug op mijn column over modulair ontwerpen (april 2017): een samenstelling van een blok en een as. Tegen de eenvoud doe ik er nog een wiel bij en maak van as met wiel een subsamenstelling:
De structuur waarin deze producten samenhangen, wordt vastgelegd in de BoM-tabel:
U zult gemakkelijk een stuklijst herkennen. Elke regel beschrijft een component (Child) van een samenstelling (Parent). Per samenstelling zijn de regels genummerd met een positienummer. Bijzonder is de toevoeging ‘Product’ achter Parent en Child. Dit betekent dat de attribuutwaarden objectnamen uit de Product-tabel moeten zijn dus dat het hier associatie-kolommen betreft. Om de samenhang tussen tabellen te visualiseren gebruiken we een ‘data structure’-diagram:
Objectklassen (tabellen) worden hierin voorgesteld door een blok met de tabelnaam in het bovenste veld en de attributen in het onderste. Een lijn tussen twee objectklassen is een associatie en betekent dus een associatie-attribuut: een attribuut met objectnamen uit de overliggende klasse als waarden. In de meeste gevallen is er tussen twee objectklassen maar één associatie. De klassennamen worden dan als attribuutnaam gebruikt. De BoM is echter wat minder simpel en heeft twee associaties tussen Product en BoM. Om die uit elkaar te kunnen houden moeten we die dus aparte namen geven. In de BoM-klasse zijn dit Parent en Child. De associatienaam wordt altijd geplaatst aan de zijde van de objectklasse waarnaar verwezen wordt. Zo geeft het data structure-diagram aan dat, gezien vanuit Product, de associaties WhatUsed en WhereUsed heten.
Het creëren van deze database is simpel: We typen gewoon de twee tabellen en het systeem herkent ze als objectklassen, die het meteen laat zien als u het data structure-diagram opvraagt. Op grond van de dubbele punten in de Parent- en Child-kolommen tekent het systeem zelf de twee associaties. We moeten alleen nog even de namen WhatUsed en WhereUsed invullen. Als gevolg daarvan voegt het systeem deze als kolom toe aan de Product-tabel en vult meteen de waarden in. Omdat beide kolommen afgeleid zijn, zijn ze cursief gedrukt in onderstaande uitgebreide Product-tabel.
Omdat we vinden dat de BoM-objectnamen niet direct zijn wat we verwachten als WhatUsed-lijst, voegen we de laatste twee kolommen toe. WhatUsed.Child is de expressie voor de producten waarmee het betreffend WhatUsed-object als Child is geassocieerd. Die expressie zorgt ervoor dat het systeem de waarden (cursief) kan invullen. Voor WhereUsed geldt hetzelfde. Als we nu een nieuw product en een extra BoM-regel zouden toevoegen, dan worden alle cursieve attribuutwaarden automatisch aangepast.
U ziet hoe eenvoudig het is om een systeem te creëren dat BoMs kan bijhouden. Het enige wat u meer doet dan in een spreadsheet, is het specificeren van de associaties. Op grond daarvan kan het systeem vervolgens, dankzij de formele semantiek van het achterliggende datamodel, allerlei afgeleide waarden bijhouden. Handig is ook de mogelijkheid om kolommen te specificeren met expressies. In een spreadsheet moet u die in elk veld herhalen en dat is lastig als u de expressie een keer wilt veranderen.
Overigens is deze BoM eigenlijk nog iets te simpel, want er wordt geen rekening met versies gehouden. De volgende keer wil ik daarmee gaan spelen om te kijken hoe eenvoudig de database blijft, als de structuur van de vastgelegde data complexer wordt.