Category: DDD

  • [AoNW] The Refactor So Far: One Map, Better Gates, Less Drift

    In the previous post, I described a plan to refactor Age of New Worlds without rewriting it.

    The plan looked clean on paper.

    Then the real work started.

    The goal was not to move files around or rename a few classes. The goal was to remove duplicate paths while keeping the game working after every step.

    The first safety work is now complete. Most of the new quality gates are running. The map migration is far advanced. Some real inconsistencies were found and fixed along the way.

    (more…)
  • [AoNW] Refactoring a Growing Flutter 4X Game Without Rewriting It

    When I wrote the first article about Age of New Worlds, the basic game loop was already working.

    I could explore a hex map, found cities, move units, manage production, research technologies, improve terrain, end turns, and save the game. Flutter and Flame had already proved they could handle a 4X game. The new question was whether I could keep adding features without making the code harder to change every time.

    (more…)
  • [AoNW] Testing Bounded Contexts: Making Architecture Fail Loudly

    In Age of New Worlds, bounded contexts are not only a design idea. They are something I want the test suite to defend.

    It is easy to draw clean diagrams early in a project. The hard part is keeping them true after months of adding features, fixing UI problems, wiring multiplayer, changing saves, and moving logic between client and server.

    A boundary does not usually break dramatically. It breaks through one convenient import, one shortcut, one helper used from the wrong layer, one piece of presentation logic leaking into the domain.

    So I try to make those mistakes fail loudly.

    (more…)
  • [AoNW] Building AI That Uses the Same Commands as the Player

    AI in a strategy game can easily become a second game hidden inside the first one. That is dangerous.

    If the AI has its own movement rules, its own production shortcuts, its own visibility model, or its own private way of mutating state, then every new feature has to be implemented twice: once for the player and once for the AI. Worse, bugs become harder to reason about because the AI is no longer playing the same game.

    In Age of New Worlds, I want the AI to use the same language as the player. That language is commands.

    (more…)
  • [AoNW] From Hotseat to Multiplayer: Making the Server Authoritative

    Age of New Worlds started with local play. That was the right place to begin. A 4X game already has enough moving parts before networking enters the picture: turns, units, cities, production, research, fog of war, saves, UI state, and AI. Adding multiplayer too early can turn every feature into a distributed-systems problem.

    But I did not want local play to become a dead end.

    So even while the game focused on hotseat, I tried to shape the architecture around a future server-backed model. The main rule was simple:

    Local play can be convenient, but multiplayer must be authoritative.

    (more…)
  • [AoNW] Saving game: Snapshots, Event Logs, and Migrations

    Saving a sounds simple until the game starts becoming a real 4X game.At the beginning, it is tempting to think of saving as one operation:

    jsonEncode(gameState)

    That works for a prototype. It does not work for long.

    (more…)
  • [AoNW] The Domain and Application Layers: Where the Game Actually Lives

    A 4X has many different kinds of decisions. Some are game rules. Some are player workflow. Some are persistence. Some are rendering. Some are network concerns. If I let all of them live in the same place, every new feature becomes harder than it should be.

    So the project uses a DDD-inspired split between the domain layer and the application layer.

    The domain layer answers: what is true in the game?

    The application layer answers: how do I perform a use case around that truth?

    (more…)
  • [AoNW] General Architecture Overview

    Age of New Worlds is strongly DDD-inspired. I use domain boundaries, application ports, infrastructure adapters, commands, events, projections, and persistent snapshots because a 4X game becomes complicated very quickly. The architecture is there to answer one question:

    How do I keep the game understandable when rendering, UI, AI, saving, hotseat play, and multiplayer all want to touch the same state?

    (more…)
  • Experimenting with Event Sourcing and Ecotone

    I’ve just published a new repo, a side project where I’m experimenting with Event Sourcing, CQRS, and the Ecotone framework in a Symfony 7 environment.

    This is a personal learning project, not something production-ready. The goal is to better understand how to design event-driven systems in PHP using real-world structures like aggregates, value objects, and projections. As a playground, I’m building a turn-based strategy game (inspired by Civilization) -just enough to have a meaningful domain to model.

    Right now, the repo includes:

    • Symfony 7.3 backend with Ecotone (commands, events, projections),
    • Early frontend setup using Vite, Symfony UX and PixiJS for rendering a hex map,
    • A bunch of evolving domain logic for turns, players, and cities.

    Again – this is an experimental setup for learning, so expect the code to change frequently. But if you’re also exploring Ecotone or curious how event sourcing might work in a Symfony project, feel free to check it out, leave feedback, or just follow along.

    github.com/ernestwisniewski/symfony-of-ages

  • Projections – Transforming Events into Read Models

    In an event-sourced architecture, the entire history of changes to the application’s state is stored as a sequence of events. However, to effectively work with this data, we often need optimized read models. This is where projections come into play. In today’s post, I’ll show you how to set up and implement projections in Ecotone, allowing you to easily transform events into the current state of your system.

    (more…)