Spellcasting ended up being the largest feature of the game that we have added to date. We knew this going up front that there would be lots of intricacies, but one of the biggest challenges we had was untangling the large web that had formed between our API layer and our Data Layer.
Up until this point we had relied upon manager/handler-type classes to handle a lot of our business logic. This led to a dependency nightmare as many of our modules began to depend on each other for either a lookup or to perform a specific action. After much research, we decided to adopt and refactor most of our server side code to be based on domain driven design.
To achieve this, some of the bigger changes we had to make:
- Create new domain models and value objects for all game-related interactions.
- Domain models would hold all of the business logic that was once in our handler/manager classes.
- Data Transfer Objects would never be stored in a domain, but instead just hold the data for an incoming request or to update a record in the Database.
- Manager classes became "facades" which just orchestrated the actions between domain models.
- Created an abstract repository that can adopt a flexible set of caching strategies.
- Moved all domain models & value objects to aggregate roots, which would then be cached within and looked up from our repositories.
With the above changes implemented we finally had a clear division in the different layers of our server. More importantly, the web was untangled enough to add all of the pieces for handling spellcasting.