Could you please tell me what is the difference between the model Anemic Domain Model and the DDD? what is the most used nowadays ? which model is relevent when using an application the spring framework (spring data ...)?
See Martin Fowler, 2003.
The basic symptom of an Anemic Domain Model is that at first blush it looks like the real thing. There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models have. The catch comes when you look at the behavior, and you realize that there is hardly any behavior on these objects, making them little more than bags of getters and setters.
The anemic domain model is really just a procedural style design, exactly the kind of thing that object bigots like me (and Eric) have been fighting since our early days in Smalltalk
the problem with anemic domain models is that they incur all of the costs of a domain model, without yielding any of the benefits.
Anemic Domain Model is a bad thing - it's a poorly implemented DDD Domain Model where the domain objects contain little or no business logic. All the logic is in other services.
Related
So I started my 2nd developer job after spending 10 years at my first company and not really feeling I earned the title of a senior developer. It was java development but we were working with an anemic domain model and the application in my opinion was a huge difficult-to-test mess. Unfortunately the code base that I'm working with now is exactly the same and I recently had another interview where the interviewer described their Hibernate model as being light weight and just containing setters getters as well. So it appears this is quite common across the industry.
There's plenty of articles describing the anemic domain model as an anti-pattern and also some articles where it is described as perfectly fine for simple systems. But I haven't seen any examples of making the best out of working with a large enterprise system with an ADM.
Has anyone had experience with this? Are there any best practices for creating a loosely coupled system that contains unit tests that are readable and actually valuable? I really want to take pride in my work but am losing hope.
Edit:
To the developers that advocate business logic being contained in services:
how do you limit the dependencies on other services within each service? i.e. OrderCancelService needs CustomerAccountService and PaymentService and RefundCalculatorService and RewardsAdjustmentService, etc This tends to lead to several mock objects in tests making tests way too tied into implementation
how do you limit the number of parameters in each service's method? Since everything needs to be passed around and objects don't operate on their own data, this seems to lead to very large and confusing method signatures
Do you apply tell, don't ask principle to service objects? I see a lot of services that return values which are then used by the calling service to make decisions in execution flow.
You may consider your persistence model, which you now think about as the anemic domain model, as what it is - the persistence model for your domain model state.
If you do that, you probably can create a real domain model, which will have its state stored inside the persistence model objects (State pattern). Then, you can have your logic inside this new domain model. Reading your comment above, I would say you can convert your "manager/service" classes to state machines, you can call them aggregates if they match with transaction boundaries, and have their state in POJOs persisted by Hibernate as it is done now.
Probably similar questions have been asked many times but I think that every response helps to make the understanding of DDD better and better. I would like to describe how I perceive certain aspects of DDD. I have some basic uncertainties around it and would appreciate if someone could give a solid and practical anwser. Please note, these questions assume a 'classic' approach to DDD. This means using ORM's etc. Approaches like CQRS and event sourcing are not considered here.
Aggregates and entities are the primary objects that implement domain logic. They have state and identity. In this context, I perceive domain logic as the set of all commands that mutate that state. Does that make sense? Why is domain logic related exclusively to state? Is it legal to model domain objects that have no identitiy or no state? Why can't a domain object be implemented as a transaction script? Example: Consider an object that recommends you a partner for a dating site. That object has no real state, but it does quite a lot of domain logic? Putting that into the service layer implies that the domain model cannot cover all logic.
Access to other domain objects. Can aggregates have access to a repository? Example: When a (stateful) domain object needs to have access to all 'users' of the system to perform its work, it would need access them via the repository. As a consequence, an ORM would need to inject the repository when loading the object (which might be technically more challenging). If objects can't have access to repositories, where would you put the domain logic for this example? In the service layer? Isn't the service layer supposed to have no logic?
Aggregates and entities should not talk to the outside world, they are only concerned about their bounded context. We should not inject external dependencies (like IPaymentGateway or IEmailService) into a domain object, this would cause the domain to handle exceptions that come from outside. Solution: an event based approach. How do you send events then? You still need to inject the correct 'listeners' every time you instantiate a domain object. ORM's are about restoring 'data' but are not primarly intended to inject dependencies. Do we need an DI-ORM mix?
Domain objects and DTO's. When you query an aggregate root for its state does it return a projection of its state (DTO) or the domain objects themselves? In most models that I see, clients have full access to the domain data model, introducing a deep coupling to the actual structure of the domain. I perceive the 'object graph' behind an aggregate to be its own buisness. That's encapsulation, right? So for me an aggregate root should return only DTO's. DTO's are often defined in the service layer but my approach is to model it in the domain itself. The service layer might still add another level of abstraction, but that's a different choice. Is that a good advice?
Repositories handle all CRUD operations at the aggregate root level. What about other queries? Queries return DTO's and not domain objects. For that to work, the repsitory must be aware of the data structure of the domain which introduces a coupling. My advice is similar to before: Use events to populate views. Thus, the internal structure is not made public, only the events carry the necessary data to build up the view.
Unit of work. A controller at the system boundary will instantiate commands and pass them to a service layer which in turn loads the appropriate aggregates and forwards the commands. The controller might use multiple commands and pass them to multiple services. This is all controlled by the unit of work pattern. This means, repositories, entities, services - all participate in the same transaction. Do you agree?
Buisness logic is not domain logic. From a buisness perspective the realization of a use case might involve many steps: Registering a customer, sending an email, create a storage account, etc. This overall process can impossibly fit in a domain aggregate root. The domain object would need to have access to all kind of infrastructure. Solution: Workflows or sagas (or transaction script). Is that a good advice?
Thank you
The first best practice I can suggest is to read the Evans' book. Twice.
Too many "DDD projects" fail because developers pretend that DDD is simply OOP done right.
Then, you should really understand that DDD is for applications that have to handle very complex business rules correctly. In a nutshell: if you don't need to pay a domain expert to understand the business, you don't need DDD. The core concept of DDD, indeed, is the ubiquitous language that both the coders, the experts and the users share to understand each other.
Furthermore, you should read and understand what aggregates are (consistency boundaries) by reading Effective Aggregate Design by Vernon.
Finally, you might find useful the modeling patterns documented here.
Despite my comment above, I took a stab at your points. (note: I'm not Eric Evans or Jimmy Nilsson so take my "advice" with a grain of salt).
Your example "Consider an object that recommends you a partner for a dating site.", belongs in a Domain service (not an infrastructure service). See this article here - http://lostechies.com/jimmybogard/2008/08/21/services-in-domain-driven-design/
Aggregates do not access repositories directly, but they can create a unit of work which combines operations from multiple domain objects into one.
Not sure on this one. This should really be a question by itself.
That's debatable, in theory, the domain entities would not be directly available outside the aggregate root, but that is not always practical. I consider this decision on a case-by-case basis.
I not sure what you mean exactly by "queries". If modeling all possible "reading" scenarios in your domain does not seem practical or provide sufficient performance, it suggests a CQRS solution is probably best.
Yes, I agree. UOW is a tool in your toolbox that you can use in various layers.
This statement is fundamentally wrong "Business logic is not domain logic". The domain IS the representation business logic, thus one reason for using ubiquitous language.
I am getting my feet wet with DDD (in .Net) for the first time, as I am re-architecting some core components of a legacy enterprise application.
Something I want to clear up is, how do we implement persistence in a proper DDD architecture?
I realize that the domains themselves are persistence ignorant, and should be designed using the "ubiquitous language" and certainly not forced into the constraints of the DAC of the month or even the physical database.
Am I correct that the Repository Interfaces live within the Domain assembly, but the Respository Implementations exist within the persistence layer? The persistence layer contains a reference to the Domain layer, never vice versa?
Where are my actual repository methods (CRUD) being called from?
Am I correct that the Repository Interfaces live within the Domain
assembly, but the Repository Implementations exist within the
persistence layer? The persistence layer contains a reference to the
Domain layer, never vice versa?
Yes, this is a very good approach.
Where are my actual repository methods (CRUD) being called from?
It might be a good idea to not think in CRUD terms because it is too data-centric and may lead you into Generic Repository Trap. Repository helps to manage middle and the end of life for domain objects. Factories are often responsible for beginning. Keep in mind that when the object is restored from the database it is in its midlife stage from DDD perspective. This is how the code can look like:
// beginning
Customer preferredCustomer = CustomerFactory.CreatePreferred();
customersRepository.Add(preferredCustomer);
// middle life
IList<Customer> valuedCustomers = customersRepository.FindPrefered();
// end life
customersRepository.Archive(customer);
You can call this code directly from you application. It maybe worth downloading and looking at Evan's DDD Sample. Unit of Work pattern is usually employed to deal with transactions and abstracting your ORM of choice.
Check out what Steve Bohlen has to say on the subject. The code for the presentation can be found here.
I was at the presentation and found the information on how to model repositories good.
Am I correct that the Repository Interfaces live within the Domain
assembly, but the Repository Implementations exist within the
persistence layer? The persistence layer contains a reference to the
Domain layer, never vice versa?
I disagree here, let's say a system is comprised of the following layers:
Presentation Layer (win forms, web forms, asp.net MVC, WPF, php, qt, java, , ios, android, etc.)
Business Layer (sometimes called managers or services, logic goes here)
Resource Access Layer (manually or ORM)
Resource/Storage (RDBMS, NoSQL, etc.)
The assumption here is that the higher you are the more volatile the layer is (highest being presentation and lowest being resource/storage). It is because of this that you don't want the resource access layer referencing the business layer, it is the other way around! The business layer references the resource access layer, you call DOWN not UP!
You put the interfaces/contracts in their own assembly instead, they have no purpose in the business layer at all.
What's the difference between UML-Modeling and UML-Design? Or is it the same concept?
Thank you.
It's the same thing. Both refer to planning out your app (and documenting it) using UML.
Not really, even when both are part of the Structural Model (aim to model the static structure of the scenario), they use different objects.
The Domain Model instances are real-world objects. It is concerned with the problem domain and attempts to create a useful working model of the domain in which you are creating a solution for.
On the other hand, Design Model instances are software objects, which may be technology frameworks, databases, user interfaces, etc. you are using to get working software. You can say that Design Model is inspired by the Domain Model.
In Eric Evans' Domain Driven Design approach, would it be a good idea to use Rocky Lhotka's CSLA.NET for designing Business Entities for Domain Layer?
Looks like we can do that.
It's been a while since I read the CSLA book, but I do recall that it has support for a N-tier model that allows you to remote your domain objects. While interesting and maybe even useful in some cases, I'd be afraid the added complexity would not be worth it. Personally I would stick with a POCO domain model with an unobtrusive ORM like NHibernate unless my requirements dictated something more complicated.