DEV Community

Cover image for The way I see DDD (from a still-learning POV)

The way I see DDD (from a still-learning POV)

I'll be honest, this post isn't a masterclass. It's a (not so) deep-dive into Domain-Driven Design (DDD) from someone who's relearning the ropes. If you've ever stared at a diagram full of aggregates, repositories, and bounded contexts and thought: "Wait... what's going on here?" then welcome, you're in good company.

This write-up is my way of:

  • Rebuilding a solid mental model of what DDD is.
  • Connecting abstract concepts to (hopefully) intuitive analogies.
  • Sharing what clicked for me, especially through a more conversational, personified lens.

Whether you're brushing off the rust like me or exploring DDD for the first time, I hope this guide clears fog, sparks curiosity and makes the journey a little more enjoyable.

Core Concepts of DDD

And we begin. For starters, Domain-Driven Design (DDD) is a strategic software design approach focused on modeling complex domains through rich, meaningful code that reflects the business logic. Whether you're in a team, or doing a big project by yourself (May God help you) you should say to yourself: "Before we (or I) start coding, let's make sure we understand what we're building and why."

From my (re-learning) point of view, DDD is:

  • A way to reconnect development with the domain experts, or the people who actually understand the business.
  • An approach that values boundaries and expressiveness in code (you'll see in a while what I'm referring to)
  • A structure that asks teams to speak a ubiquitous language or consistent terminology across code, business conversations and documentation.

Layered Architecture in DDD

DDD isn't just about modeling, it's also about organizing. Most enterprise-grade applications benefit from a layered architecture that separates responsibilities and helps manage complexity. These layers are logical, not physical. So... that means they help you understand and build your system but not necessarily map how you deploy it.

The common representation of these layers is:

1. Domain Model Layer

The heart of the system, where business logic lives. This is where DDD's key building blocks (Entities, Aggregates, Value Objects, etc.) reside.
This layer houses the fundamental elements that define how your system behaves and enforces the rules that make your domain meaningful. It's completely isolated from infrastructure concerns, and that's by design. It's where your software thinks like the business.

Let's meet the building blocks that live here:

Entity - The identifiable Veteran

An Entity is defined by a unique identity (like orderId or userId) that persists through time, even if its properties change.

Examples:

  • User: has a userId and may update their email
  • Order: identified by orderId, even if its items change

You can think of it as... a traveler with a passport, no matter the clothes or the destination, their identity remains consistent and trackable.

Value Object - The Elegant Minimalist

A Value Object holds data that's immutable and interchangeable. Two value objects with the same properties are equal.

Examples:

  • Address: composed of street, city and zipCode
  • Money: with amount and currency

You can think of it as... a paint swatch, defined only by its color and properties, not by identity. Easy to duplicate, safe to discard.

Aggregate - The Cohesive Group

An Aggregate is a cluster of entities and value objects that work as a single unit. All access and updates happen via the aggregate root.

Example:

  • Order aggregate might include OrderItems, ShippingDetails and TotalAmount.

You can think of it as... a LEGO build, individual bricks are only meaningful when assembled under one clear purpose.

Aggregate Root - The Wise Gatekeeper

An Aggregate Root is the main entry point into the aggregate. It enforces rules and ensures consistency. You never touch inner objects directly, always go through the roof.

Example:

  • Order is the root that manages its items, status, payment flow and ensures business rules are respected.

You can think of it as... the school principal, access to the staff or records, goes through this one authority to ensure order and integrity.

Domain Event - The Loud Announcer

A Domain Event signals something meaningful happened in the domain. It allows systems to react without being tightly coupled.

Example:

  • OrderPlaced can trigger notification services, payment processing or shipment scheduling.

You can think of it as... the town crier, shouting the news so anyone listening can decide what to do next.

Repository - The Discreet Wingman

A Repository abstracts the data storage logic for aggregates. It lets you retrieve, save, and delete domain objects without knowing how persistence works.

Example:

  • OrderRepository handles methods like save(order) or findById(orderId)

You can think of it as... your backstage assistant, you can ask for something and it silently fetches or stores it without disrupting the show.

2. Application Layer

The one that orchestrates business use cases, it doesn't contain business rules, but it knows who should execute what. It handles incoming requests from the UI or external systems, then translates these requests into actions for the domain model, often using DTOs or ViewModels already shaped for presentation.

It NEVER validates business rules or interact with databases directly, instead it relies on repositories.

A good example would be the following:

Let's say a user clicks "Place Order" on your site:

  1. Presentation Layer sends the data -> PlaceOrderCommand
  2. Application Layer receives the command
  3. It asks the OrderAggregate to handle creation (with help from domain entities and rules)
  4. On success, it returns a ViewModel shaped for display.

3. Infrastructure Layer

This one is what we can call a Behind the scenes fixer, being practical but out of the spotlight. Supports everything else with persistence, networking and external services, it provides access to databases, external APIs, message queues, file systems, really anything the system needs to interact with the outside world.

It should NEVER leak into the domain. Instead, it serves the domain discreetly through abstractions like repositories, event dispatchers or service interfaces.

4. Presentation Layer

What the user sees and interacts with, it communicates with the application layer using ViewModels. This layer is responsible for delivering the user interface (UI), handling input, and presenting output. It communicates with the Application Layer via DTOs or ViewModels, ensuring that only valid and structured data reaches deeper into the system.

It's responsible for displaying user interfaces via views, templates and controllers (for example in MVC frameworks). It also formats and validates input before handing it off to the application layer.

When (and when not) to use DDD?

Let's be real: DDD isn't for every project. Sure, it shines in complex domains where logic is constantly evolving, multiple teams need to stay aligned and it's also kinda cool (at least in my opinion, seeing all those folders in my IDE and know where to search for errors is oddly satisfying). But if you try to use DDD for a weekend to-do list app... you might as well hunt a rabbit with a rocket launcher.

So how do we decide?

You should look into a checklist and see if the project fits into any of these:

  • You're dealing with complex business rules and need to represent real-world logic properly.
  • Your domain will evolve over time, like new rules, new behaviors, new use cases.
  • You want clear boundaries between different parts of the system
  • Multiple teams need to speak the same language, both code and business terms MUST stay aligned.
  • You're building for long-term maintainability rather than short-term speed.

On the other hand, if your project or app is...

  • Mostly CRUD (Create, Read, Update, Delete) with little domain complexity
  • A quick MVP or proof-of-concept
  • A solo project and need fast iteration more than layered organization

... DDD may be a little bit overkill.

That said, even in simpler projects, you can absolutely apply DDD principles without adopting the full architecture. Defining clear boundaries or avoiding infrastructure leakage into core logic can make a big difference. This isn't a yes-or-no situation, it's a spectrum. You can adopt parts of DDD gradually and let your system's structure grow as complexity demands.

Wrapping it All Up

So there you have it, a full walkthrough of Domain-Driven Design, not from the Ivory tower of theory, but from the perspective of someone piecing it all together again. Every layer has its role, every concept its voice, and now hopefully, every folder in your IDE has a reason to exist beyond just "feels organized".

This approach isn't about being perfect. It's about thinking in systems, talking in the language of the business and building with intention. Whether you decide to fully embrace DDD or just borrow its best ideas, the goal is the same: write software that makes sense.

Thanks for reading all the way here, and if you've got thoughts, corrections or your own take on DDD, hit me up in the comments! We're all learning here.

Top comments (2)

Collapse
 
xwero profile image
david duymelinck

Nicely written post!

These layers are logical, not physical

I know what you are trying to say, but I had a bit of a laugh. We are creating software, so nothing is physical.

like orderId or userId

Just id is enough, the type of id is defined by the class it is in.

You never touch inner objects directly, always go through the roof.

I think roof is a typo. I guess you meant root. But I'm good with roof if you want to keep it for fun.

I love your conclusion. Know why DDD is a good way to write software, but be smart about it.

Collapse
 
parizad profile image
Parizad

It was a great article. I write about Agile in my blog. I would be happy if you read my articles and write your comments about them.