Hexagonal Architecture for a Game

91 views Asked by At

I am learning about different architecture and want to implement the MasterMind game with Hexagonal Architecture and Onion architecture in the core. But I can't wrap my head around it completely.

The goal is to have an independent Application core so user can easily select if they want to play against an other users or the computer or maybe later over the network. Lets first imagine the UI is just the CLI.

I think I got most of the concepts and for an web app it seems pretty straight forward. But the part where my understanding fails is how would one go about implementing the game loop?

The Game always has the same Logic:

  1. get code from coder
  2. get guess from decoder
  3. get rating from coder
  4. (optional) win / lose

So I need 4 Ports Coder-In and Coder-Out, Decoder-In and Decoder-Out. Coder-In and Decoder-In would be driving ports/primary ports and Coder-Out Decoder-Out would be driven/secondary ports.

Here arises my first question: Is this right or would all be driven adapter because the game ask for input and processes it or would there be a main loop that controls the game core. And asks the coder and decoder for the input and then "forwards" it to the game core.

The second question is somehow similar: When the pattern is applied to an web app the user requests some data and it uses an driving port which return some data which is then send to the user. So in a way the driving port creates the output. So would I even need driving ports?

1

There are 1 answers

0
hatem87 On

The Onion architecture is like an update or revision of the Hexagonal architecture.

The 2 architectures agreed on adding ports/adapters on any project dependencies (the Onion architecture comes with a few extra layers, I think). Your project design should be based on a Core/Kernel/Domain layer that resolves all program functionality. This should be implemented regardless of any dependencies: database interaction, API request (this can be from either side your program consumes api=input port or exposes api=output port...) All these details should not impact your design. This can be achieved using inversion of control, keeping your Core project only aware of dependency interfaces, like IUserRepository, IOrderApiClient...

For your design to be successful, your Core project must allow game users to perform all interactions independently:

  • How the player connects to your game: Launch the web as a standalone application installed
  • How the game exposes or consumes data (database, API...)
  • Frameworks used (only frameworks that have a big impact, I will ignore the impact of CsvHeleper on my design if I analyze one or 2 files somewhere in the project)

A quick example of how your code can be organized:

  • Game.WebUI = Front-end
  • Game.DesktopUI = Desktop Front-end (the standalone version installed so it may refer the Game.Core directly or connected version so it pass throw the Game.WebApp Apis like the Game.WebUI)
  • Game.WebApp = Back-end startup project, Expose Web Api for the Game.WebUI + performs dependency injection (Game.Core reference)
  • Game.Core = Game code (entity + feature code), only knows Game.Repository and Game.ExternalApi
  • Game.Infra.Repository = interfaces for database access routines
  • Game.Infra.Repository.Impl
  • Game.Infra.ExternalApi = interfaces of an Api client for example
  • Game.Infra.ExternalApi.Impl

The Game.Core allows the user to play the game if they came from the web (Game.WebUI) as a web player or even if they used a desktop installation (Game.DesktopUI) The whole game should be in the Game.Core and you just need to translate that representation to the Web or Desktop player.

=> There you need your output ports/adapters.

=> The Game.Infra modules are input ports/adapters.

I would like to point out that I am not an expert in game development, this is from a pure design point of view :)