image

🚢 DeepStrike – Applying DDD, Clean Architecture, Event Sourcing, and CQRS in a Battleship Game

As software engineers, we constantly hear about concepts like Domain-Driven Design (DDD), Clean Architecture, Event Sourcing, and CQRS. They appear in conference talks, blog posts, and technical debates.

But what really caught my attention was Event Sourcing. I wanted to understand how to structure aggregates in a way that works naturally with Event Sourcing and CQRS.

That’s how DeepStrike was born — a proof of concept where I used these architectural techniques to implement something both fun and complex enough: a digital version of the classic Battleship game.

The Book That Sparked the Idea

One of the main inspirations for this PoC was the book: 📖 Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy by Vlad Khononov.

It’s an incredible resource that helped me connect business strategy with technical architecture. What I really loved about the book is how it demystifies DDD: it’s not about heavy frameworks or obscure patterns, it’s about language, collaboration, and boundaries.

This book gave me the confidence to take the next step: building something myself.

Why Battleship? 🎯

When choosing a domain for the PoC, I wanted something that:

  • Had a clear ubiquitous language (ships, shots, boards, hits, sinks…).
  • Allowed for state changes to be expressed as events.
  • Was simple enough to implement, but rich enough to explore concepts like aggregates, projections, and history navigation.

The classic Battleship game was a perfect match. Every action — placing a ship, firing a shot, marking a hit — naturally translates into an event. And that made it a great playground for Event Sourcing and CQRS.

How I Built It ⚙️

I decided to split the project into two modules, each with its own architectural approach:

API (Domain Core)

  • Built with DDD, Event Sourcing, CQRS, and Clean Architecture.
  • Domain logic is expressed through aggregates and value objects.
  • Game state is reconstructed by replaying events.
  • Projections (like Game Summary) use CQRS to provide fast reads.
  • PostgreSQL + Liquibase → Events and read models persisted in a structured way.
  • OpenAPI → Contract-first approach with code generation for API stubs.

CTL (Supporting Domain)

  • A lightweight Spring Shell CLI client.
  • Implements commands such as create, fire, join, ready.
  • Orchestrates requests to the API, handles errors, and provides user feedback.
  • No heavy domain logic — just a transaction script pattern.

Other Tech Choices

  • Java 21 + Spring Boot as the foundation.
  • Docker to run Postgres and the system easily.

What I Learned 💡

Building this PoC was full of “aha!” moments. Some of my main takeaways:

  • DDD is about shared understanding. Modeling the game using its own language (ships, shots, hits) made the code more expressive and aligned with the domain.
  • Event Sourcing gives superpowers. Instead of just storing the current state, I can replay the entire game, debug past moves, or even reconstruct “what the board looked like at turn 5.”
  • CQRS reduces complexity. By separating reads and writes, I could design projections like Game Summary without polluting the main aggregate logic.
  • Clean Architecture enforces discipline. It kept my domain pure and isolated from infrastructure details.
  • Learning accelerates with practice. Reading concepts was useful, but building something concrete made everything “stick” in my mind.

Challenges Along the Way ⚔️

Of course, it wasn’t all smooth sailing:

  • I ran into ship overlapping issues when generating random fleets.
  • Handling coordinates (A–J, 0–9) was trickier than expected, since humans think in grid letters while the system thinks in integers.
  • Designing events to be both expressive and minimal took several iterations.
  • But each challenge was exactly what I wanted: a chance to think like a domain modeler, not just a coder.

Repository 📂

For anyone curious to dive deeper, the full source code is available here: 👉 GitHub Repository – DeepStrike

Final Thoughts 🌟

This project wasn’t about building the “perfect” Battleship game. It was about using a playful domain to explore serious architectural principles.

If you’re learning DDD, Event Sourcing, or CQRS, my advice is: ⚡ Don’t stop at theory. Pick a domain (even a game!) and try to model it. You’ll be amazed at how much the concepts come alive when applied.

And if you’re looking for guidance, Vlad Khononov’s Learning Domain-Driven Design is a fantastic starting point. It truly changed how I approach software design.