Skip to content

Overview

dkettner edited this page Sep 11, 2023 · 18 revisions

Separation Of Concerns

The Ticketing System is split into three components: A database, a backend with a RESTful API and a frontend.

There are a number of reasons for separating the frontend from the backend like this.

  • As long as the service contract (REST API) does not change, the frontend may change the way it is presenting data to the user.
  • Vice versa the backend also does not need to concern with how the frontend is desigend.
  • The frontend may even be exchanged for a new one at any time without touching the code of the backend.
  • There may be multiple frontends for different plattforms but the domain logic is handled by only one backend.
  • Also note that currently the main focus of this project is the backend. The provided frontend is a proof-of-concept and is in no way optimized, secure or professionally designed. So the frontend is essentially meant to be replaced.
  • Alternatives for integrating the UI in the backend code (like JSPs or Thymeleaf) would mean that the system could only be used with this one poorly written UI. Changing the UI would require changing the backend.

Tech Stack

Database: Postgres

  • Arbitrary choice.
  • Easily exchangeable for other relational databases like MariaDB or Oracle because the backend uses an ORM framework for tables, queries etc.

Backend: Spring Boot (with embedded Tomcat web server)

  • Spring Core provides useful technologies like dependency injection, events, logging, SpEL, ...
  • Spring Data JPA simplifies the communication with the database by using ORM.
  • Spring Web MVC for building a RESTful service by handling incoming requests in a comfortable way.
  • Spring Security to handle authentication and authorization of incoming requests.
  • Having an embedded and pre-configured Tomcat makes it an obvious choice.

Frontend: Vue + Naive UI (component library) + Nginx (web server)

  • Three frameworks were considered: React, Angular and Vue.
  • Vue comes with built-in solutions for important features like state management (Pinia), routing (Vue Router) and building (Vuex). React does not.
  • Vue is easier to start with than Angular (although this is highly subjective).
  • Vue does not have a dedicated component library like Angular (Material UI). Instead the frontend uses a third-party library called Naive UI. It provides clean looking components which were especially designed to work with Vue.
  • Nginx is lightweight.

Deployment: Docker + Docker Compose

  • Easier installation: No need to build images, install the correct version of the jvm, installing a database server and configuring the backend to use the correct credentials etc. Just run the docker compose file and the already build images will get pulled from Docker Hub. Pre-configured and ready to go.
  • Ensuring compatibility with all platforms that are able to run docker containers. It does not matter if it is Linux, MacOS or Windows.

Layers (Horizontal View)

The layered architecture is inspired by domain driven design principles. By assigning specific tasks to each layer, the code base stays cleaner and is easier to maintain and expand.

Below you will find the indivdual tasks of each service.

  • Frontend: Client-specific representation of the domain. To interact with the backend it sends HTTP requests to the controllers.

  • Controller: Receives HTTP requests, reads/maps necessary data from the path and body to DTOs and delegates the task with the necessary data to the application service.

    The return of the application service gets mapped to an HTTP response and the controller answers the client. Depending on the type of request, the body of the response might contain data.

  • Application Service: Checks if the user is authorized (might trigger an exception with an annotated status code) and maps the received DTO to an actual domain entity (if applicable). But it does not contain any domain logic. Instead it delegates the actual task or query to the domain service.

    Depending on the type of request it will map the return value (maybe an entity) to a dedicated response DTO which gets returned to the controller.

  • Domain Service: Handles domain logic. This might involve quering the repository for existing entities or creating/patching/deleting entities. It will also make sure to keep track of invariants and other domain-specific rules which cannot be implemented by single entities.

    The result of the operation gets returned to the application service. Note that the domain service does not need to concern with permissions, DTOs or HTTP requests.

    Another important part is the handling of incoming events and the publishment of its own events (for example the ProjectCreatedEvent). Please refer to the dedicated event section in this wiki to learn more about this.

  • Repository: Manages entities. It might trigger changes in the database upon a succesful return.



Clone this wiki locally