design·lab

Design approach

Data-Driven Design

Move business rules out of your source code and into data — then write one small, fixed engine that interprets whatever rules it's given.

✗ The problem

Rules hard-coded as if/else

Every pricing tweak, new discount, or country rule means editing the function itself — and redeploying.

function priceOrder(order) {
  let total = order.spend;
  if (order.spend >= 100) total *= 0.9;
  if (order.member)      total *= 0.95;
  if (order.country === 'EU') total *= 0.97;
  // new rule? new country? → edit + redeploy…
  return total;
}
Logic is buried in code — only devs can change a discount, and every tweak risks a deploy.
✓ The approach

Externalize rules into data; write a fixed engine

The rules become a table (config / JSON). A small generic engine interprets them — behavior changes by editing data, not code.

const discountRules = [
  { label: 'spend>=100', pct: 10 },
  { label: 'member',      pct: 5  },
];

function apply(rules, order) {
  let pct = 0;
  rules.forEach(r => {
    if (r.test(order)) pct += r.pct;
  });
  return order.spend * (1 - pct / 100);
}
Data
rules table
Engine
apply(rules, order)
Result
price
✓ See it live

Edit the rules — the engine never changes

Fixed sample order: $220 spend, member customer. Toggle or add a rule row — the same apply() engine re-evaluates it instantly.

RuleDiscountState
Order
$220 · member
↓ engine
Result
✓ Takeaway

Behavior lives in data, not code

  • Change behavior without redeploying — edit a row in the rules table/config/JSON, done.
  • Non-devs can drive it — ops, pricing, or game-design teams can own the data file.
  • One engine, many rule sets — the same apply() powers every campaign, country, tier.
  • Great fit: pricing engines, feature flags, game balancing, validation rules, workflow configs.
  • Caution: data can hide logic — keep rule sets small, typed, and validated, or debugging turns into archaeology.
🎯 Relates: the engine-over-data idea is Strategy + Interpreter, and it delivers Open/Closed (new rules = new data, not new code).