Due to the scale needed, retailers usually rely on multiple distributed systems each one involving many components.
This means that the design and implementation of even only one element has an high level of complexity also to support the versatility required by the business domain.
It is pretty common to use Domain-Driven Design to analyze an area of the business, a DDD subdomain, maybe with some EventStorming sessions, with the goal of getting a better awareness of concepts, processes and rules that belong to it and start talking all the same ubiquitous language.
Multiple subdomains cooperate by means of integration events and web APIs and even within a single subdomain it is possible to find one or more microservices that, whenever possible, use a choreography rather than orchestration integration model.
The implementation of a single microservice is often based on the ports and adapters pattern also known as hexagonal architecture.
Moreover, when different use cases need different levels of scale and flexibility, the CQRS pattern is used, resulting in different write and read models often needing polyglot persistence, sometimes in combination with Event Sourcing.
This is what goes under the term Event-Driven Architecture.
The goal is usually taming complexity by decomposing a huge system in multiple simpler parts with only one responsibility. Unfortunately this brings along a big increase in the overall system complexity and the challenges related to its implementation, deploy (e.g. SDLC, release management, containerization and container orchestrators like Kubernetes), handling (observability), maintenance, evolution.
One of the key element for any retailer is the checkout which allows customers to complete a purchase and the company to be paid and make profit.
Considering the goal of this kata is to focus on simple design and coding style and skills, the solution should be as simple as possible.
It would be overkill to design and implement a full system with one or more microservices, using DDD, CQRS, ES, a full-fledged hexagonal architecture and code with full instrumentation for observability (logging, application and business metrics monitoring, distributed tracing at least).
The focus should be on the business logic and its implementation with a trade-off on the completeness of functionalities usually exposed by services belonging to other subdomains like catalog, pricing, billing.
Tests should be used to guarantee that main use cases are covered and the software is maintainable and evolvable without introducing misbehaviors or regressions.
As per the build and test phase few or no scripts should be used and it wouldn't make senso to introduce Kubernetes and Helm at this stage.
A possible C# .NET Standard 2.0 implementation of the solution was developed using Visual Studio.
Code has been tested for the main use cases and behaviors, but no benchmark or test coverage has been used.
The build and test phase supports Docker
The high-level class diagram has been created with PlantUML:
Further details are provided by the following class diagrams created by Visual studio.
Namespace SalesTaxesKata.Domain.Sales
Namespace SalesTaxesKata.Domain.Taxation
Namespace SalesTaxesKata.Domain.Shopping
Namespace SalesTaxesKata.Domain.Payment
- Install .NET Core SDK
- Execute the following commands from the terminal:
git clone https://github.com/luigiberrettini/sales-taxes-kata cd sales-taxes-kata
- Run tests by executing the following commands from the terminal:
cd src dotnet test # OR ./build/scripts/bootstrap.sh # Linux shell .\build\scripts\bootstrap.ps1 # Windows PowerShell
- Install Docker
- Execute the following commands
git clone https://github.com/luigiberrettini/sales-taxes-kata cd sales-taxes-kata docker build . -t dnjq # Can be run multiple times after editing the code docker run -v $(pwd):/app -w /app --rm dnjq ./build/scripts/bootstrap.sh docker image rm dnjq
- Install VirtualBox and its Extension Pack
- Install Vagrant
- Download the Vagrantfile provided with this repo
- Execute the command
vagrant up
- Connect via SSH to localhost on port 2200 with username
vagrant
and passwordvagrant
- Execute step 2 of the previous section