A backend service for a small cinema, which only plays movies from the Fast & Furious franchise.
Before running, make sure:
- you have JDK 11 or higher installed
- you have no MongoDB instance running locally
To run the application execute:
./gradlew bootRun --args='--furious-cinema.infrastructure.http-client.omdb.api-key=<your omdb api key>'
To run tests execute:
./gradlew test
Here are some details about the project.
Tools used to implement the project:
The project contains a single module.
The codebase is organized more or less according to my article.
The module implements hexagonal architecture.
Application logic resides in the core
package which is bounded by inbound and outbound ports.
The only inbound port is FuriousCinema
.
All the application logic in encapsulated behind its API.
Inbound adapters lie inside the rest
package.
REST endpoints MovieEndpoint
and RepertoireEndpoint
play their roles.
The outbound ports are
Authentications
,
Movies
,
Ratings
,
Repertoires
.
The corresponding outbound adapters, which are concrete implementations of the outbound ports, lie inside the infrastructure
package.
Inside the core
package, source code is organized using Tactical DDD
building blocks.
The core
package is divided into small mini-modules, one per aggregate.
Every mini-module encapsulates a part of the business logic behind its facade's API.
There are only integration (E2E) tests in the project. That type of tests assures the most that the project will work as expected in the real world, although they are relatively slow. For bigger projects testing application logic in separation should be considered.
Consistent naming is one of the things that makes code more readable. The project sticks to the one name per operation and per entity throughout the whole codebase (endpoints, application logic, tests).
To view and test the REST API of the project run the project and go to Swagger UI. To get the raw JSON description of the REST API go to API documentation.
Here is the list of what should be done besides of what already exists:
- some generic logging mechanism (based on function or AspectJ) to automatically log inbound and outbound ports operations.
- ArchUnit tests
Loads all available movies. Invariants:
- movie must have ID
- movie must have title
Loads a single movie. Invariants:
- movie must exist
- movie must have ID
- movie must have title
- movie must have description
- movie must have release date
- movie must have moviegoers rating
- movie must have imdb rating
- movie must have runtime
Recalculates the overall moviegoers rating of the movie because of the new user vote. Invariants:
- user must be a registered moviegoer
- movie must exist
- user mustn't vote multiple times for the same movie
- vote has rating that can be a number 1...5
- overall movie rating is an average of all user votes
Cinema owner adds an empty repertoire for a single day. Invariants:
- user must be a cinema owner
- only one repertoire per day can be added
Cinema owner adds a single movie screening to a daily repertoire by specifying a start time and price. Invariants:
- user must be a cinema owner
- movie must exist
- repertoire for a requested day must exist
- repertoire must have a free time slot for the whole screening runtime
- no more than one screening can be showed at the time
- whole screening must run on the same day
- price can not be 0 or lower
Loads all daily repertoire screenings. Invariants:
- repertoire must exist
- screening must have start time
- screening must have movie title
- screening must have price