Skip to content

Modular application designed with principles of DDD and Clean Architecture.

License

Notifications You must be signed in to change notification settings

ryletko/LexiQuest-Modular-DDD

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LexiQuest Game

Modular application built with Clean Architecture and DDD principles which is ready to quickly get splitted into microserves.

Introduction

I think it's long been clear to everyone how to handle order processing in a DDD style. Enough with the repetitive examples! Such examples cover the core principles only superficially, without addressing corner cases at all. Let's imagine how we could design a card game for people learning foreign words. This task is quite atypical for DDD, at least based on what I could find on GitHub. With this example, you can explore:

  • HOW TO break down a non-trivial task into bounded-contexts and allocate an independent isolated module for each bounded context, architecturally ensuring the possibility of turning any module into a microservice deployed on a separate machine.
  • HOW TO abstract the inter-module interaction mechanism — it's possible to avoid using docker containers, and go for a regular database or even memory for message exchange, for example, to deploy the application on web hosting, and later when required to switch to VPS.
  • HOW TO orchestrate long-running processes involving multiple modules — I prefer orchestration through sagas instead of choreography, as this approach provides centralized control of operations, process consistency, and a clear understanding of what is happening and when, improving manageability and transparency.
  • HOW TO ensure reliable delivery and processing of inter-module messages and domain events using the outbox pattern.
  • HOW TO use domain services for logic involving multiple aggregates, and for non-trival business logic requiring its responsibility to be extracted outside the aggregate.
  • HOW TO create a simple way to control access to a user's own resources.

Frameworks

  • MassTransit and RabbitMQ - inter-service communication.

  • MassTransit.Mediator - for handling domain events.

  • EPPlus - importing from xlsx.

  • EF Core - ORM, and PostgreSQL - database.

  • On the frontend, Blazor Interactive WebAssembly is used with RESTful API, along with a bit of Blazor Bootstrap. Auth0 - for authentication, and SignalR - handling messages from the backend, including errors.

How to launch

You need to add an appsettings.json file to LexiQuest.WebApp and LexiQuest.WebApp.Client/wwwroot, specifying the settings for Auth0 and EPPlus, then:

docker-compose up

Event Storm diagram

Dependency diagram

Conracts are:

  • Commands
  • Queries
  • Events

Context map and contracts

Start New Game Saga Sequence Chart

---
config:
  theme: forest
---
sequenceDiagram
  participant WebApp as WebApp
  box QuizGame Module
    participant StartNewGameSaga as StartNewGameSaga
    participant StartGameLimiter as StartGameLimiter
    participant Game Domain as Game Domain
  end
  participant Puzzle Manager as Puzzle Manager
  WebApp ->>+ StartNewGameSaga: StartNewGame
  StartNewGameSaga ->>+ StartGameLimiter: CheckLimitRequest
  StartGameLimiter -->>- StartNewGameSaga: CheckLimitRequest.Completed
  alt is duplicate
    StartNewGameSaga ->> WebApp: StartNewGameRefusedEvent
  else not duplicate
    StartNewGameSaga ->> WebApp: StartNewGameStatusEvent (FetchingPuzzles)
    StartNewGameSaga ->>+ Puzzle Manager: GetPuzzlesForCurrentOwnerQuery
    Puzzle Manager -->>- StartNewGameSaga: PuzzleRequest.Completed
    StartNewGameSaga ->> WebApp: StartNewGameStatusEvent (FetchingPuzzles)
    StartNewGameSaga ->>+ Game Domain: CreateNewGameCommand
    Game Domain -->>- StartNewGameSaga: NewGameCreatedEvent
    StartNewGameSaga ->> WebApp: StartNewGameStatusEvent (CreatingNewGame)
    StartNewGameSaga ->>+ Game Domain: StartGameCommand
    Game Domain -->>- StartNewGameSaga: GameStartedEvent
    StartNewGameSaga ->> WebApp: StartNewGameCompletedEvent
  end
Loading

Googlesheets Import Saga Sequence Diagram

---
config:
  theme: forest
---
sequenceDiagram
    participant WebApp
    box Import Module
      participant ImportSaga
      participant ImportInitializer
      participant GoogleImportService
    end
    participant PuzzleManager

    WebApp->>ImportSaga: ImportCommand
    activate ImportSaga
    Note over ImportSaga: State: Initially
    ImportSaga->>ImportSaga: Set ImportId, Timestamp, ImporterId, ImportSourceId
    ImportSaga->>ImportSaga: Transition to Initializing
    ImportSaga-->>WebApp: ImportStatusChangedEvent (Initializing)
    ImportSaga->>ImportInitializer: InitializeImport

    ImportInitializer->>ImportSaga: ImportInitialized
    Note over ImportSaga: State: Initializing
    ImportSaga->>ImportSaga: Set Initialized, Url, Language
    ImportSaga->>ImportSaga: Transition to FetchingDataFromGoogle
    ImportSaga-->>WebApp: ImportStatusChangedEvent (FetchingDataFromGoogle)
    ImportSaga->>GoogleImportService: FetchDataFromGoogle

    GoogleImportService->>ImportSaga: FetchedEvent
    Note over ImportSaga: State: FetchingDataFromGoogle
    ImportSaga->>ImportSaga: Set Fetched
    ImportSaga->>ImportSaga: Transition to SavingInPuzzleMgr
    ImportSaga-->>WebApp: ImportStatusChangedEvent (SavingInPuzzleMgr)
    ImportSaga->>PuzzleManager: AddNewPuzzlesCommand

    PuzzleManager->>ImportSaga: PuzzlesAddedEvent
    Note over ImportSaga: State: SavingInPuzzleMgr
    ImportSaga->>ImportSaga: Set SavedInPuzzleMgr
    ImportSaga-->>WebApp: ImportCompletedEvent
    ImportSaga->>ImportSaga: Finalize
    deactivate ImportSaga
Loading

TO-DO

What needs to be done:

  • Finish the editing section for puzzles and import sources.
  • Add a couple more import options in separate modules, for example, from a text file.
  • Add support for puzzle collections and parallel games with different collections. Currently, a user always has one collection and one game.
  • The project was written to demonstrate solving architectural tasks; I did not focus on optimizing word-checking algorithms, imports, etc.
  • For the same reason, tests were not written, and this needs to be fixed in future.

About

Modular application designed with principles of DDD and Clean Architecture.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published