I choose the hexagonal (ports and adapters) for the architecture because It provides isolation between layers, keeping the domain and service core with no dependencies besides the business logic.
├── cmd // entry points
└── internal
├── config // load app configs
├── core
│ ├── domain // business domain entities
│ ├── ports // services and repository interfaces
│ ├── services
│ │ └── cartservice
├── handlers // requests handlers
├── infra
| └── server // http server
├── repositories // database in-memory
| ├── cartrepository
└── └── itemrepository
The app starts with the data below pre-loaded:
Items
| Item_id | Name | Price (USD) |
|---------|---------|-------------|
| 10 | T-shirt | 12.99 |
| 20 | Jeans | 25.00 |
| 30 | Dress | 20.65 |
Carts(User)
User ID: bba82f7a-caa1-4587-819b-6db46e14fc60
For simplicity, the app has no shared transaction isolated context.
The app uses in-memory storage, so It's not able to horizontal scale out of the box.
Requirements:
- Docker
- Docker-compose
$ docker build --target test -t shopping-cart . &&
docker run -t -i --rm \
-v .:/usr/app:delegated \
--name shopping-cart-test \
shopping-cart \
go clean --testcache && \
go test -cover ./...
$ cp .env.sample .env && docker-compose up
There's only one user cart pre-loaded, so all requests must include the header --header 'user_id: bba82f7a-caa1-4587-819b-6db46e14fc60'
curl --location 'http://localhost:8080/shopping-carts' \
--header 'user_id: bba82f7a-caa1-4587-819b-6db46e14fc60'
- quantity param is optional
curl --location --request POST 'http://localhost:8080/shopping-carts/items?item_id=20&quantity=3' \
--header 'user_id: bba82f7a-caa1-4587-819b-6db46e14fc60'
curl --location --request DELETE 'http://localhost:8080/shopping-carts/items/10' \
--header 'user_id: bba82f7a-caa1-4587-819b-6db46e14fc60'