The aim of the exercise is to build the pricing portion of a self-service checkout machine. This exercise focuses mostly on the pure Domain, but you can also try structuring it according to Hexagonal Architecture for the "receipt printing" feature.
The supermarket has a catalog with different types of products (rice, apples, milk, toothbrushes,...). Each product has a price, and the total price of the shopping cart is the total of all the prices.
The supermarket runs special deals, such as:
- Buy two toothbrushes, get one half-off
- 10% discount on rice
- Bags of 1 kg of oranges $4 instead of $5.
- and so on
These are just examples: the actual special deals changes each week, so needs to be easily configurable.
A story to start with is:
Given a toothbrush product that has a price of $1
When toothbrush is added to the cart
Then querying cart's total price returns $1.00
And you can follow up with:
Given toothbrush with price of $1
And there is a deal: buy two toothbrushes get one half-off
When two toothbrushes are added to the cart
Then querying cart's total price returns $1.50
Start with the test, of course.
Think about a "baseline" test: what is the cart's total price when it's empty?
Then when adding one product.
Then when adding multiple products.
This path follows the ZOM in the ZOMbie acronym: Zero, One, Many/More complex (while considering Boundaries, Interfaces, and Exceptional cases).
When handling a "receipt printing" story, think about where that might go.
In Hexagonal Architecture, all I/O goes into a separate class and package (e.g., adapter.out.console.receipt.ReceiptPrinter
), while keeping the Domain "pure" in its own package (e.g., domain.Cart
).
The goal of the exercise is to implement pricing code in the cart that can handle different scenarios, such as the following:
-
The client should get a receipt with the list of products and the total price
-
The code should be able to handle the following scenarios:
- Buy 2 of the same item, get one 50% off
- Buy 3 of the same item, get one free
- 10% discount on certain products: 10% discount on 1kg packets of rice
- Buy 3 items in a single category (e.g., produce, i.e., fruits and vegetables) and get
- Fixed $ discounts (e.g., bag of 1kg of oranges costs $4 instead of $5)
- Discounts based on day of the week (e.g., Friday Special: sourdough bread 30% off)
-
It should be able to handle combinations of the above scenarios, when there is more than one special deal in the shopping cart items.
Adapted from http://codekata.com/kata/kata01-supermarket-pricing/ and https://github.com/serenity-dojo/kata-supermarket-checkout.