This project is intended to showcase my software engineering and development skills.
It is a demo project but incorporates key software design and clean code principles.
This project represents a backend module of a basic Store Management System (SMS), it provides APIs to:
- Create cart with/without items.
- Get cart details.
- Add/remove items to/from cart.
- Checkout cart (inc. processing applicable discount offers).
Items examples:
- Bread - 1.20€ per Packet
- Milk - 0.85€ per Bottle
- Tuna - 1.65€ per Tin
Offers examples:
- 15% discount on Bread this week
- Buy 2 bottles of Milk and get 50% discount on Bread
- 20% direct discount on cart
Applied Design Pattern | Use Case | Example |
---|---|---|
Strategy | Define condition/execution strategies for different types of offers | Discount Strategies |
Builder/Director | Build cart objects | Cart Builder |
Factory Method | Create repositories based on config properties | Items Repository |
Singleton | Maintain unique instance of several models (using CDI @ApplicationScoped ) |
Cart/Offer Services |
- Code maintains dependency on abstraction rather than concrete objects (Inversion of Control).
- DI framework: Jakarta Context Dependency Injection (CDI).
- KISS: code is written as SIMPLE as possible.
- DRY: code relies on re-usability and abstraction to prevent duplication.
- YAGNI: no unnecessary functionalities are implemented (except for some cases for the sake of this demo).
- Readability: descriptive & self-explanatory classes, methods, and variable names.
- Convention: code follows consistent and standard naming conventions.
- Code is self-explanatory.
- Code is documented in javadoc format.
- Clarification comments are added when necessary.
- Nothing is commented out!
- Extensive test cases for happy path and edge cases.
- Unit tests organized in AAA - Arrange, Act, Assert pattern.
- Testing framework: TestNG
- Mocking library: Mockito
- Code is fully OOP (thanks to Java!).
- Abstraction: code relies on abstraction to handle complexity (DI, design patterns, ...).
- Encapsulation: code implements restricted access to data members and methods (with getters/setters when required).
- Inheritance: classes are structured in hierarchical manner.
- Polymorphism: ex. via strategy design pattern.
- API contracts use custom deserializers to isolate api response from internal data fields (see Contracts and Adapters).
- API errors follow IETF RFC 7807 standard (see APIErrorResponseJsonAdapter.java).
- Used C4 model to design the system in multiple levels of abstraction.
- High level diagrams can be found here.
To deploy the project on your device, clone it and run the following:
To compile java files and create executable war/jar packages:
mvn clean package
To create docker network (first time only):
docker network create smsjavademo_net
To build docker image and start container:
docker-compose up --build
To run APIs, simply use attached Postman collection in /docs/postman.
GET /sms/api/engineering/ping
POST /sms/api/cart
- Body - raw (json):
[... "itemIdentifier" ...]
GET /sms/api/cart/{cartId}
POST /sms/api/cart/{cartId}/items
Parameter | Type | Description |
---|---|---|
itemIdentifier |
String |
Required. Item to be added |
DELETE /sms/api/cart/{cartId}/items/{itemIdentifier}
GET /sms/api/cart/{cartId}/checkout
Here are some examples of APIs response: