Menu — version 2
Menu bounded context — the catalogue of pizzas, sizes and toppings the pizzeria sells. It is the upstream that publishes the ubiquitous language of money and toppings; Ordering shares its Currency as a shared kernel and conforms to its Topping weight (see context-map.koi). Version 2 of the published model: a kcal nutrition field was added in v2, demonstrating contract evolution with @since.
Domain Model
Section titled “Domain Model”classDiagram
class Currency {
<<enumeration>>
EUR
USD
GBP
}
class MassUnit {
<<enumeration>>
Gram
Kilogram
}
class Size {
<<enumeration>>
Small
Medium
Large
}
class Availability {
<<enumeration>>
Available
SoldOut
Seasonal
}
class Money {
<<value object>>
+Decimal amount
+Currency currency
}
class Portion {
<<quantity>>
+Decimal amount
+MassUnit unit
}
class HappyHour {
<<value object>>
+Range~Instant~ window
}
class Topping {
<<value object>>
+String name
+Money surcharge
+Portion portion
+String /key
}
class Pizza {
<<aggregate root>>
+PizzaCode id
+String name
+Size size
+Money basePrice
+Availability availability
+String description
+Set~String~ toppings
+Int kcal
+String /displayName
+String /summary
+Bool /isAvailable
+Bool /hasNutrition
}
Money *-- Currency
Portion *-- MassUnit
Topping *-- Money
Topping *-- Portion
Pizza *-- Size
Pizza *-- Money
Pizza *-- Availability
Aggregates
Section titled “Aggregates”Catalog
Section titled “Catalog”A pizza on the menu — the product the pizzeria sells. Its identity is a natural string key (PizzaCode as natural(String), no client-side New()), and being an aggregate root it gains an IPizzaRepository and joins the context’s generated IUnitOfWork. The repository block tunes the mutating set and adds intention-revealing finders.
Root entity: Pizza (identified by PizzaCode)
Repository finders:
available(): List<Pizza>bySize(size: Size): List<Pizza>
Repository operations: getById, add, update
Invariants
Section titled “Invariants”Business rules
- a pizza needs a name
Domain Types
Section titled “Domain Types”Money — value object
Section titled “Money — value object”A monetary amount in a specific currency. Never negative. Currency is a shared-kernel type owned jointly with Ordering (see context-map.koi), so the same enum flows through both contexts without translation.
| Field | Type | Description |
|---|---|---|
| amount | Decimal | |
| currency | Currency |
Business rules
- a price cannot be negative
Portion — quantity
Section titled “Portion — quantity”| Field | Type | Description |
|---|---|---|
| amount | Decimal | |
| unit | MassUnit |
Business rules
- a portion weight cannot be negative
HappyHour — value object
Section titled “HappyHour — value object”| Field | Type | Description |
|---|---|---|
| window | Range<Instant> |
Topping — value object
Section titled “Topping — value object”A topping that can be added to a pizza — pepperoni, mushrooms, extra cheese. A first-class value object so a “topping” is never just a bare string, and a rich one: it carries its own surcharge and portion weight. Exported to Kitchen, which conforms to Menu and imports it to list a ticket’s toppings.
| Field | Type | Description |
|---|---|---|
| name | String | |
| surcharge | Money | |
| portion | Portion | |
| key | String | derived |
Business rules
- a topping needs a name
Currency — enum
Section titled “Currency — enum”Values: EUR(”€”, 2), USD(”$”, 2), GBP(”£”, 2)
MassUnit — enum
Section titled “MassUnit — enum”The unit a topping’s portion weight is expressed in. Drives the unit-checked arithmetic on the Portion quantity below.
Values: Gram, Kilogram
Size — enum
Section titled “Size — enum”The three pizza sizes on offer. A plain enum used for routing and pricing.
Values: Small, Medium, Large
Availability — enum
Section titled “Availability — enum”Whether a menu item is currently sellable. Defaults to Available.
Values: Available, SoldOut, Seasonal
Coverage
Section titled “Coverage”| Kind | Covered | Total |
|---|---|---|
| aggregate | 1 | 1 |
| entity | 1 | 1 |
| enum | 4 | 4 |
| query | 0 | 2 |
| readModel | 0 | 1 |
| value | 4 | 4 |
⚠️ 3 not documented