From ebd69d6ea872444589d0bbc3a906537d4eacc0fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pelayo=20Rojas=20=C3=8D=C3=B1igo?= Date: Sun, 11 Feb 2024 22:56:40 +0100 Subject: [PATCH 1/5] create branch --- docs/src/07_deployment_view.adoc | 103 +++++++++---------------------- 1 file changed, 30 insertions(+), 73 deletions(-) diff --git a/docs/src/07_deployment_view.adoc b/docs/src/07_deployment_view.adoc index 22b45c27..51b03122 100644 --- a/docs/src/07_deployment_view.adoc +++ b/docs/src/07_deployment_view.adoc @@ -1,94 +1,51 @@ -ifndef::imagesdir[:imagesdir: ../images] - [[section-deployment-view]] - == Deployment View -[role="arc42help"] -**** -.Content -The deployment view describes: - - 1. technical infrastructure used to execute your system, with infrastructure elements like geographical locations, environments, computers, processors, channels and net topologies as well as other infrastructure elements and - -2. mapping of (software) building blocks to that infrastructure elements. - -Often systems are executed in different environments, e.g. development environment, test environment, production environment. In such cases you should document all relevant environments. - -Especially document a deployment view if your software is executed as distributed system with more than one computer, processor, server or container or when you design and construct your own hardware processors and chips. - -From a software perspective it is sufficient to capture only those elements of an infrastructure that are needed to show a deployment of your building blocks. Hardware architects can go beyond that and describe an infrastructure to any level of detail they need to capture. - -.Motivation -Software does not run without hardware. -This underlying infrastructure can and will influence a system and/or some -cross-cutting concepts. Therefore, there is a need to know the infrastructure. - -.Form - -Maybe a highest level deployment diagram is already contained in section 3.2. as -technical context with your own infrastructure as ONE black box. In this section one can -zoom into this black box using additional deployment diagrams: - -* UML offers deployment diagrams to express that view. Use it, probably with nested diagrams, -when your infrastructure is more complex. -* When your (hardware) stakeholders prefer other kinds of diagrams rather than a deployment diagram, let them use any kind that is able to show nodes and channels of the infrastructure. - - -.Further Information - -See https://docs.arc42.org/section-7/[Deployment View] in the arc42 documentation. - -**** +The deployment strategy for our game, which leverages the Wikidata API to dynamically generate questions, is built around a Docker-based infrastructure. This approach allows for the encapsulation of our Java Spring Boot application within a Docker container, simplifying deployments across different environments (development, testing, and production) while ensuring consistency and isolation. === Infrastructure Level 1 -[role="arc42help"] -**** -Describe (usually in a combination of diagrams, tables, and text): - -* distribution of a system to multiple locations, environments, computers, processors, .., as well as physical connections between them -* important justifications or motivations for this deployment structure -* quality and/or performance features of this infrastructure -* mapping of software artifacts to elements of this infrastructure +Our application is containerized using Docker, enabling us to deploy the entire stack as a single `.jar` file that includes the web server. This method ensures that our application can be easily moved across environments or scaled up as needed without significant changes to the infrastructure. -For multiple environments or alternative deployments please copy and adapt this section of arc42 for all relevant environments. -**** +_**Overview Diagram:**_ +The infrastructure features a single Docker container that hosts the Java Spring Boot application. This container communicates with external services, such as the Wikidata API, to fetch data in real-time and generate game questions. -_****_ +.Motivation:: +The primary motivation behind using Docker for deployment is to streamline the development and deployment processes. By containerizing the application, we reduce discrepancies between environments, making it easier to develop, test, and deploy with confidence. -Motivation:: - -__ - -Quality and/or Performance Features:: - -__ - -Mapping of Building Blocks to Infrastructure:: -__ +.Quality and/or Performance Features:: +- **Portability:** Docker containers can run on any system that has Docker installed, reducing environment-specific bugs. +- **Scalability:** While we start with a single container, the setup can be easily scaled using Docker Compose or Docker Swarm if the need arises. +- **Efficiency:** Docker utilizes resources more efficiently than traditional VMs, allowing for faster startup times and lower overhead. +.Mapping of Building Blocks to Infrastructure:: +- **Web Server/Application (.jar file):** Packaged within a Docker container, it includes all necessary dependencies to run independently across any Docker-supported platform. +- **External APIs (e.g., Wikidata API):** Accessed over the network, these APIs provide dynamic content for the game. === Infrastructure Level 2 -[role="arc42help"] -**** -Here you can include the internal structure of (some) infrastructure elements from level 1. - -Please copy the structure from level 1 for each selected element. -**** +At this level, we describe the Docker container configuration that encapsulates our application. -==== __ +==== _Docker Container_ -__ +Our Docker container is built from a Java base image, which is then layered with our application’s `.jar` file. This setup encapsulates the entire runtime environment required for our application. -==== __ +.Diagram: Docker Container Setup:: +[plantuml,"Docker Container Setup",png] +---- +@startuml +rectangle "Docker Container" { + node "Java Spring Boot App (.jar)" as App + database "Web Server (Embedded)" as WebServer +} -__ +cloud "Wikidata API" as API -... +App --> API : Fetch questions +App ..> WebServer : Serve application +---- -==== __ -__ +.Explanation:_ +This diagram illustrates the internal structure of our Docker container. It shows the Java Spring Boot application, including the embedded web server, packaged as a `.jar` file. The application interacts with external APIs, like the Wikidata API, to retrieve data necessary for generating game questions. The containerized approach ensures that the application can be deployed consistently across any environment that supports Docker. \ No newline at end of file From 4ebfee87cee8d3bec070add183f72de20ae483f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pelayo=20Rojas=20=C3=8D=C3=B1igo?= Date: Sun, 11 Feb 2024 23:53:09 +0100 Subject: [PATCH 2/5] typo in uml --- docs/src/07_deployment_view.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/07_deployment_view.adoc b/docs/src/07_deployment_view.adoc index 51b03122..c51919cb 100644 --- a/docs/src/07_deployment_view.adoc +++ b/docs/src/07_deployment_view.adoc @@ -43,7 +43,7 @@ rectangle "Docker Container" { cloud "Wikidata API" as API App --> API : Fetch questions -App ..> WebServer : Serve application +App ..> WebServer : Server application ---- From 6da96099398015a94c20fc181d830e9cfcd500e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pelayo=20Rojas=20=C3=8D=C3=B1igo?= Date: Mon, 12 Feb 2024 18:05:22 +0100 Subject: [PATCH 3/5] Finish 7 and 8 --- docs/src/07_deployment_view.adoc | 2 +- docs/src/08_concepts.adoc | 77 ++++++++++++++------------------ 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/docs/src/07_deployment_view.adoc b/docs/src/07_deployment_view.adoc index c51919cb..521e3efd 100644 --- a/docs/src/07_deployment_view.adoc +++ b/docs/src/07_deployment_view.adoc @@ -44,8 +44,8 @@ cloud "Wikidata API" as API App --> API : Fetch questions App ..> WebServer : Server application +@enduml ---- - .Explanation:_ This diagram illustrates the internal structure of our Docker container. It shows the Java Spring Boot application, including the embedded web server, packaged as a `.jar` file. The application interacts with external APIs, like the Wikidata API, to retrieve data necessary for generating game questions. The containerized approach ensures that the application can be deployed consistently across any environment that supports Docker. \ No newline at end of file diff --git a/docs/src/08_concepts.adoc b/docs/src/08_concepts.adoc index 591ccf1f..91dee5ee 100644 --- a/docs/src/08_concepts.adoc +++ b/docs/src/08_concepts.adoc @@ -3,71 +3,60 @@ ifndef::imagesdir[:imagesdir: ../images] [[section-concepts]] == Cross-cutting Concepts +The following concepts provide a foundation for the design and implementation of the trivia game project, which utilizes the Wikidata API for dynamic question generation and employs a hexagonal architecture for its Java Spring Boot application. -[role="arc42help"] -**** -.Content -This section describes overall, principal regulations and solution ideas that are relevant in multiple parts (= cross-cutting) of your system. -Such concepts are often related to multiple building blocks. -They can include many different topics, such as +=== Domain Model -* models, especially domain models -* architecture or design patterns -* rules for using specific technology -* principal, often technical decisions of an overarching (= cross-cutting) nature -* implementation rules +The domain model for our game includes entities such as `Question`, `Category`, `Player`, and `GameSession`. These are crucial for representing the game's data and logic. The model serves as the basis for interactions within the application and between the application and the database. +.Explanation: +The `Question` entity encapsulates details of the trivia questions. `Category` classifies these questions into various topics. `Player` represents users and their interactions with the game, while `GameSession` maintains the state of play, including scores and progress. -.Motivation -Concepts form the basis for _conceptual integrity_ (consistency, homogeneity) of the architecture. -Thus, they are an important contribution to achieve inner qualities of your system. +=== Hexagonal Architecture -Some of these concepts cannot be assigned to individual building blocks, e.g. security or safety. +Our application is structured using hexagonal architecture principles, which prioritize the separation of core logic from peripheral concerns like user interface and external API interactions. +.Explanation: +This architecture facilitates the creation of a flexible and maintainable codebase. It allows for easy adaptation to changes in external services or user interface technologies without impacting the application's core logic. -.Form -The form can be varied: +=== Java Persistence API (JPA) for Data Management -* concept papers with any kind of structure -* cross-cutting model excerpts or scenarios using notations of the architecture views -* sample implementations, especially for technical concepts -* reference to typical usage of standard frameworks (e.g. using Hibernate for object/relational mapping) +We use JPA for data persistence to abstract and handle all database operations, allowing for a more streamlined and object-oriented approach to data handling. -.Structure -A potential (but not mandatory) structure for this section could be: +.Explanation: +JPA enables us to map our domain objects to the database schema with ease, providing a clear layer of abstraction that simplifies data persistence and retrieval while ensuring our application remains agnostic of the underlying database technology. -* Domain concepts -* User Experience concepts (UX) -* Safety and security concepts -* Architecture and design patterns -* "Under-the-hood" -* development concepts -* operational concepts +=== Logging with Log4j and System.out -Note: it might be difficult to assign individual concepts to one specific topic -on this list. +For monitoring runtime behavior and troubleshooting, the project utilizes Log4j and System.out for logging. While Log4j offers more sophisticated logging capabilities, System.out is used for straightforward, immediate console output. -image::08-Crosscutting-Concepts-Structure-EN.png["Possible topics for crosscutting concepts"] +.Explanation: +Log4j is configured to capture various levels of output, which can be directed to multiple destinations such as console, files, or even remote logging servers. For simplicity and immediacy during development or less complex deployment scenarios, System.out is employed for logging output directly to the console. +=== Security -.Further Information +Security is a key concern, ensuring that user data and game integrity are protected. We implement standard security practices at various levels within the application. -See https://docs.arc42.org/section-8/[Concepts] in the arc42 documentation. -**** +.Explanation: +This includes securing the web layer with Spring Security, encrypting sensitive data, and protecting against common web vulnerabilities. +=== Performance Optimization -=== __ +Performance optimization is considered in all aspects of the application, from the efficient design of the domain model to the configuration of the persistence layer. -__ +.Explanation: +We ensure that database interactions are efficient through JPA's caching and lazy loading. Queries are optimized to fetch only the necessary data, minimizing response times and resource utilization. +=== Continuous Integration and Continuous Deployment (CI/CD) +The project adheres to CI/CD practices, facilitating automated testing, building, and deployment processes which contribute to the robustness and reliability of the application. -=== __ +.Explanation: +Our CI/CD pipeline automates the process of integrating code changes, building the application, running tests, and deploying the Dockerized application, ensuring consistent and reliable delivery of updates. -__ +=== Scalability -... +Designing for scalability, the application can accommodate an increasing number of users and interactions without performance degradation. -=== __ - -__ +.Explanation: +Scalable solutions such as Docker containers allow the application to be deployed in a distributed environment, where resources can be adjusted based on demand. \ No newline at end of file From be6c7ca5f7298ac4a39785a883e863996b9654cc Mon Sep 17 00:00:00 2001 From: Pelayori <31128562+Pelayori@users.noreply.github.com> Date: Mon, 26 Feb 2024 22:01:44 +0100 Subject: [PATCH 4/5] Complete domain model diagram (WIP) --- docs/src/07_deployment_view.adoc | 32 +++-- docs/src/08_concepts.adoc | 199 ++++++++++++++++++++++++++++++- 2 files changed, 216 insertions(+), 15 deletions(-) diff --git a/docs/src/07_deployment_view.adoc b/docs/src/07_deployment_view.adoc index 521e3efd..08de22f5 100644 --- a/docs/src/07_deployment_view.adoc +++ b/docs/src/07_deployment_view.adoc @@ -11,15 +11,15 @@ Our application is containerized using Docker, enabling us to deploy the entire _**Overview Diagram:**_ The infrastructure features a single Docker container that hosts the Java Spring Boot application. This container communicates with external services, such as the Wikidata API, to fetch data in real-time and generate game questions. -.Motivation:: +.Motivation The primary motivation behind using Docker for deployment is to streamline the development and deployment processes. By containerizing the application, we reduce discrepancies between environments, making it easier to develop, test, and deploy with confidence. -.Quality and/or Performance Features:: +.Quality and/or Performance Features - **Portability:** Docker containers can run on any system that has Docker installed, reducing environment-specific bugs. - **Scalability:** While we start with a single container, the setup can be easily scaled using Docker Compose or Docker Swarm if the need arises. - **Efficiency:** Docker utilizes resources more efficiently than traditional VMs, allowing for faster startup times and lower overhead. -.Mapping of Building Blocks to Infrastructure:: +.Mapping of Building Blocks to Infrastructure - **Web Server/Application (.jar file):** Packaged within a Docker container, it includes all necessary dependencies to run independently across any Docker-supported platform. - **External APIs (e.g., Wikidata API):** Accessed over the network, these APIs provide dynamic content for the game. @@ -29,23 +29,35 @@ At this level, we describe the Docker container configuration that encapsulates ==== _Docker Container_ -Our Docker container is built from a Java base image, which is then layered with our application’s `.jar` file. This setup encapsulates the entire runtime environment required for our application. +Our app's Docker container is built from a Java base image, which is then layered with our application’s `.jar` file. -.Diagram: Docker Container Setup:: +In addition to the Spring boot standalone file, we also use the official `MySQL` server docker container image brought by DockerHub. This is our database server and it is used to store the game data, such as user scores, questions, etc. and all the other persistent data. + +This setup encapsulates the entire runtime environment required for our application, and does not require extensive configuration. + +.Diagram: Docker Container Setup [plantuml,"Docker Container Setup",png] ---- @startuml -rectangle "Docker Container" { - node "Java Spring Boot App (.jar)" as App - database "Web Server (Embedded)" as WebServer +rectangle "Docker compose" { + rectangle "App's Docker Container" { + node "Java Spring Boot App (.jar)" as App + database "Web Server (Embedded)" as WebServer + } + + rectangle "MySQL Server Container" { + database "MySQL Server" as MySQL + } } cloud "Wikidata API" as API +App --> MySQL : Store game data +MySQL --> App : Fetch game data App --> API : Fetch questions App ..> WebServer : Server application @enduml ---- -.Explanation:_ -This diagram illustrates the internal structure of our Docker container. It shows the Java Spring Boot application, including the embedded web server, packaged as a `.jar` file. The application interacts with external APIs, like the Wikidata API, to retrieve data necessary for generating game questions. The containerized approach ensures that the application can be deployed consistently across any environment that supports Docker. \ No newline at end of file +.Explanation: +This diagram illustrates the internal structure of our Docker containers structure. It shows the Java Spring Boot application, including the embedded web server, packaged as a `.jar` file and the MySQL server. The application interacts with external APIs, like the Wikidata API, to retrieve data necessary for generating game questions. The containerized approach ensures that the application can be deployed consistently across any environment that supports Docker. \ No newline at end of file diff --git a/docs/src/08_concepts.adoc b/docs/src/08_concepts.adoc index b5e89dc4..e3be5af0 100644 --- a/docs/src/08_concepts.adoc +++ b/docs/src/08_concepts.adoc @@ -7,7 +7,196 @@ The following concepts provide a foundation for the design and implementation of === Domain Model -The domain model for our game includes entities such as `Question`, `Category`, `Player`, and `GameSession`. These are crucial for representing the game's data and logic. The model serves as the basis for interactions within the application and between the application and the database. +The domain model for our game includes entities such as `Question`, `Category`, `Player`, `Role`, and `GameSession`. These are crucial for representing the game's data and logic. The model serves as the basis for interactions within the application and between the application and the database. + + +[plantuml, domain-model, svg, subs="attributes", subs="methods"] +---- +@startuml +class Question { + - id: Long + - question: String + - correctAnswer: String + - incorrectAnswers: List + - category: Category + - difficulty: String + - type: String + - updatedAt: LocalDateTime + + getId(): Long + + getQuestion(): String + + getCorrectAnswer(): String + + getIncorrectAnswers(): List + + getCategory(): Category + + getDifficulty(): String + + getType(): String + + getUpdatedAt(): LocalDateTime +} + +class Category { + - id: Long + - name: String + + getName(): String + + getId(): Long + + setName(name: String): void + + setId(id: Long): void +} + +class Player { + - id: Long + - username: String + - email: String + - password: String + - passwordConfirm : String + - roles: Set + + getId(): Long + + getUsername(): String + + getEmail(): String + + getPassword(): String + + getPasswordConfirm(): String + + getRoles(): Set + + setUsername(username: String): void + + setEmail(email: String): void + + setPassword(password: String): void + + setPasswordConfirm(passwordConfirm: String): void + + setRoles(roles: Set): void + + setId(id: Long): void +} + +class GameSession { + - id: Long + - player: Player + - correctQuestions: Integer + - totalQuestions: Integer + - createdAt: LocalDateTime + - updatedAt: LocalDateTime + + getPlayer(): Player + + getScore(): Integer + + getCreatedAt(): LocalDateTime + + getUpdatedAt(): LocalDateTime + + getCorrectQuestions(): Integer + + getTotalQuestions(): Integer + + addQuestion(correct: boolean): void + + setPlayer(player: Player): void + + setScore(score: Integer): void + + setCreatedAt(createdAt: LocalDateTime): void + + setUpdatedAt(updatedAt: LocalDateTime): void + + setCorrectQuestions(correctQuestions: Integer): void + + setTotalQuestions(totalQuestions: Integer): void +} + +class Role { + - id: Long + - name: String + + getId(): Long + + getName(): String + + setId(id: Long): void + + setName(name: String): void +} + +class WiqEs04bApplication { + + main(args: String[]): void +} + +interface PlayerService { + + addNewPlayer(playerDto: PlayerDto): Player + + getUsers(): List + + getUser(id: Long): Optional + + getUserByUsername(username: String): Optional + + getUserByEmail(email: String): Optional +} + +interface RoleService { + + addRole(roleDto: RoleDto): Role + + getRoles(): List + + getRole(name: String): Role +} + +class PlayerServiceImpl { + - playerRepository: PlayerRepository + - roleService: RoleService + + addNewPlayer(playerDto: PlayerDto): Player + + getUsers(): List + + getUser(id: Long): Optional + + getUserByUsername(username: String): Optional + + getUserByEmail(email: String): Optional +} + +class RoleServiceImpl { + - roleRepository: RoleRepository + + addRole(roleDto: RoleDto): Role + + getRoles(): List + + getRole(name: String): Role +} + +interface CrudRepository { + + save(entity: T): T + + findById(id: ID): Optional + + findAll(): List +} + +interface PlayerRepository { + + findByUsername(username: String): Optional + + findByEmail(email: String): Optional +} + +interface RoleRepository { + + findByName(name: String): Role +} + +class PlayerDto { + + username: String + + email: String + + password: String + + passwordConfirm: String + + roles: String[] +} + +class RoleDto { + + name: String +} + +class CustomErrorController { + + error(model: Model, webRequest: HttpServletRequest): String +} + +class HomeController { + + home(model: Model): String +} + +class PlayersController { + + showRegistrationForm(model: Model): String + + registerUserAccount(user: PlayerDto, result: BindingResult, model: Model): String + + showLoginForm(model: Model, error: String, session: HttpSession): String + + home(model: Model, principal: Principal): String +} + +class SecurityConfig { + + passwordEncoder(): PasswordEncoder + + filterChain(http: HttpSecurity): SecurityFilterChain + + configureGlobal(auth: AuthenticationManagerBuilder): void + + isAuthenticated(): boolean +} + +class CustomAuthenticationFailureHandler { + + onAuthenticationFailure(request: HttpServletRequest, response: HttpServletResponse, exception: AuthenticationException): void +} + +Question "1" *- "1" Category +GameSession "*" *-- "1" Player +Role "*" - "*" Player +PlayerService <|.. PlayerServiceImpl +RoleService <|.. RoleServiceImpl +PlayerService ..> Player +RoleService ..> Role +PlayerService ..> PlayerDto +PlayerServiceImpl ..> PlayerRepository +RoleServiceImpl .> RoleRepository +RoleService ..> RoleDto +PlayerRepository --|> CrudRepository +RoleRepository -|> CrudRepository +@enduml +---- + === Hexagonal Architecture @@ -23,16 +212,16 @@ We use JPA for data persistence to abstract and handle all database operations, .Explanation: JPA enables us to map our domain objects to the database schema with ease, providing a clear layer of abstraction that simplifies data persistence and retrieval while ensuring our application remains agnostic of the underlying database technology. -=== Logging with Log4j and System.out +=== Logging with Slf4j and System.out -For monitoring runtime behavior and troubleshooting, the project utilizes Log4j and System.out for logging. While Log4j offers more sophisticated logging capabilities, System.out is used for straightforward, immediate console output. +For monitoring runtime behavior and troubleshooting, the project utilizes Slf4j, bundled with Sprint Boot, and System.out for logging. While Slf4j offers more sophisticated logging capabilities, System.out is used for straightforward, immediate console output. .Explanation: -Log4j is configured to capture various levels of output, which can be directed to multiple destinations such as console, files, or even remote logging servers. For simplicity and immediacy during development or less complex deployment scenarios, System.out is employed for logging output directly to the console. +Slf4j is configured to capture various levels of output, which can be directed to multiple destinations such as console, files, or even remote logging servers. For simplicity and immediacy during development or less complex deployment scenarios, System.out is employed for logging output directly to the console. === Security -Security is a key concern, ensuring that user data and game integrity are protected. We implement standard security practices at various levels within the application. +Security is a key concern, ensuring that user data and game integrity are protected. We implement standard security practices at various levels within the application .Explanation: This includes securing the web layer with Spring Security, encrypting sensitive data, and protecting against common web vulnerabilities. From db4e31d5add17baadbcd6433f0e974a1e9a8dc58 Mon Sep 17 00:00:00 2001 From: Pelayori <31128562+Pelayori@users.noreply.github.com> Date: Mon, 26 Feb 2024 22:53:36 +0100 Subject: [PATCH 5/5] Split diagram for better visibility --- docs/src/08_concepts.adoc | 40 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/docs/src/08_concepts.adoc b/docs/src/08_concepts.adoc index e3be5af0..b228f3ff 100644 --- a/docs/src/08_concepts.adoc +++ b/docs/src/08_concepts.adoc @@ -93,10 +93,6 @@ class Role { + setName(name: String): void } -class WiqEs04bApplication { - + main(args: String[]): void -} - interface PlayerService { + addNewPlayer(playerDto: PlayerDto): Player + getUsers(): List @@ -155,6 +151,28 @@ class RoleDto { + name: String } +Question "1" *- "1" Category +GameSession "*" *-- "1" Player +Role "*" - "*" Player +PlayerService <|.. PlayerServiceImpl +RoleService <|.. RoleServiceImpl +PlayerService ..> Player +RoleService ..> Role +PlayerService ..> PlayerDto +PlayerServiceImpl ..> PlayerRepository +RoleServiceImpl .> RoleRepository +RoleService ..> RoleDto +PlayerRepository --|> CrudRepository +RoleRepository -|> CrudRepository +@enduml +---- + +[plantuml, domain-model-2, svg] +---- +@startuml +class WiqEs04bApplication { + + main(args: String[]): void +} class CustomErrorController { + error(model: Model, webRequest: HttpServletRequest): String } @@ -181,23 +199,9 @@ class CustomAuthenticationFailureHandler { + onAuthenticationFailure(request: HttpServletRequest, response: HttpServletResponse, exception: AuthenticationException): void } -Question "1" *- "1" Category -GameSession "*" *-- "1" Player -Role "*" - "*" Player -PlayerService <|.. PlayerServiceImpl -RoleService <|.. RoleServiceImpl -PlayerService ..> Player -RoleService ..> Role -PlayerService ..> PlayerDto -PlayerServiceImpl ..> PlayerRepository -RoleServiceImpl .> RoleRepository -RoleService ..> RoleDto -PlayerRepository --|> CrudRepository -RoleRepository -|> CrudRepository @enduml ---- - === Hexagonal Architecture Our application is structured using hexagonal architecture principles, which prioritize the separation of core logic from peripheral concerns like user interface and external API interactions.