35

I am learning DDD and I am a little bit lost in the Infrastructure layer.

As I understand, "all good DDD applications" should have 4 layers: Presentation, Application, Domain, and Infrastructure. The database should be accessed using Repositories. Repository interfaces should be in Domain layer and repository implementation - in Infrastructure (reference DDD: Where to keep domain Interfaces, the Infrastructure?).

Application, Domain, and Infrastructure layer should/may have services (reference Services in Domain-Driven Design), for example, EmailService in Infrastructure layer which sends e-mail messages.

BUT, inside the Infrastructure layer, we have repository implementations, which are used to access the database. So, in this case, repositories are database services? What is the difference between Infrastructure service and repository?

Thanks in advance!

sajadre
  • 1,141
  • 2
  • 15
  • 30
Zygimantas
  • 8,547
  • 7
  • 42
  • 54

4 Answers4

36

Sticking with DDD definitions, a Repository is different than a Service. A Repository directly correlates to an Entity, often an Aggregate Root. A Service defines behaviors that don't really belong to a single Entity in your domain. You can absolutely find Services in every layer, though the types of problems they address differ from layer to layer and may be different from DDD's conceptual Service.

When working at the conceptual level, a DDD Repository differs from a DDD service in that it is specifically tied to Entity persistence. A Service can address any Domain, Application, or Infrastructure problem you may have.

You run into terminology clashes with DDD all over the place. For instance, a DDD Repository is NOT the same thing as the Repository pattern found in Martin Fowler's PoEAA book, though it may employ such a pattern. This is often a source of confusion for many people.

It helps with DDD if you always keep the Domain Model at the very center of everything you do. When it comes to layering DDD apps, I often choose Jeffrey Palermo's Onion Architecture. Check it out. Download CodeCampServer, an example app using this architecture. I think it's a perfect fit for DDD programming.

Good luck!

Kevin Swiber
  • 1,546
  • 11
  • 13
10

Maybe it will help to see a potential project structure.

Possible assembly or package structure:

Project.Domain
Project.Infrastructure.Data
Project.Infrastructure.Components
Project.Infrastructure.Services

Possible namespace or folder structure:

Project.Domain
-n- Modules
----n- Account
-------f- Account.xx
-------f- AccountRepository.xx
-------f- Contact.xx
----n- Marketing
-------f- RegionRepository.xx
-n- Shared
-n- Services

Project.Infrastructure.Data (OR-Mappers)
-n- Tables
-n- Views
-n- Procedures
-n- Functions

Project.Infrastructure.Components (Generic)
-n- Mail
-n- Cryptography
-n- UI

Project.Infrastructure.Services (Special Operations)
-f- DoingSomethingService1.xx
-f- DoingSomethingService2.xx
-f- DoingSomethingService3.xx

Domain Entities and Value Types do not use Domain Services. The Application Layer uses the Services of the Domain. The Domain Repository objects use the Infrastructure.Data objects to return Domain objects.

zx81
  • 41,100
  • 9
  • 89
  • 105
Roy Oliver
  • 338
  • 3
  • 10
  • 2
    The point of DDD is not to have a certain project structure, but rather to have behavior on your entities. When you say "make copies of your ORM objects" it sounds like you're using an anemic domain, which is not really DDD at all. The behavior (domain state mutations) should be inside of the domain objects, not in services. – Ryan May 18 '10 at 14:56
  • 1
    Of course, Ryan. DDD is NOT about a certain project type. That's an implementation detail. That's why I said it may help to see a project structure. By "make copies", I'm speaking in context of attributes, NOT the behavior. Domain object will resemble database object, for the most part. What does that mean? It means that the attributes will be similar except for the Aggreate and Composition associations. Since that confused you, I'll remove that text. If it confused you, I'm sure it will confuse others. – Roy Oliver May 18 '10 at 17:24
  • I think you mean properties, not attributes. I don't mean to criticize, just to clarify. I'm of the school of thought that properties on a domain object are an anti-pattern. Lately I've been going towards a quasi-cqrs route: read only properties on my domain and methods to mutate state. My views are about 50% reading from denormalized DB views and 50% projecting off the domain model. The approach I choose just depends on the complexity of the data. – Ryan May 18 '10 at 17:51
  • @Roy since you said "Domain Entities and Value Types do not use Domain Services" does it mean it also do not use Repository? How about Aggregates, does it also not using Service nor Repository? – No Body Jun 01 '10 at 08:52
  • In the past, I had Entities or Aggregate Roots (AR) calling Repositories. Now, my AR are either saved or retrieved by Repositories. The Domain can be a very funny thing. You have to be comfortable with it's design and implementation. Some ARs are simple, yet some may have collection-properties that contain millions of items. It will often be too tempting to call a repository from an Entity or AR because sometimes it seems natural. I recommend try seeing how far you can get by not calling a Repository from an Entity or AR. What type of project or solution are you working on? – Roy Oliver Jun 03 '10 at 18:03
  • @Roy,thanks for the reply. Can you site a quick example? I am working on a Dental medical records, where Patient has the basic personal/contact info, medical/dental history, dental services, medicine & dental materials used, payment on dental service & materials used. – No Body Jun 03 '10 at 23:33
  • Cool. Sounds like you're working on a small EMR system. I'm sorry for the late reply. I do not check this site often. As for examples, sorry. I do not have examples of my material. I've taken pieces from Udi, Martin Fowler, & Greg Young to build something that works for me. I'm not sure what flexibility you have, but it may be too late to introduce CQRS and Event Sourcing to your product. – Roy Oliver Jun 17 '10 at 20:38
  • @Ryan, I don't think properties by themselves is an anti-pattern. I think when those properties are used only as getters & setters is when the anti-pattern is revealed. You're right. It's best to make them read-only and use behavioral methods for setting them versus boldly assigning values to them. – Roy Oliver Jun 17 '10 at 20:44
  • @No Body, See http://stackoverflow.com/questions/1584105/can-aggregate-root-entity-calls-repository/3071378#3071378 – Roy Oliver Jun 18 '10 at 16:27
8

An unfortunate thing about DDD is the word 'Service'. What it should be is 'Domain Service'. Think of the Domain as entities and value objects, while Services are a way of dealing with actions, operations and activities.

As for the Repositories, they are just a facade that should behave like a collection to your domain. If you are using an ORM or writing your own, this is what all your domain objects should be going through in order to achieve persistence instead of those services directly.

Ty.
  • 3,888
  • 3
  • 24
  • 31
  • Well, maybe you misunderstood my question, or I misunderstood the answer. Inside infrastructure layer, if we have a service which deals with Mail API, we call it "email service", but the code to retrieve data from database is called "repository implementation". Isn't it the same type of "infrastructure service"? – Zygimantas Sep 05 '09 at 20:24
-5

Why would you put repository implementations into Infrastructure ? They're not related to 'Infrastructure' at all imho.

According to Evan's Blue Book, repositories are a part of the domain model. Therefore, I put the repository interface inside the domain model. The implementation of the repository sometimes as well.

Infrastructure should contain 'infrastructure' code, which could be a service which enables you to easily sent e-mail over smtp, or code which abstracts DB access for you (so, some classes that you could use in your repository, but it is not your repository).

So, do not put your repositories into 'infrastructure', since they do not belong there. To me, the classes that can be found in infrastructure , are classes that you can use in different other projects, see what I mean ? Classes that are not tightly related to your domain model or application belong in Infrastructure. And a repository implementation is quite tightly coupled to a specific application. :)

Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
  • 1
    I see repositories as domain-specific, not necessarily application-specific. Looking at it that way, it makes sense to have a repository interface defined in your Domain Model layer. I see data access as a domain-specific infrastructure concern, separate from application code. I see what you're saying about reusable libraries, but I separate those libraries into different modules: one (or more) reusable modules, containing classes such as EmailSender, and one (or more) domain-specific infrastructure modules, containing classes such as CustomerRepository. Different modules, same layer. – Kevin Swiber Sep 06 '09 at 15:29
  • Indeed, repository implementation should not be in the application. It should be in the domain model. However, the application-layer should control the transaction-scope that is used by a repository. – Frederik Gheysels May 28 '10 at 06:30
  • I think a traditional repository should be implemented outside of the domain model if it houses the actual infrastructure for doing data access. But with Jimmy Nilsson's NWorkspace concept I think repositories can then be have non-infrastructure implementation moved back into the domain layer where it it makes more sense. – jpierson Apr 22 '11 at 03:24
  • 10
    Repository interfaces can go in CORE/DOMAIN, Implementations of repositories are fine in infrastructure especially in the case of any ORM. We don't want ORM dependencies in CORE. – CrazyCoderz Feb 21 '12 at 16:42
  • So, if your repository interfaces are in 'DOMAIN', and your implementations in infrastructure, ths implies that your infrastructure has knowledge of your domain (you have a dependency on 'DOMAIN' in 'INFRA'). I don't think you want that ... – Frederik Gheysels Apr 12 '19 at 19:23