Skip to content

Architecture

BrunoRosendo edited this page Aug 14, 2023 · 7 revisions

The project is being developed using the Spring Boot framework and the Kotlin programming language. That said, the architecture is mainly inspired by the community standards regarding those two technologies.

Contents

Layered Architecture

The project architecture follows a layered approach, which is essential for understanding its structure and implementation. This section aims to provide an explanation of this approach and how it is implemented. For a more in-depth understanding of the design decisions made, please refer to this article.

The diagram below illustrates the various layers employed in the architecture, highlighting the ones that are exposed to the public through the API. Subsequently, we will delve into a comprehensive explanation of each layer.

architecture-diagram

Web Layer

This is the uppermost layer of a web application and defines all routes/endpoints exposed in the API (if any of these terms look alien to you, please just Google them :) ). The function associated with each route usually only calls a few of the services' methods. They are implemented using Spring's controllers.

The web layer also assumes responsibility for handling exceptions that may occur in any layer of the program. It transforms these exceptions into informative error messages that are returned to the users. This is implemented in the ErrorController class. As the entry point of the application, this layer is crucial for authentication and serves as the initial line of defense against unauthorized users.

For more information about the web layer, refer to the Services and Controllers wiki page.

Services

Below the web layer, we have the services layer, which is utilized by controllers or other services. It encapsulates the entire business logic of the application, including interactions with external resources such as databases, files, and emails. They are implemented with Spring's services and resemble common classes.

In theory, it is possible to omit the services layer by directly implementing all its methods within the controllers. However, such an approach would strongly violate the principle of Separation of Concerns and would make it exceedingly challenging to avoid code duplication.

For more information about the service layer, refer to the Services and Controllers wiki page.

Repositories

Repositories define the lowest layer of a web application. They use the entities defined in the model and offer simple CRUD methods to communicate with the database. Spring's repositories already give us out-of-the-box functionalities but we can also create custom queries!

For more information about repositories, refer to the Models wiki page.

Domain Model

The domain model encompasses all the entities utilized in the internal representation of our application. Despite sounding complex, it becomes much clearer when we examine examples such as Event, Project, Account, and others.

With Spring JPA, we can define entities as regular data classes and incorporate useful validations to their properties. Spring will then leverage this model and seamlessly translate it into any relational database configured within the application.properties file.

For more information about the model, refer to the Models wiki page.

Data Transfer Objects (DTOs)

A DTO is just a simple data object/class used to carry data between different layers of our application. They are essential for the following reasons:

  • They translate the user's input (JSON) into a usable Kotlin class without converting it directly to entities. That would be problematic because the entities usually contain fields we do not want the user to control (e.g. passwords and timestamps).
  • They translate the entities back to user responses (JSON). We violate this process by instead using the @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) annotation directly in the entity model when needed. This way, we simplify the process and still have a way of hiding unwanted fields from the users.

DTOs create a small overhead when developing new functionalities but help maintain API consistency and avoid security concerns.

For more information about the DTOs, refer to the Services and Controllers wiki page.

Project Structure

  • src/main
    • backend/ - Contains all the source code (excluding tests and resources)
      • config/ - Configuration classes used at boot (more in Configuration)
      • controller/ - Methods that register endpoints for the app (more in Services and Controllers)
      • model/ - Database entity models (Spring Data JPA entities, more in Models)
      • dto/ - Data Transfer Objects for creating and modifying entities
      • repository/ - Data access layer methods (Spring Data repositories, more in Repositories)
      • service/ - Business logic for the controllers
      • utils/ - Auxiliary packages used in the project
        • extensions/ - Extension functions used throughout the project
        • validation/ - Custom validations used across the different models
    • resources/ - All assets and static files needed, including static configurations
  • src/test/ - Self-explanatory: unit tests, functional (end-to-end) tests, etc. (more in Unit Testing and Integration Testing)

It's also important to note that the API documentation is written and generated when implementing/running integration tests.