Lab 1 - TDD Aggregate Root - Create Kitchen Commands with Business Logic and Invariants

1. Summary

The first responsibility of an Aggregate is to maintain the business invariants of the domain concept it represents, and to ensure that these invariants are transactionally consistent.

In this lab, we’ll implement these concerns by treating the Aggregate as a state machine. It will ensure that Aggregates only transition state when the appropriate conditions are met.

We’ll complete 18 stories:

  1. When a KitchenOrder is created, its status is NEW.

  2. When a cook starts preparing a KitchenOrder, its status becomes PREPPING.

  3. Only a NEW KitchenOrder can begin prepping.

  4. When a cook starts baking a KitchenOrder, its status becomes BAKING.

  5. Only a PREPPING KitchenOrder can begin baking.

  6. When an assembler starts assembling a KitchenOrder, its status becomes ASSEMBLING.

  7. Only an BAKING KitchenOrder can begin assembly.

  8. When an assembler finishes assembling a KitchenOrder, its status becomes ASSEMBLED.

  9. Only an ASSEMBLING KitchenOrder can finish assembly.

  10. When a Pizza is created, its status is NEW.

  11. When a cook starts preparing a Pizza, its status becomes PREPPING.

  12. Only a NEW Pizza can begin prepping.

  13. When a cook finishes preparing a Pizza, its status becomes PREPPED.

  14. Only a PREPPING Pizza can finish prepping.

  15. When a cook starts baking a Pizza, its status becomes BAKING.

  16. Only a PREPPED Pizza can begin baking.

  17. When a cook finishes baking a Pizza, its status becomes BAKED.

  18. Only a BAKING Pizza can finish baking.

You can run com.mattstine.dddworkshop.pizzashop.suites.Lab1Suite to check your progress in this lab.

2. Instructions

  1. KitchenOrder and Pizza will be responsible for maintaining business invariants.

  2. Each command that an actor can execute on an Aggregate exists as a method on that Aggregate. The command method is responsible for maintaining the business rules and executing the state transitions.

  3. For example, when a cook starts baking a pizza, the Pizza.startBake() method is called.

  4. Implement each of these command methods on the two Aggregates.

  5. Each state of an Aggregate has a status method that explicitly exposes the state of the state machine, but hides the implementation.

  6. For example, to check if a pizza is baking, the Pizza.isBaking() method is called.

  7. Implement each of these status methods on the two Aggregates.

  8. If you’re looking for hints on how to implement these command and status methods, take a look at the Aggregates in the Ordering or Payments contexts.