5

Quoting DDD theory:

The application layer is thin in terms of domain logic - it merely coordinates the domain layer objects to perform the actual work.

When it comes to modularization, and assuming that the module containing the domain entities and the interfaces of the domain services belongs to the domain layer, the application layer depends on the domain layer, which breaks the dependency inversion principle.

The implementation of the high-level component's interface by the low level component requires that the low-level component package depend upon the high-level component for compilation, thus inverting the conventional dependency relationship.

What am I missing?

I add an UML diagram to clarify the problem I see. enter image description here

  • The Persistence Layer depends upon an abstration in the Domain Layer -> DIP ok!
  • The Application Layer depends upon an abstraction in the Domain Layer -> Does this break the DIP?
2

4 Answers 4

3

It doesn't break DIP because Domain is the highest level, higher than Application, and doesn't have a dependency on it. The reverse (Domain depending on Application) would break DIP.

Also, the "should depend on abstraction" part of DIP doesn't necessarily apply here, because domain entities can't be abstracted -- they are already a pure conceptual model of your domain. The only exception may be Domain Services, because you could place an interface in front of those.

As a side note, you generally don't need to leverage dependency inversion inside the Domain model itself, because

  • Domain entities have few to no collaborators
  • The ones they have are well identified (ubiquitous language) and often not polymorphic in nature
  • Domain resides entirely in memory with no external communication (3d party framework, network, disk, etc.) involved, so it can be tested with fast integration tests without needing mocks.
10
  • 1
    Honestly, IMHO this answer misses the point. If an Application layer depends on a Domain layer directly, this can be a violation of the DIP as well as the other way round. The key point is that the Application layer does only depend on interfaces of the Domain Layer classes, not on the domain layer classes directly.
    – Doc Brown
    Commented Nov 19, 2014 at 15:25
  • 1
    Disagree. Domain Entities are concrete, rarely abstract. Your repositories don't return abstractions. Entities are what the Application layer services manipulate in a typical DDD architecture, yet they don't violate SRP. Commented Nov 19, 2014 at 16:02
  • 1
    How can domain be higher level than application? "The application layer is thin in terms of domain logic - it merely coordinates the domain layer objects to perform the actual work." This means that the application layer is a consumer of the services provided by the domain layer, and that's what I understand as being a higher level. Commented Nov 20, 2014 at 9:47
  • 1
    I also agree that doesn't make sense to have abstractions for the domain entitites. And since both application and data access layers (as you pointed out, a repository implementation needs to return a real entity) need to use domain entities, then both depend upon the domain layer and both break the DIP. Commented Nov 20, 2014 at 9:50
  • 1
    @diegomtassis: you are fully correct (at least, to my understanding of what an application layer is). What guillaume IMHO really wants to say is that in a context of lightweight domain entities applying DI to the application layer is often just not useful. For example, to unit test the application layer one can utilize domain entities directly, assumed there is a possibility to create them without a database (probably through a mock repository). I still will not upvote this answer as long as it starts with this first, IMHO wrong, sentence.
    – Doc Brown
    Commented Nov 20, 2014 at 9:54
1

The Dependency Inversion Principle has one major exception: At some point you must do something concrete. An example is in order.

Let's say you've got a Blogging application. You've got two tables in the database, and two domain models, say Blog and Post. Let's also say you are working with an MVC framework like ASP.NET MVC, Ruby on Rails, etc.

Now, let's say you've got another class called BlogPostsController implementing the basic CRUD operations for blog posts.

The framework implements the Dependency Inversion Principle by not hard coding the following lines anywhere in its code base:

new BlogPostsController();

The framework looks at the incoming URL and constructs the name of the controller class dynamically. The framework doesn't have a hard dependency on your BlogPostsController class.

Now, let's look at the controller. Inside your controller you see new Post() peppered all over. This is not a violation of the Dependency Inversion Principle because at some point you, as a programmer, need to actually save a blog post to the database.

The Dependency Inversion Principle is mainly aimed at dependencies that aren't laser focused on the basic intent of a class, for instance creating a new "controller" in an MVC framework. You don't want a hard coded switch or if statement in order to do that. Authentication is another area where DIP is important because your BlogPostsController class shouldn't care how browser cookies are handled, or if the user logs in using a custom login page wired to a Database, or using Windows authentication or plain text authentication in the browser wired to LDAP behind the scenes.

1
  • 1
    The DIP says that high level modules shouldn't depend on low level modules, both should depend upon abstractions. That´s the original formulation by Robert Martin. Then, some versions say that the abstractions belong to the upper level, and that's the problem I see. When it comes to Domain layer - Data Access layer everything is ok, because the Repositoy interfaces belong to the Domain layer and the implementation to the Data access layer, but when it comes to application layer - domain layer is different, the domain entities belong to the Domain layer. Commented Nov 19, 2014 at 11:24
1

The DI means your Application layer shall not depend directly on the Domain Service classes, but on abstract interfaces of those service classes (actually, your diagram is already showing this). The only thing which is debatable is if those interfaces should be placed in the Domain Layer. You better place them outside, in a "Service Interface" layer, so they can be referenced from the Application layer as well as from the Domain layer. This way, you have no direct dependendencies between Application layer and Domain layer, in none of the two possible directions.

Of course, as Greg has already pointed out, somewhere in your application you have to wire everything together and actually create non-abstract instances of your Domain Service classes. Either you use a DI framework for this purpose, or you do this manually in a kind of "infrastructure" part of your program, outside of any of the classic "layers". Neither a DI framework, nor a manual start-up infrastructure is relevant in the sense of the DIP.

13
  • Exactly, the original formulation of the DIP by Uncle Bob says "High level modules should not depend upon low level modules. Both should depend upon abstractions.". Then, in small type, it also says "Each of the lower level layers are represented by an abstract class. The actual layers are then derived from these abstract classes. Each of the higher level classes uses the next lowest layer through the abstract inter-face. Thus, none of the layers depends upon any ofthe other layers.". So I assume the abstractions are not considered part of any layer. Commented Nov 19, 2014 at 14:14
  • 2
    @diegomtassis The point of DIP is to minimize dependencies. What matters is that the interface is separate from the implementation so you can develop the layers independently. Think of C code for example - the headers (interfaces) for a library can be distributed separately and you can compile your part of the code without having the library's implementation on hand. It doesn't matter where you put the library's interface in your mental model of the code as long as it can be packaged separately. Where you draw the line between what's "application" and "domain" code is subjective.
    – Doval
    Commented Nov 19, 2014 at 14:59
  • 1
    @DocBrown Domain Services are rare. I'd say they represent 20% at most of all externally accessible objects living in your Domain Layer in a typical DDD system. Commented Nov 19, 2014 at 16:11
  • 1
    @DocBrown My first comment was precisely to say that the Domain is a layer of purely concrete classes (well, at least 80% of it). You're basing your answer on the 20% that is not representative of what the Domain is. There's no point in abstracting a BlogPost, an OrderLine or a CargoShippingRoute. Commented Nov 19, 2014 at 16:54
  • 1
    @guillaume31: well, in this case I interpret your own answer above as "it breaks the DPI, but it does not matter, because the DI is not useful here". That is quite a valid point of view (though I think your wording above a little confusing).
    – Doc Brown
    Commented Nov 19, 2014 at 17:27
0

Cannot yet comment so here we go: Your misunderstanding becomes very obvious if you look at graphs of a "hexagonal architecture". Essentially DDD just wants all your sourcecode dependencies to point "inwards" into your application core, into your domain.

The architecture you layed out does not violate this principle. You merely use the DIP to topple the layers persistence and application, avoiding for the dependency to point "downwards".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.