Ebook · Hoofdstuk 3 van 10
Requirements en Ontwerp
Van vage businessvraag naar concreet, implementeerbaar datawarehouse-ontwerp. De stappen die je niet mag overslaan.
Beginnen bij de business
De grootste reden dat datawarehouse-projecten falen is niet techniek — het is dat de business nooit echt heeft uitgesproken wat ze van het systeem verwachten. Een goed ontwerp begint bij vragen, niet bij tabellen. Dit hoofdstuk loopt door het traject van requirements naar technisch ontwerp, met de templates die je in de praktijk kunt gebruiken.
Het belang van een goed begin
Onderzoek door Gartner en TDWI laat consequent zien dat 50-70% van datawarehouse-trajecten de oorspronkelijke doelstellingen niet of slechts gedeeltelijk haalt. De oorzaken liggen vrijwel nooit bij gebrek aan technische kunde — ze liggen bij onduidelijke scope, gebrekkig stakeholder-management en verkeerde aannames over wat de business eigenlijk wil meten. Investeer twee tot vier weken aan requirements en design voor je één tabel bouwt; je verdient die tijd in de bouwfase dubbel terug.
Stap 1: stakeholders identificeren
Voordat je één regel SQL schrijft, moet helder zijn wie je opdrachtgever is en wie je gebruikers zijn. Onderscheid:
- Sponsor — wie betaalt en krijgt de waarde? Vaak een directielid (CFO, CCO).
- Power users — analisten en BI-developers die dagelijks queries draaien.
- Casual consumers — managers die dashboards bekijken.
- Data owners — eigenaren van de bronsystemen (CRM, ERP, e-commerce).
- Operators — DevOps / platform-teams die het draaiend houden.
Houd één-op-één-gesprekken met deze groepen, geen plenaire sessies. In een groep zwijgt de minderheid.
Stap 2: functionele requirements
Functionele eisen beschrijven wat het warehouse moet kunnen. De meest praktische techniek is om met stakeholders een lijst van analytical questions op te stellen — concrete vragen die ze willen kunnen beantwoorden. Bijvoorbeeld:
- "Wat is de gemiddelde orderwaarde per klantsegment per maand?"
- "Hoeveel procent van de nieuwe klanten heeft binnen 90 dagen een tweede order geplaatst?"
- "Welke producten worden vaak samen gekocht?"
Deze vragen worden je acceptatiecriteria. Aan het einde van een sprint test je: kan ik deze vraag in < 10 seconden beantwoorden met één SQL-query?
Anti-pattern: alleen velden vragen
Een veelgemaakte fout is vragen wat de stakeholder "in het rapport wil zien". Je krijgt dan een lijst velden zonder context. Vraag in plaats daarvan welke beslissingen ze willen nemen — daaruit volgen de velden vanzelf.
Stap 3: niet-functionele requirements
Even belangrijk en vaak vergeten:
- Data freshness — moet de data realtime zijn, dagelijks, wekelijks?
- Latency / performance — hoe snel moet een dashboard laden? < 3 sec is een gangbare BI-norm.
- Concurrency — hoeveel gelijktijdige gebruikers?
- Volume — hoeveel rijen per dag, hoeveel historie bewaren we?
- Security — row-level security, kolom-masking voor PII, audittrail?
- Compliance — GDPR, financiële regels, retentiebeleid?
- Beschikbaarheid — werktijden of 24/7? RPO/RTO bij uitval?
- Budget — max kosten per maand voor compute en storage?
Deze antwoorden bepalen de platformkeuze (hoofdstuk 7). Een freshness van 5 minuten is niet hetzelfde architectuurprobleem als een freshness van 24 uur.
Stap 4: bus matrix opstellen
De bus matrix (Kimball) is een eenvoudige maar krachtige tabel: business processen op de rij-as, dimensies op de kolom-as. Een vinkje in een cel betekent: "deze dimensie is relevant voor dit proces".
| Business proces ↓ / Dimensie → | Datum | Klant | Product | Winkel | Medewerker | Leverancier |
|---|---|---|---|---|---|---|
| Verkoop | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Inkoop | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Voorraad | ✓ | ✓ | ✓ | |||
| Marketing | ✓ | ✓ | ✓ | |||
| HR | ✓ | ✓ | ✓ |
De waarde zit niet in de tabel zelf, maar in het gesprek dat eraan voorafgaat. Het dwingt stakeholders om expliciet te zijn over wat ze nodig hebben, en het laat zien welke dimensies conformed moeten worden — als datum, klant en product overal terugkomen, moet je die maar één keer goed bouwen.
Stap 5: drie modelleerniveaus
Modelleer je warehouse in drie iteraties:
- Conceptual model — entiteiten en relaties, business-taal. Geen attributen, geen technische keuzes. Past op één A3.
- Logical model — entiteiten met attributen en datatypes, primary/foreign keys. Patroon-keuze (Kimball / Inmon / Data Vault) komt hier binnen.
- Physical model — concrete DDL voor je gekozen platform. Partitioning, clustering, distribution keys, indexen.
Een fragment van een conceptual model in pseudo-notatie:
-- Conceptueel: alleen entiteiten en relaties
Klant ─── plaatst ───► Order
Order ─── bevat ────► OrderRegel
Product ─── op ──────► OrderRegel
Winkel ─── verkoopt ──► Order
En het logische model dat eruit volgt (Kimball-stijl):
CREATE TABLE fact_order_line (
order_line_key BIGINT,
date_key INT,
customer_key INT,
product_key INT,
store_key INT,
order_id VARCHAR(50), -- degenerate dimension
quantity INT,
unit_price DECIMAL(10,2),
discount_amount DECIMAL(10,2),
net_amount DECIMAL(12,2)
);
order_id staat hier als degenerate dimension in de fact table: het is een attribuut zonder eigen dimension table, omdat er verder geen interessante context aan hangt.
Stap 5b: dataprofiling vóór je modelleert
Tussen logical en physical model hoort altijd een ronde dataprofiling op de bron. Aannames die in de praktijk vrijwel altijd fout zijn:
- "De business key is uniek" — profiel het. Dubbele klant-IDs door fusies, herstarts of test-records komen vaker voor dan je denkt.
- "Dit veld is altijd gevuld" — een NULL-percentage van 12% verandert je model.
- "De datatypes kloppen" — dat datum-veld is een VARCHAR met 14 verschillende formaten.
- "De cardinaliteit klopt" — een veld dat 50 unieke waarden hoort te hebben heeft er 12.000 wegens vrije invoer.
Tools: SELECT-queries op de bron, dbt's source freshness checks, of dedicated profilers als Great Expectations en Soda Core. Documenteer bevindingen in je STTM voordat je modeldecisies in beton giet.
Stap 6: naming conventions
Naming is geen detail. Niets vertraagt onboarding zoveel als inconsistente namen. Spreek vooraf af:
- Lowercase met underscores:
fact_sales, nietFactSalesoffact-sales. - Prefixen voor type:
dim_,fact_,stg_(staging),int_(intermediate),hub_,sat_,link_(Data Vault). - Suffix
_keyvoor surrogate keys,_idvoor business keys. - Booleans beginnen met
is_ofhas_(is_active,has_subscription). - Datums:
_datevoor DATE,_atof_tsvoor TIMESTAMP (created_at,load_ts). - Bedragen: kolomnaam met valuta indien meerdere (
amount_eur,amount_usd). - Bron-prefix in staging:
stg_salesforce__accounts,stg_shopify__orders.
Schrijf het op
Leg de afspraken vast in een NAMING.md in je repo. Verwijs ernaar in elke code review. Inconsistentie sluipt er anders in zodra een nieuw teamlid begint.
Stap 7: data dictionary
Voor elke tabel en kolom leg je vast: betekenis, herkomst, datatype, voorbeeld, toegestane waarden, verantwoordelijke. Tools die dit automatiseren: dbt docs, DataHub, Collibra, Alation. Voor kleinere projecten volstaat een markdown-file of een schemafile in YAML.
# schema.yml — dbt-stijl data dictionary
version: 2
models:
- name: dim_customer
description: "Eén rij per klant, SCD Type 2 — actuele én historische versies."
columns:
- name: customer_key
description: "Surrogate key. Wijzigt bij elke SCD Type 2-mutatie."
tests: [unique, not_null]
- name: customer_id
description: "Business key uit Salesforce."
tests: [not_null]
- name: segment
description: "Klantsegment: SMB / Mid-Market / Enterprise."
tests:
- accepted_values:
values: ['SMB', 'Mid-Market', 'Enterprise']
Stap 8: prioriteren met MoSCoW
Je krijgt nooit alles in v1. Prioriteer met MoSCoW:
- Must have — zonder dit faalt het project.
- Should have — belangrijk maar niet kritiek voor v1.
- Could have — leuk om te hebben.
- Won't have — expliciet uit scope, nu niet.
Een eerste werkende versie ("MVP") moet de Must-haves dekken voor één business proces. Niet alles voor alle processen tegelijk — dat is een recept voor vertraging.
Source-to-target mapping (STTM)
Tussen logical model en implementatie hoort een Source-to-Target Mapping — per doelkolom: welke bron, welke transformatie, welke business rule. Vaak in Excel of een dbt-yaml, maar onmisbaar bij audits, onboarding van nieuwe engineers en bij debugging. Een minimaal voorbeeld:
target_table: dim_customer
target_column: segment
source: salesforce.account.classification__c
transformation: |
CASE
WHEN classification__c IN ('SMB','Small') THEN 'SMB'
WHEN classification__c = 'MidMarket' THEN 'Mid-Market'
WHEN classification__c = 'Enterprise' THEN 'Enterprise'
ELSE 'Unknown'
END
business_rule: "Segment-mapping bevroren in 2024 door Sales-Ops."
data_steward: "alice@example.com"
last_review: "2026-04-01"
Veelvoorkomende valkuilen in de requirements-fase
- "We willen alle data" — een non-requirement. Dwing tot focus op concrete vragen en business processen.
- Geen sponsor met beslissingsmandaat — projecten zonder een directielid die knopen kan doorhakken modderen jarenlang voort.
- Velddefinities die per afdeling verschillen — wat is een "actieve klant"? Documenteer dit centraal voor je bouwt, niet erna.
- Te veel processen tegelijk — eerst sales, dan inkoop, dan voorraad. Niet drie tegelijk vanaf dag één.
- Geen moment van "klaar" — definieer per analytical question expliciet de acceptatiecriteria, anders blijven requirements eindeloos open.
Een ontwerpdocument-template
Vat alles samen in een 5-10 pagina's lang ontwerpdocument:
- Doel en scope (wat wel, wat niet)
- Stakeholders en rollen
- Business processen en analytical questions
- Niet-functionele requirements
- Bus matrix
- Conceptual model
- Patroon-keuze met motivatie (Kimball / Inmon / DV / hybride)
- Platformkeuze met motivatie (Snowflake / BigQuery / Synapse / Fabric)
- Logical model — kerntabellen
- Naming conventions
- Implementatieplan en mijlpalen
Key takeaways
- Begin bij de business — vraag naar beslissingen, niet naar velden.
- Niet-functionele eisen bepalen de platformkeuze, onderschat ze niet.
- De bus matrix dwingt expliciete keuzes en vindt conformed dimensions.
- Drie modelleerniveaus (conceptual / logical / physical) voorkomen verwarring.
- Naming conventions zijn niet optioneel; leg ze vast voor je begint.
- MoSCoW houdt scope onder controle. Build a slice, not a slab.
Veelgestelde vragen
Hoe verzamel je requirements voor een datawarehouse?
Begin bij de business met één-op-één-gesprekken. Stel een lijst van analytical questions op — concrete vragen die stakeholders willen beantwoorden. Deze vragen worden je acceptatiecriteria. Vraag naar beslissingen, niet naar velden.
Wat is een bus matrix?
Business processen op de rij-as, dimensies op de kolom-as, met vinkjes waar dimensies relevant zijn. Het laat zien welke dimensies conformed moeten worden gebouwd, en dwingt stakeholders tot expliciete scope.
Wat zijn functionele en niet-functionele requirements?
Functionele requirements beschrijven wat het warehouse moet kunnen. Niet-functionele requirements beschrijven hoe goed: data freshness, latency, concurrency, volume, security, compliance, beschikbaarheid en budget. Niet-functionele eisen bepalen de platformkeuze.
Wat is het verschil tussen conceptual, logical en physical model?
Conceptual model: alleen entiteiten en relaties in business-taal. Logical model: voegt attributen, datatypes en patroonkeuze toe. Physical model: concrete DDL voor je platform met partitioning, clustering en distribution keys.
Welke naming conventions gebruik je?
Lowercase met underscores. Prefixen: dim_, fact_, stg_, int_, hub_, sat_, link_. Surrogate keys op _key, business keys op _id. Booleans op is_/has_. Datums op _date of _at/_ts. Leg afspraken vast in NAMING.md.
Wat is MoSCoW-prioritering?
Must have (zonder dit faalt het), Should have (belangrijk niet kritiek), Could have (leuk om te hebben), Won't have (expliciet uit scope). Een MVP dekt de Must-haves voor één business proces — niet alles voor alle processen tegelijk.