Project 4: Product Catalog Rules DSL

Build a business-readable DSL for product bundles, constraints, and promotions with deterministic rule execution and explainable outcomes.

Quick Reference

Attribute Value
Difficulty Level 3: Advanced
Time Estimate 2-3 weeks
Main Programming Language Python
Alternative Programming Languages Ruby, Elixir, TypeScript
Coolness Level Level 4: Hardcore Tech Flex
Business Potential 3. The “Service & Support” Model
Prerequisites Projects 2-3, domain modeling basics, event-driven logic
Key Topics Domain modeling, rule semantics, conflict resolution, explainability

1. Learning Objectives

By completing this project, you will:

  1. Design a DSL vocabulary aligned with merchandising/business operations.
  2. Parse product and rule declarations into executable structures.
  3. Execute rules in deterministic order with trace output.
  4. Resolve rule conflicts using explicit priorities and caps.
  5. Produce user-facing diagnostics non-programmers can understand.

2. All Theory Needed (Per-Concept Breakdown)

Domain Modeling as Language Design

Fundamentals A business DSL fails when it mirrors implementation details instead of business language. Domain modeling identifies stable nouns, verbs, and constraints in the target context, then maps them to syntax and semantics. In a product catalog domain, nouns include products, categories, bundles, carts, discounts, and constraints. Verbs include include, require, apply, suggest, block. Good modeling balances expressive power and operational safety. Too little expressiveness forces business teams back into code. Too much expressiveness creates unreadable rules and unpredictable behavior. The model should be intentionally narrow but complete for core workflows.

Deep Dive into the concept Domain modeling starts with bounded context. Decide what this DSL controls and what stays outside. For this project, focus on catalog-level decisions: compatibility, bundle logic, and discount policy. Exclude payment processing and shipment optimization. This keeps semantics coherent.

Next, define canonical entities and relationships:

  • Product: id, category, price, attributes.
  • Bundle: named product set + discount metadata.
  • Rule: condition + action + optional message.
  • Cart: runtime fact set of selected items.

Then map these to language constructs. Example mapping:

  • Entity declaration -> PRODUCT ... { ... }
  • Bundle declaration -> BUNDLE ... { ... }
  • Dynamic behavior -> RULE ... { when: ... apply: ... }

Syntax should optimize for business readability. Prefer declarative statements over control-flow-heavy scripting. For instance, require: laptop.memory >= 32GB is clearer than imperative pseudo-code.

Semantic design must answer execution-time questions:

  • Are rules stateless or stateful?
  • Do rules run once or iteratively until stable?
  • Can rules modify facts used by later rules?

For this project, use deterministic phase-based execution: validate constraints, then suggestions, then pricing actions. This avoids hidden cyclic behavior and simplifies explanation.

Modeling also includes constraint language design. Constraints often involve typed comparisons and cross-entity references. Define units (GB, percentage, currency) and normalization strategy. If units are not normalized, subtle bugs appear (16GB vs 16384MB).

Error UX is part of domain modeling. Rule authors need diagnostics using business terms, not parser internals. “Unknown field mem_size in PRODUCT laptop” is useful. “Symbol resolution failed” is not.

Governance matters in production-like DSLs. Track rule version, author, and change notes. Even in this learning project, include metadata schema conceptually to prepare for team workflows.

Finally, domain models evolve. Design extension points: new rule actions, new entity attributes, and deprecation strategy. Language design is product design over time, not one-time grammar writing.

How this fit on projects

  • Primary design driver of this project.
  • Builds on expression semantics from Project 3.
  • Prepares architecture for Project 7.

Definitions & key terms

  • Bounded context: explicit scope where language terms are consistent.
  • Entity model: typed representation of core domain objects.
  • Declarative rule: statement of what should hold, not step-by-step how.
  • Constraint: condition that must be true for validity.
  • Policy surface: set of decisions exposed to business authors.

Mental model diagram

Business vocabulary
   |
   v
DSL declarations --> Parsed model --> Rule executor --> Cart outcomes + explanation

How it works

  1. Discover business nouns/verbs.
  2. Define language constructs for them.
  3. Attach typed semantics to each construct.
  4. Execute with deterministic phase order.
  5. Report outcomes/errors in business terms.

Minimal concrete example

RULE storage_memory_constraint {
  when: laptop.storage == "2TB"
  require: laptop.memory >= 32GB
  error: "2TB storage requires at least 32GB memory"
}

Common misconceptions

  • “Business DSL means non-technical, therefore loose.” -> it must still be formally precise.
  • “Domain terms can be inferred later.” -> ambiguity compounds quickly.
  • “One giant generic rule language fits all domains.” -> domain fit beats generic flexibility.

Check-your-understanding questions

  1. Why define bounded context before grammar?
  2. What is gained by phase-based execution?
  3. How should diagnostics differ for parser errors vs business rule violations?

Check-your-understanding answers

  1. It prevents scope creep and term ambiguity.
  2. Determinism and explainability.
  3. Parser errors discuss syntax; rule violations discuss business constraints.

Real-world applications

  • E-commerce promotion engines.
  • Insurance underwriting rule sets.
  • Subscription feature entitlement systems.

Where you’ll apply it

  • §3.1 build scope and exclusions.
  • §4.2 component model.
  • §5.11 rule authoring decisions.
  • Also used in Project 7.

References

  • Fowler, Domain Specific Languages, semantic model chapters.
  • Russell & Norvig, rule-based systems basics.

Key insights A rules DSL is successful when business intent maps directly to executable semantics without translation gaps.

Summary Domain modeling transforms fuzzy business requirements into explicit language constructs and runtime contracts.

Homework/Exercises to practice the concept

  1. List nouns/verbs for your own catalog domain.
  2. Classify which constructs belong in DSL vs application code.
  3. Write 3 rule errors in plain business language.

Solutions to the homework/exercises

  1. Include product, cart, bundle, promo, compatibility, threshold.
  2. Keep domain policy in DSL; keep IO/integration in app code.
  3. Example: “Accessory discount requires at least 3 accessories in cart.”

Rule Execution Semantics, Conflicts, and Explainability

Fundamentals Rule engines are semantics engines. The same set of rules can produce different outcomes if execution order, conflict policy, and stopping criteria are not explicit. Explainability is equally important: business stakeholders need to know why discounts were or were not applied. A useful DSL runtime records trace events: condition matched, action applied, conflict resolved, cap enforced. Deterministic execution plus transparent traces create trust and simplify debugging.

Deep Dive into the concept Begin by defining execution model. Common options:

  1. single-pass in fixed order,
  2. priority queue,
  3. iterative forward-chaining until no changes.

For this project, use priority + phase model:

  • Phase 1: hard constraints (require, block).
  • Phase 2: suggestions/recommendations.
  • Phase 3: pricing actions. Inside each phase, apply descending priority and deterministic tie-breaker (e.g., rule id lexical order).

Conflict resolution needs explicit strategies. Typical conflict classes:

  • competing discounts on same target.
  • action contradicts prior rule (set price vs apply discount).
  • cumulative discounts exceed cap.

Recommended policy:

  • highest-priority rule applies first,
  • caps enforced as post-processing guard,
  • conflict events logged with chosen winner and suppressed rules.

Explainability data model should include:

  • rule id,
  • evaluated condition result,
  • action result,
  • input facts snapshot hash,
  • timestamp/order index,
  • conflict metadata if applicable.

Do not rely on free-form logs only; store structured traces for testing and UI presentation.

Semantic safety includes idempotency. Re-running engine on same cart should not keep stacking effects unless explicitly configured. Use normalized action model where each rule emits proposed effects, then a reducer computes final state once.

Avoid hidden side effects in condition evaluation. Conditions should be pure reads. Actions mutate through controlled effect pipeline. This separation prevents non-deterministic outcomes and simplifies replay.

Performance: evaluate conditions with indexed fact access (by product/category), not full scans when avoidable. But preserve correctness first.

Testing conflict behavior is mandatory. Create fixtures where two rules intentionally collide. Assert chosen outcome and trace content. Add determinism tests across repeated runs.

This semantic discipline is direct preparation for enterprise-grade engines in Project 7.

How this fit on projects

  • Determines runtime correctness in this project.
  • Direct bridge to inference/explainability in Project 7.

Definitions & key terms

  • Conflict resolution: policy for contradictory/competing rule outcomes.
  • Rule trace: structured record of evaluation and action results.
  • Idempotency: repeated execution with same inputs yields same outputs.
  • Effect reducer: stage that merges proposed actions deterministically.
  • Tie-breaker: deterministic ordering when priority equals.

Mental model diagram

Facts -> Condition evaluator -> Proposed effects -> Conflict resolver -> Final cart state
                      |                               |
                   rule trace ------------------------+

How it works

  1. Load parsed rules and cart facts.
  2. Evaluate conditions by phase/priority.
  3. Emit proposed effects.
  4. Resolve conflicts/caps.
  5. Apply final effects and emit trace.

Minimal concrete example

Rule A: apply 15% accessory discount
Rule B: cap total discount at 20%
Input: discount proposals total 28%
Output: final applied discount 20%, trace includes cap reason

Common misconceptions

  • “Rule order in file is enough policy.” -> it is fragile and opaque.
  • “Explainability can be added later.” -> requires structured data from start.
  • “Forward-chaining always needed.” -> many domains need deterministic phase passes only.

Check-your-understanding questions

  1. Why separate condition evaluation from effect application?
  2. How do you ensure deterministic conflict handling?
  3. What should trace include to support audits?

Check-your-understanding answers

  1. It preserves purity and simplifies conflict resolution.
  2. Priority plus explicit tie-breakers.
  3. rule id, condition result, action outcome, conflict decisions.

Real-world applications

  • pricing and promotions systems.
  • compliance eligibility engines.
  • anti-fraud pre-check policy layers.

Where you’ll apply it

  • §3.2 requirements 3-6.
  • §4.1 execution architecture.
  • §6.2 conflict test cases.

References

  • Fowler Rules Engine article.
  • Drools docs for conflict-handling patterns.

Key insights Without explicit conflict and trace semantics, rule DSLs become un-debuggable policy black boxes.

Summary Deterministic rule execution plus structured explainability is the difference between demo DSLs and production-ready policy systems.

Homework/Exercises to practice the concept

  1. Define three conflict scenarios and resolution policies.
  2. Draft trace schema fields.
  3. Design one idempotency test.

Solutions to the homework/exercises

  1. Competing discounts -> higher priority wins; equal priority -> stable lexical tiebreak.
  2. Include rule id, phase, priority, condition result, action effect, timestamp index.
  3. Execute same cart/rules twice; final totals and trace hashes must match.

3. Project Specification

3.1 What You Will Build

A DSL-driven catalog rules engine that can:

  • define products and bundles,
  • author conditional business rules,
  • evaluate cart events and emit outcomes with trace explanations.

Excluded:

  • distributed execution,
  • UI authoring tool,
  • persistent versioned rule storage (extension).

3.2 Functional Requirements

  1. Parse product, bundle, and rule declarations.
  2. Support conditional expressions and actions (suggest, apply, require, block).
  3. Execute rules in deterministic phase order.
  4. Resolve conflicts with explicit priority policy.
  5. Emit human-readable and structured traces.
  6. Return clear errors for invalid rules or data mismatches.

3.3 Non-Functional Requirements

  • Performance: evaluate 1k-rule set on 100-item cart under 250 ms baseline.
  • Reliability: identical inputs produce identical outputs and trace hash.
  • Usability: business-readable diagnostics and trace messages.

3.4 Example Usage / Output

Input event: add laptop(memory=16GB,storage=2TB)
Result:
- constraint violation: storage_memory_constraint
- message: "2TB storage requires at least 32GB memory"
- suggested action: upgrade memory option

3.5 Data Formats / Schemas / Protocols

Rule {
  id: string
  phase: enum(CONSTRAINT,SUGGESTION,PRICING)
  priority: int
  when: ExprAST
  actions: list<Action>
}
Action = Suggest | ApplyDiscount | Require | Block

3.6 Edge Cases

  • conflicting discounts on same item.
  • cyclic dependencies in constraints.
  • unknown product attributes in rules.
  • rule references entity not in cart.

3.7 Real World Outcome

Business and engineering can collaborate on product logic via readable rules, with deterministic engine output and explanation logs.

3.7.1 How to Run (Copy/Paste)

cd project_based_ideas/COMPILERS_RUNTIMES/DOMAIN_SPECIFIC_LANGUAGES_DSL_PROJECTS
make p04-test
./bin/p04-catalog-engine --rules fixtures/p04_rules.dsl --cart fixtures/p04_cart.json

3.7.2 Golden Path Demo (Deterministic)

p04_cart.json always yields the same applied discounts and same trace hash.

3.7.3 If CLI: exact terminal transcript

$ ./bin/p04-catalog-engine --rules fixtures/p04_rules.dsl --cart fixtures/p04_cart.json
[ok] rule_count=12
[ok] applied_actions=3
[ok] final_total=2141.60
[ok] trace_hash=bac27211
exit=0

$ ./bin/p04-catalog-engine --rules fixtures/p04_bad_unknown_attr.dsl --cart fixtures/p04_cart.json
[error] SemanticError: unknown attribute 'mem_size' in rule storage_memory_constraint
[hint] valid attributes: memory, storage, color
exit=2

4. Solution Architecture

4.1 High-Level Design

DSL source -> Parser -> Rule model -> Execution planner -> Evaluator -> Effect reducer -> Outcome + trace

4.2 Key Components

Component Responsibility Key Decisions
DSL parser parse entities/rules reuse expression parser from P03
Rule planner phase + priority ordering deterministic sequence
Evaluator condition checking pure reads only
Reducer conflict and cap resolution explicit policies
Trace writer explanation records structured + human text

4.4 Data Structures (No Full Code)

TraceEvent {
  seq: int
  rule_id: string
  phase: string
  condition_result: bool
  effect_result: string
  conflict_note?: string
}

4.4 Algorithm Overview

Key Algorithm: Phase-Based Rule Execution

  1. Sort rules by phase then priority desc then id asc.
  2. Evaluate when clause for each rule.
  3. Collect proposed actions.
  4. Reduce actions with conflict/cap policies.
  5. Apply final actions and emit trace events.

Complexity Analysis

  • Time: O(r log r + r * e) where r rules, e avg expression eval cost.
  • Space: O(r + a) for sorted rules and action proposals.

5. Implementation Guide

5.1 Development Environment Setup

mkdir -p bin fixtures tests

5.2 Project Structure

p04-product-rules/
├── src/
│   ├── parser.*
│   ├── rule_model.*
│   ├── planner.*
│   ├── evaluator.*
│   ├── reducer.*
│   └── trace.*
├── fixtures/
└── tests/

5.3 The Core Question You’re Answering

“How do I let non-programmers express pricing and compatibility logic safely without losing deterministic execution?”

5.4 Concepts You Must Understand First

  1. Domain modeling and bounded context.
  2. Expression AST reuse from P03.
  3. Conflict-resolution policy design.
  4. Structured explainability traces.

5.5 Questions to Guide Your Design

  1. Which actions are declarative enough for business authors?
  2. Should conflicts fail hard or resolve with priorities?
  3. How do you keep traces readable yet machine-parseable?
  4. What guarantees make reruns deterministic?

5.6 Thinking Exercise

Create two discounts that conflict and define precise resolution policy plus user-facing explanation line.

5.7 The Interview Questions They’ll Ask

  1. How does domain modeling influence grammar quality?
  2. What conflict strategy did you choose and why?
  3. How do you make rule outcomes explainable?
  4. How would you prevent rule sprawl as teams grow?
  5. Where would you add type checking in this pipeline?

5.8 Hints in Layers

Hint 1: start with one entity and one rule action.

Hint 2: keep execution planner independent from parser.

Hint 3: represent actions as data, not imperative callbacks.

Hint 4: generate trace for every rule, matched or not.

5.9 Books That Will Help

Topic Book Chapter
DSL semantic models Domain Specific Languages Ch. 11-14
Rule systems AIMA rule-based reasoning chapters
Compiler semantics mindset Engineering a Compiler semantic analysis

5.10 Implementation Phases

Phase 1: Foundation (4-6 hours)

  • parse entities + simple rules.
  • evaluate one action type.

Checkpoint: one deterministic rule outcome.

Phase 2: Core Functionality (8-14 hours)

  • add priority phases and conflict reducer.
  • add trace schema and output.

Checkpoint: conflict fixtures pass with expected winner.

Phase 3: Polish & Edge Cases (6-10 hours)

  • improve diagnostics and business wording.
  • add deterministic hash of outcomes and traces.

Checkpoint: golden + failure demos stable.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Execution model file-order / priority-phase / forward-chaining priority-phase deterministic + manageable complexity
Conflict strategy fail / max-priority / combine-all max-priority + cap predictable commerce behavior
Trace format plain text / structured JSON / both both audit + human readability

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Parser tests syntax validity entity/rule declarations
Execution tests semantic correctness applied actions and totals
Conflict tests resolution guarantees competing discount fixtures

6.2 Critical Test Cases

  1. memory-storage constraint violation message.
  2. dual discount conflict with cap enforcement.
  3. identical run produces identical trace hash.
  4. unknown attribute error includes valid alternatives.

6.3 Test Data

fixtures/p04_rules.dsl
fixtures/p04_cart.json
fixtures/p04_conflict.dsl
fixtures/p04_bad_unknown_attr.dsl

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

Pitfall Symptom Solution
mixing parse and runtime semantics hard-to-debug failures strict pipeline separation
hidden rule order dependence flaky outcomes explicit phase/priority sorting
missing trace detail impossible business debugging structured event model

7.2 Debugging Strategies

  • rule-by-rule dry-run mode with condition outputs.
  • trace diff tool between two rule versions.

7.3 Performance Traps

Evaluating every rule against every cart change without indexing can degrade quickly; pre-index by affected entity/category.


8. Extensions & Challenges

8.1 Beginner Extensions

  • add message templates with variable interpolation.
  • add rule tags (seasonal, safety, marketing).

8.2 Intermediate Extensions

  • add rule versioning metadata and change history.
  • add simulation mode comparing two rulesets.

8.3 Advanced Extensions

  • add incremental evaluation for cart deltas.
  • add governance checks (linting for conflicting policies).

9. Real-World Connections

9.1 Industry Applications

  • e-commerce promotion engines.
  • telecom plan recommendation systems.
  • venmo/business-rules: https://github.com/venmo/business-rules
  • Drools: https://www.drools.org/

9.3 Interview Relevance

  • business rules engine architecture.
  • conflict resolution and explainability.

10. Resources

10.1 Essential Reading

  • Fowler, Domain Specific Languages.
  • Russell & Norvig, rule-based reasoning sections.

10.2 Video Resources

  • rules engine architecture talks.
  • domain modeling case studies.

10.3 Tools & Documentation

  • JSON schema tools for trace validation.
  • DSL linting/checking utilities.

11. Self-Assessment Checklist

11.1 Understanding

  • I can map business vocabulary to DSL constructs.
  • I can explain my conflict policy and tradeoffs.
  • I can explain trace schema to non-engineers.

11.2 Implementation

  • rule parser handles required constructs.
  • deterministic execution and trace hash checks pass.
  • conflict fixtures and constraint fixtures pass.

11.3 Growth

  • I documented one governance risk and mitigation.
  • I can describe how to scale to thousands of rules.
  • I can connect this project to enterprise rule engines.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • parse and execute basic rules with one action type.
  • produce readable output and at least one failure-path diagnostic.

Full Completion:

  • all minimum plus phase/priority execution, conflict reducer, structured traces.

Excellence (Going Above & Beyond):

  • simulation mode, incremental evaluation, and governance checks.

13 Additional Content Rules (Applied)

13.1 Determinism

Sort by phase/priority/id and snapshot trace hash.

13.2 Outcome Completeness

Include golden and failure transcripts with explicit exit codes.

13.3 Cross-Linking

Core expression semantics come from Project 3; final scaling path is Project 7.

13.4 No Placeholder Text

All sections are concrete and executable as a learning plan.