- This is a Movie Ticket reservation system implementation of the requirements described here;
- It is based on template found here;
- Live app is deployed on heroku here;
- Sample request/response and issue test calls to live app is on apiary here.
- Dependencies are defined here and plugins here;
- Rest API based on akka-http;
- DB layer uses PostgreSQL for production, H2 DB for the
Integration Tests,
Slick with HikariCP connection pool as DB Access Layer and Flyway for DB schema management; - For json (de)serialization two frameworks are used: spray-json and play-json;
- Testing layer uses: scala test for defining test cases, scala mock for mocking dependencies in unit tests and akka-http-test-kit for api tests;
- Plugins configured for the project are: s-coverage for code test coverage, scala-style for code style checking and scala-iform for code formatting.
- Code follows the following programming concepts:
- OOP (Object Oriented Programming) principles of abstraction (all operations (meaning function, methods and procedures) and parameters are abstracted concepts of the business domain language (to be read as DDD Domain Driven Design) found in the task description, encapsulation (for example in the case classes, MoviesDao encapsulates db management logic in private implementation exposed only via public interface). Inheritance and Polymorphism is exhibited in the relation MovieId with concrete Movie implementations;
- FP (Funtional Programming) principles of immutability (all data is immutable), higher order functions, pattern matching, monadic constructions, recursion;
- Declarative style where operations describe what is done and not how;
- TDD with ScalaTest the test were created before the implementation;
- Mocking (with a tool like ScalaMock) - the db layer is mocked to only test the outer service layer in test MovieServiceTest
- Iterative Development that can be traced through git commit messages;
- Intention Revealing Operations where all parts of the method contribute to the clarity: operation name, parameter names, parameter types, and operation return type;
- Separation of concerns: each class/object/trait has clearly defined responsibilities that are fully testable and tested;
- Meaningful commit and messages - commit per implemented feature, and on important code changes that might be usefull to revisit;
- Layer architecture: Each outer layer can only access the layers from the same level or a level immediate bellow it;
- Given a different scale of the Application and longer development time several things would be done in different scenarios:
- BDD (with a tool like Cucumber) - having non technical audience as stackholders would make apropriate for a testing closer to the business level/language;
- Performance Tests (with a tool like Gatling) - having some SLA (Service Level Agreements) and thus non functional requirements would require to have this test layer in place;
- CI/CD (Continuous Integration/Continuous Delivery with a tool like Jenkins or TeamCity) pipe line set up for easier delivery of the functionality;
- Feature/Issue/Release/Time management and tracking with a tool like Jira or YouTrack
- Cloud Infrastructure Provisioning and Configuration Management (on AmazonCloudServices, OpenStack, Teraform, Puppet, Consul, etc)
- given requirements for Elastic Systems (concept of the Reactive Programming);
- Architecture diagrams of the code and infrastructure.
It's behaviour is defined by the API Integration test found here.
[info] HttpServiceTest:
[info] service
[info] - should respond with HTTP-404 Not Found for a non existing path
[info] - should respond with HTTP-405 Method Not Allowed for a non supported HTTP method
[info] registration
[info] - should respond with HTTP-200 OK when registering a new movie
[info] - should respond with HTTP-409 Conflict when trying to register an existing movie
[info] - should respond with HTTP-403 Forbidden failing validation if path and body resource identifiers are different
[info] reservation
[info] - should respond with HTTP-200 OK when reserving an existing movie
[info] - should respond with HTTP-409 Conflict if no seats left
[info] - should respond with HTTP-404 Not Found for a non existing movie/screen combination
[info] - should respond with HTTP-403 Forbidden failing validation if path and body resource identifiers are different
[info] retrieval
[info] - should respond with HTTP-200 OK for an existing movie
[info] - should respond with HTTP-404 Not Found for a non existing movie/screen combination
- The register movie input date only provides the movie id, but no movie title, whereas the retrieve requires a movie title, thus on register flow a call to an external movie information service provider is made here to get movie title by movie id (as a side note the javaGet is a temporary solution while figuring out the akkaGet to work);
- This call will only be executed if movies is not already registered as can be seen in this logic;
- If the service responds with a non error json, movie title along with input registration data is saved to the db, other wise the error json is saved as movie title in the db containing the error code and message returned by the upstream server in the body as json response;
- This is a scala sbt project, and was developed and tested to run with: Java 1.8, Scala 2.12.1 and Sbt 0.13.8
- Production db is PostgreSQL;
- Create database in PostgresSQL
- Set database settings on application config or set environment variables
There are two config files. Application config src/main/resources/application.conf
and test config src/test/resources/application.conf
.
PSQL_URL
||PSQL_TEST_URL
- database url by schemejdbc:postgresql://host:port/database-name
PSQL_USER
||PSQL_TEST_USER
- database userPSQL_PASSWORD
||PSQL_TEST_PASSWORD
- database password
To run application, call:
sbt run
If you wanna restart your application without reloading of sbt, use:
sbt re-start