Deltabeer is written in mainly Kotlin using Gradle as a build tool and leveraging the Spring Boot framework. Hibernate is used for persistence.
This program follows the Repository MVC pattern (Model–View–Controller) with DTOs for transferring data through a REST -like JSON API, and DAOs for accessing and interacting with the database. A third object type without a postfix is used internally for business logic.
---
title: Model–View–Controller with a repositry
---
graph TD
Browser -->|Requests| Controller
Controller -->|Calls| Service
Service -->|Interacts with| Repository
Repository -->|CRUD Operations| Database
Repository -->|Returns Data| Service
Service -->|Returns Data| Controller
Controller -->|Selects| View
View -->|Renders| Browser
Service -->|Business Logic| Service
Database -->|Returns Data| Repository
DTOs live in the View-layer, whereas DAOs live in the Repository-layer. The Controller-layer is the interface between DTOs and internal objects which are used by Services in the Model-layer. The Model-layer also translates between internal objects and DAOs that represents objects in the database.
Spring takes care of the Controller- and View-layers using Decorations and Hibernate handles the Repository layer, so we mostly have to care about the Model-layer. This includes configuration and business login in the Service.
The database is modelled using Hibernate decorations (using spring.jps.hibernate.ddl-auto: create
and
spring.jps.show-sql: true
),
and then copied over to regular SQL creation queries to use with Flyway for better
control over the database.
Normally hibernate.ddl-auto
is set to validate
,
so remember to update the Flyway migrations when changing the database using Hibernate.
The main database table is the Users table which — as the name indicates, contains the users registered in the system. Each user is given a unique ID which is not exposed. Users are retrieved using either the cardID or e-mail field which must both be unique to each user. This opens up for the possibility of changing a user's cardID using e-mail or updating the e-mail using the cardID.
A wallet is created when a user first performs a transactions, each user can only have one wallet. This wallet is stored in the aptly named _Wallets table. Each wallet transaction (i.e. buying or spending tokens) is stored in the Transactions table for auditing purposes. It should be possible to re-build and verify a Wallet balance using the transaction log for auditing purposes.
For personalisation and fun, it's possible to register different properties on a user,
these properties are defined in
the UserPropertyType enum as
either TITLE
, COMMENT
, CREDIT
or OTHER
.
The CREDIT
property is used to give users the possibility of having a negative wallet balance.
A planned feature is the use of this system to register items and keeping track of borrowed items by user, though this can probably be scrapped if there's no need for the feature. This could perhaps be split into a different application.
When running locally the local-h2
can be used to spin up an in-memory H2-database.
This profile is also set up to run the migrations present in the db/testdata
resources folder,
i.e. populate the database with testdata.
There is also a local-postgres
profile for connecting with a local PostgreSQL database.
JUnit 5 is used for testing. Developers should aim to write simple unit tests for each new feature or fix they create. This is to avoid regressions and maintain a stable codebase.
To package this application into a container image we're using the Google Jib Gradle Plugin. To build the project to your local docker instance navigate to the root of this project and run
./gradlew jibDockerBuild
You should then be able to run a containerised instance of this project using the in-memory H2-database by executing
docker run -it --rm -p 8080:8080 deltabeer:$(./gradlew -q printVersion) --spring.profiles.active=local-h2
Developers should aim to use Conventional Commits for concise commit comments explaining what they've changed.
It would also be good to introduce a Changelog following Keep A Changelog practises, and follow Semantic Versioning.