DDD with Symfony2: Making Things Clear

Domain Driven Design also known as DDD is an approach to develop software for complex needs by connecting the implementation to an evolving model. It is a way of thinking and a set of priorities, aimed at accelerating software projects that have to deal with complicated domains.

It is possible to use this approach in a Symfony2 project, and that is what I am going to introduce in a series of blog posts. You will learn how to build an application that manages users through a REST API using Domain Driven Design.

This is the second article of this series! You should read Folder Structure And Code First before digging into that one. This blog post is an attempt to fix a few misunderstandings coming from the first post. I recommend you to quickly jump to all links, they are valuable!

DDD Is Not RAD

Domain Driven Design is not a fast way to build a software. It is not RAD at all! It implies a lot of boilerplate code, tons of classes, and so on. No, really. It is not the fastest way to write an application. No one ever said that DDD was simple or easy.

However, it is able to ease your life when you have to deal with complex business expectations. How? By considering your domain (also known as your business) as the heart of your application. Honestly, DDD should be used in a rather large application, with complex business rules and scenarios. Don't use it if you are building a blog, it does not make much sense (even if it is probably the best way to learn the hard way). So question is when to use DDD? I would say when your domain is very complex, or when the business requirements change fast.

There Is No Database

In DDD, we don't consider any databases. DDD is all about the domain, not about the database, and Persistence Ignorance (PI) is a very important aspect of DDD.

With Persistence Ignorance, we try and eliminate all knowledge from our business objects of how, where, why or even if they will be stored somewhere. Persistence Ignorance means that the business logic itself doesn't know about persistence. In other words, your Entities should not be tied to any persistence layer or framework.

So, don't expect me to make choices because it works better with Doctrine, Propel or whatever. This is not how we should use DDD. We, as developers, need to become part of our business users domains, we need to stop thinking in technical terms and constructs, and need to immerse ourselves in the world our business users inhabit.

DDD And REST

By now, I use a REST API as Presentation Layer. It is perfectly doable and, even if both concepts seem opposites, they play nice together. Remember that one of the strengths of DDD is the separation of concerns thanks to distinct layers. I am afraid that people think that it is not possible to play with both at the same time because nobody understands REST or HTTP.

Basically, you should not expose your Domain Model as-is over a public interface such as a REST API. That is why you should use Data Transfer Objects (DTOs). DTOs are simple objects that should not contain any business logic that would require testing by the way. A DTO could be seen as a PHP array actually.

What you should do here is to write a REST API that exposes resources that make sense for the clients (the clients that consume your API), and that are not always 1-1 with your Domain Model. See these resources as DTOs. For instance, if you deal with Orders and Payments, you could create a transaction resource to perform the business operation payOrder(Order $order, Payment $payment) as proposed by Jonathan Bensaid in the comments of the previous article:

POST /transactions
orderId=123&paymentId=456&...

The Application Layer will receive the data from the Presentation Layer and call the Domain Layer. This transaction is a DTO. It is not part of the domain but it is useful to exchange information between the Presentation and the Application layers.

However, in the previous article I was able to directly map my User Entity to resources of type users. But if you look at the whole thing, I used a Serializer component to only expose some properties. That is actually another sort of DTO. The Entity is transformed to only expose data that are relevant for the clients (the clients that consume your API). So it is ok(-ish)!

Also, note that HTTP methods explicitly delineate commands and queries. That means Command Query Responsibility Separation CQRS maps directly to HTTP. Hurray!

So, What's Next?

In this series, I will introduce a more complex business, don't worry! Hopefully I was clear enough to explain my choices regarding this series, and I fixed some misconceptions about DDD, RAD, and REST.

In the next blog post, I will introduce the Presentation Layer, new Value Objects such as the Name one, and more on DDD! At the end of the next post, you will basically get a CRUD-ish application. Yes, I know... CRUD is an anti-pattern, but it does not mean you should avoid it all the time. Creating new users make sense afterall.

The third post will allow you to create almost everything you need in the different DDD layers to build a strong and powerful domain, with complex logic, and so on. You may not get why DDD is great until that, so don't panic and stay tuned!

By the way, if you found a typo, please fork and edit this post. Thank you so much!
This post is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

If you like this post, or if you use one of my Open Source projects, don't hesitate to send me an email. Oh, and just in case, here is my Amazon Wish List. Thank you ♥