Resolving Anemic Domain Model example - domain-driven-design

I am reviewing areas where I can optimize the design for my mortgage calculation tool, mostly for learning purposes. After reading about Anemic Domain Models, I became interested in creating Rich Models, and noticed that my current implementation might have anemia! Here is the current implementation in pseudocode:
class MortgageCalculator {
Mortgage mortgage; // mortgage object containing loanAmount, interest rate, etc.;
calculateMonthlyPayment(); // calculates monthly payments using mortgage object's properties
}
class Mortgage { // Anemic?
loanAmount;
interestRate;
}
Currently the Mortgage object serves primarily for data-transfer between objects, etc.
Here are some revision options I am considering:
Remove Mortgage object out of the MortgageCalculator and use Mortgage
purely as a DTO while the calculator's methods take arguments (e.g,
calculateMonthlyPayment(loanAmount,interestRate). This would help with decoupling MortgageCalculator from the Mortgage object, but would still have Mortgage as an anemic model.
Merge both classes into one "rich" MortgageCalculator model, which contains both the business logic (e.g, calculateMonthlyPayment) and mortgage properties (e.g, loanAmount). My
concern here is that I am not sure if it is necessary for a
calculator object to hold its operands as instance variables, but
they would facilitate data transfer, storage and perhaps resolve the anemia?
I am wondering what the ideal approach would be, or if I am missing the point?

Perhaps the Mortgage object can perform parts of the calculation. For example, consider an object that calculates an order total:
for (Line line : orderLines)
int total += line.getPrice() * line.getQuantity();
This is a known as Feature Envy, and could be:
for (Line line : orderLines)
int total += line.calculateTotal();

MortgageCalculator is not actually domain entity because it is not populated into database, so to avoid anemic you can merge logic into Mortgage entity:
class Mortgage {
loanAmount;
interestRate;
calculateMonthlyPayment();
}
Another thing: DTO is different with domain entity, DTO is for transferring data in distribution environment, whereas domain entity is to focus on domain logic.
You can use domain entity as DTO because in some cases, DTO has the same properties with Domain Entity. But, most of cases, depend on each clients, maybe they need to get data which requires more than one domain entities. So, for separation of concern and more maintainable, it would be suggested to create DTO separated with domain entity:
class MortgageDto {
loanAmount;
interestRate;
}

You can't do DDD if you don't know your bounded contexts (BC). So what is the BC in this case? Because all depends on that.
Form what I understand in your case, I think it's good you have a MortageCalculator , because you can have multiple ways of calculating a mortgage . This class can have amethod which wiil take a Mortgage argument. OF course, what I've said can be wrong because I don't know your domain.
It's always hard to anwser a concrete question about DDD if one doesn't happen to be an expert in the required domain. But all starts with the BC so again, what is your BC and what is the business role of the Mortgage?

Related

DDD modeling aggregate with few invariants and many fields

I thinking about modeling aggregates, invariants, data etc. There is common advice to design aggregates to be small. I have problem a with correct splitting domain and simple CRUD.
Let's assume that we have application where we are able to create project and join to it collaborators. There are a lot of informations related with project at the stage of creating (name, description, project_aims, notes, creation date, modified date, collaborators). How to correct design aggregate where there is a rule which check that we can only add 5 collaborators. Taking into consideration that fields name, description, project_aims, notes doesn't really take part in any business rule and there is only requirements that this fields should'nt be empty (those are really invariants?) should those fields really be a part of aggregate?
Is'nt that our real Domain (aggregates, entities, value objects, policies) should hold only data which take part with protecting invariants or help making business decisions?
If so, how to (create) project described above? Should class with all that nonsignificant (from a business point of view) fields be implemented as anemic model outside the Domain and Aggregate root should just have method addCollaborator which protect quantity of collaborators? Is it good idea to save anemic class object using Dao (operates on db table) and for Domain implementation of aggregate, create Repository?
How to add first collaborator during creating project as at the beggining we create anemic class object outside Domain?
Thank you for any help and advice
Papub
"How to correct design aggregate where there is a rule which check that we can only add 5 collaborators"
Project AR most likely maintains a set of collaborators and throws whenever it's size would exceed 5.
"there is only requirements that this fields should'nt be empty (those are really invariants?)"
Yes, these may be simple rules, but are still are invariants.
"should hold only data which take part with protecting invariants or help making business decisions"
This can be done when modeling ARs with EventSourcing, where you'd only materialize the properties needed to check invariants on the AR, while having all data in the full set of events.
"implemented as anemic model outside the Domain and Aggregate root should just have method addCollaborator which protect quantity of collaborators".
You could always attempt to mix CRUD-driven anemia with rich always-valid models, but the anemic/rich model decision is usually consistent for a given Bounded Context (BC), meaning you may have CRUDDy BCs and rich domain model BCs, but rarely both strategies in the same BC.
For instance, perhaps "Project Definition" is a CRUD-driven BC while "Collaboration" isin't. Those BCs may not make any sense, but it's just to give an example.
Furthermore, don't forget DDD tactical patterns are there to allow manage the complexity, they aren't hard rules. If handling a part of your AR through services and another (where there's more meat) with rich behaviors then perhaps that's acceptable. Still, I'd probably prefer CRUDDy behaviors on the ARs themselves like an update method rather than giving up in the anemic direction.

How to Approach Domain Modelling with Polymorphic Entity in Domain-Driven Design?

I am rebuilding a software in accounting. This sofware can handle many types of transactions, e.g. sales, inventory restock, and expenses. I have no background in accounting, but I learned some concepts online. I am trying to model the domain with these principles in mind:
A journal entry consists of several recordings, each of which is either a debit or credit. These recordings' total of debit and credit must be equal (balanced) in a given journal entry
A journal entry must be created based off of a source document. One cannot simply create a journal entry without any reason.
From those, I conclude that there has to be these entities present:
JournalEntry entity, which has many JournalEntryItem value objects. This entity is responsible for keeping all its entries in a balanced state.
SourceDocument entity, which has some information of transactions being made
Both JournalEntity and SourceDocument are each an aggregate root, with JournalEntity referencing to a SourceDocument identity.
Now here is the problem. Source documents that are the basis of journal entry creation, can be different things with different behaviors. For example, an 'expense' source document may consists of list of pair of expense category and expense amount, while a 'sales' source document may consists of related inventories, amount of each inventories, and the price of each inventory per one unit.
This makes me think of another approach in the model:
Create an abstract SourceDocument class, with shared properties like date of creation and identity attribute
Create SalesSourceDocument, ExpenseSourceDocument, etc., that are extended from the abstract SourceDocument
JournalEntry entity will still have to reference SourceDocument identity.
While this can make sense, I don't think this is the best way to model the problem in DDD, specifically because it requires to have an abstract entity.
From the sources I read online about DDD, when encountering such problem where I need an abstract entity, I need to separate it into different bounded contexts. However, I'm not sure if it can be done, because a SourceDocument identity may return a concrete SalesSourceDocument in 'sales' context, but it may also return nothing in 'expense' context.
What is the best way to approach this problem?
I think what's important to recognize here is that the source document terminology is to describe the relationship between a journal entry and a document, from a JournalEntry's perspective. Documents are ARs of their own, which can most likely exist without a journal so why should their abstraction be named after the relationship with another AR?
Source document most likely is a necessary terminology to describe the document relating to a journal entry and chances are it will be part of your model too, but perhaps in the form of a value object such as SourceDocument { id, type }.
That doesn't mean you couldn't have a Document abstraction as well if useful: there's no reason to avoid polymorphism at all cost when it's useful.
I may be wrong with that analysis (all models are wrong anyway), but I just wanted to give you a different perspective on that specific modeling aspect.
I am rebuilding a software in accounting. This sofware can handle many
types of transactions, e.g. sales, inventory restock, and expenses. I
have no background in accounting, but I learned some concepts online.
If you can learn your whole domain online then chances are that it's a generic sub-domain where an off the shelf product can most likely be bought. Rather than going online and try to come up with a model on your own you should be involving domain experts: perhaps your entire vision is wrong here.
Furthermore, given the source documents will most likely live in different contexts, it seems like the Accounting context could be acting as a supporting BC that doesn't have explicit knowledge or dependency on other BCs.
What is the best way to approach this problem?
Treat your separate use cases as separate until you discover domain concerns that require aligning them.
Your sales documents and your expense documents are different things, and your data model should reflect that: the information associated with each is stored in different tables; the schemas of those tables evolve in responses to changes specific to the domain that they manage.
Duplication is far cheaper than the wrong abstraction -- Sandi Metz
This is one of those questions where an answer can become quite long so I'm going to do my best to keep it short. I am no expert in accounting but I have had to implement a lot of it in my career. As such I will be developing one of those generic sub-domains when I have time (one day).
One of my recommendations is not to build classification as a code structure. However, it isn't always easy to identify classification. A "simple" example may be a Customer. We could have a GoldCustomer and SilverCustomer. We could subclass these from an abstract Customer. We have to decide why we are doing this. If, for example, it is to determine that some minimum order amount per period requires and upgrade/downgrade the customer Type in order to qualify for some discount then that can be easily abstracted into its own concept. If the business decides to add PlatinumCustomer or BronzeCustomer then we have to make code changes to inherit from the abstract class. If we rather model that concept as something that can be defined through additional instances (data) then we do not need to have code structures representing those:
public class CustomerDiscount
{
public int Type { get; }
public decimal MinimumSpend { get; }
public int Period { get; }
public decimal DiscountPercent { get; }
}
What I am getting at is that a generic subdomain that may be purchased off-the-shelf (as stated by #p|a|x) would not know about any concepts in any other domain but would need to be able to represent the requirement as a set of instances that relate to its domain specific language.
At the heart of it accounting is about an Account that has debits and credits. From there it is a matter of grouping transactions using a Journal and having some form of PostingRule that could represent the breakdown of amounts into transactions. If memory serves Martin Fowler has some accounting bits in his analysis patterns book. Your accounts are also classified using a Chart of Accounts (COA) and sometimes these are standardised (SCOA). These classifications are what make things interesting in that they typically also determine your posting rules.
I am no fan of abstract classes in your domain as they tend to complicate matters but, as mentioned by #p|a|x, there is no reason to avoid them totally. I find abstract classes and inheritance in general are better suited to technical concerns than business domain models. If you have some technical solution to a business bit then you may find them useful. If you do find yourself considering inheritance of any kind try to see if you cannot represent the relationship using some other concept/class.

DDD Factory Responsibility

If have the following Code.
public class CountryFactory : IEntityFactory
{
private readonly IRepository<Country> countryRepository;
public CountryFactory(IRepository<Country> countryRepository)
{
this.countryRepository = countryRepository;
}
public Country CreateCountry(string name)
{
if (countryRepository.FindAll().Any(c => c.Name == name))
{
throw new ArgumentException("There is already a country with that name!");
}
return new Country(name);
}
}
From a DDD approach, is the the correct way to create a Country. Or is it better to have a CountryService which checks whether or not a country exists, then if it does not, just call the factory to return a new entity. This will then mean that the service will be responsible of persisting the Entity rather than the Factory.
I'm a bit confused as to where the responsibility should lay. Especially if more complex entities needs to be created which is not as simple as creating a country.
In DDD factories are used to encapsulate complex objects and aggregates creation. Usually, factories are not implemented as separate classes but rather static methods on the aggregate root class that returns the new aggregate.
Factory methods are better suited than constructors since you might need to have technical constructors for serialization purposes and var x = new Country(name) has very little meaning inside your Ubiquitous Language. What does it mean? Why do you need a name when you create a country? Do you really create countries, how often new countries appear, do you even need to model this process? All these questions arise if you start thinking about your model and ubiquitous language besides tactical pattern.
Factories must return valid objects (i.e. aggregates), checking all invariants inside it, but not outside. Factory might receive services and repositories as parameters but this is also not very common. Normally, you have an application service or command handler that does some validations and then creates a new aggregate using the factory method and adds it to the repository.
There is also a good answer by Lev Gorodinski here Factory Pattern where should this live in DDD?
Besides, implementation of Factories is extensively described in Chapter 11 of the Red Book.
Injecting a Repository into a Factory is OK, but it shouldn't be your first concern. The starting point should be : what kind of consistency does your business domain require ?
By checking Country name uniqueness in CountryFactory which is part of your Domain layer, you give yourself the impression that the countries will always be consistent. But the only aggregate is Country and since there is no AllCountries aggregate to act as a consistency boundary, respect of this invariant will not be guaranteed. Somebody could always sneak in a new Country that has exactly the same name as the one being added, just after you checked it. What you could do is wrap the CreateCountry operation into a transaction that would lock the entire set of Countries (and thus the entire table if you use an RDBMS) but this would hurt concurrency.
There are other options to consider.
Why not leverage a database unique constraint to enforce the Country name invariant ? As a complement, you could also have another checkpoint at the UI level to warn the user that the country name they typed in is already taken. This would necessitate another "query" service that just calls CountryRepository.GetByName() but where the returned Countries are not expected to be modified.
Soon you'll be realizing that there are really two kinds of models - ones that can give you some domain data at a given moment in time so that you can display it on a user interface, and ones that expose operations (AddCountry) and will guarantee that domain invariants always hold. This is a first step towards CQRS.
What is the frequency of Countries being added or modified ? If it is that high, do we really need a Country name to be unique at all times ? Wouldn't it solve a lot of problems if we loosened up the constraints and allowed a user to temporarily create a duplicate Country name ? A mechanism could detect the duplicates later on and take a compensating action, putting the newly added Country on hold and reaching out to the user to ask them to change the name. A.k.a eventual consistency instead of immediate consistency.
Does Country need to be an Aggregate ? What would be the cost if it was a Value Object and duplicated in each entity where it is used ?

DDD: Large Aggregate Root - Person

I am building a system to manage person information. I have an ever growing aggregate root called Person. It now has hundreds of related objects, name, addresses, skills, absences, etc. My concern is that the Person AR is both breaking SRP and will create performance problems as more and more things (esp collections) get added to it.
I cannot see how with DDD to break this down into smaller objects. Taking the example of Absences. The Person has a collection of absence records (startdate, enddate, reason). These are currently managed through the Person (BookAbsence, ChangeAbsence, CancelAbsence). When adding absences I need to validate against all other absences, so I need an object which has access to the other absences in order to do this validation.
Am I missing something here? Is there another AR I have not identified? In the past I would have done this via an "AbsenceManager" service, but would like to do it using DDD.
I am fairly new to DDD, so maybe I am missing something.
Many Thanks....
The Absence chould be modeled as an aggregate. An AbsenceFactory is reposible for validating against other Absence s when you want to add a new Absence.
Code example:
public class AbsenceFactory {
private AbsenceRepository absenceRepository;
public Absence newAbsenceOf(Person person) {
List<Absence> current =
absenceRepository.findAll(person.getIdentifier());
//validate and return
}
}
You can find this pattern in the blue book (section 6.2 Factory if I'm not mistaken)
In other "modify" cases, you could introduce a Specification
public class SomeAbsenceSpecification {
private AbsenceRepository absenceRepository;
public SomeAbsenceSpecification(AbsenceRepository absenceRepository) {
this.absenceRepository=absenceRepository;
}
public boolean isSatisfiedBy(Absence absence) {
List<Absence> current =
absenceRepository.findAll(absence.getPersonIdentifier());
//validate and return
}
}
You can find this pattern in the blue book(section 9.2.3 Specification)
This is indeed what makes aggregate design so tricky. Ownership does not necessarily mean aggregation. One needs to understand the domain to be able to give a proper answer so we'll go with the good ol' Order example. A Customer would not have a collection of Order objects. The simplest rule is to think about deleting an AR. Those objects that could make sense in the absence of the AR probably do not belong on the AR. A Customer may very well have a collection of ActiveOrder objects, though. Of course there would be an invariant stating that a customer cannot be deleted if it has active orders.
Another thing to look out for is a bloated bounded context. It is conceivable that you could have one or more bounded contexts that have not been identified leading to a situation where you have an AR doing too much.
So in your case you may very well still be interested in the Absence should the Customer be deleted. In the case of an OrderLine it has no meaning without its Order. So no lifecycle of its own.
Hope that helps ever so slightly.
I am building a system to manage person information.
Are you sure that a simple CRUD application that edit/query RDBMS's tables via SQL, wouldn't be a cheaper approach?
If you can express the most of the business rules in term of data relations and table operations, you shouln't use DDD at all.
I have an ever growing aggregate root called Person.
If you actually have complex business rules, an ever growing aggregate is often a syntom of undefined (or wrongly defined) context boundaries.

Loading a Value object in List or DropdownList, DDD

I need to clarify something.
Have Person Aggreagate , 2 VOs (Country, StateProvince).
I want to load all country in my presentation layer (i am using mvc)
Evan says you only use repository (IPersonRepository) to work with root entity (it should always return just a reference to the Aggregate Root)
public interface IPersonRepository()
{
void savePerson(Person p);
void removePerson(Person p);
Ilist<Person> getPerson();
}
what i usually do to solve this :
Add in IPersonRepository this method
IList<Country> LookupCountrysOfPerson();
In Infra layer implement the Domain interfaces like this:
public IList<Person> LookupCountrysOfPerson()
{
return Session.CreateQuery("from Countrys").List<Person>());
}
My partner says im wrong.
Sometimes you have to sacrifice your domain model in order to accomplish some task
What is the best way to do this?
with code please! :)
I would say it's unlikely that you need country to be an entity. I suspect that country is nothing more than reference data, much like a person's title would be. Is there any behavior associated to country in your domain? I suspect it's just what's printed onto letters/envelops.
This question is somewhat similar to this one which I answered a while back:
Simple aggregate root and repository question
My suggestion is that you implement a Lookup service that your client can make use of and which is cached. Ignore the rules of DDD and anything to do with aggregates or repositories for this. As someone else has mentioned, this is where CQRS's ideology comes into play; the client shouldn't have to go through the domain in order to get data. The domain is purely transactional, not designed for queries.
This article explains how to build a generic lookup service for reference data for things that typically fill dropdowns in the UI (i.e. Title, Country etc)
http://wtfperminute.blogspot.com/2011/02/working-with-reference-data-lookups.html
Evans also says (pg 170) "An entity as basic as Location may be used by many objects for many reasons..."
I would also consider making Country an entity for the reasons given above. Perhaps more importantly, it is a low level object. You probably are also even supplying Country by configuration rather than through any actual domain activities. Therefore I would remove it from the Person and make it a standalone entity.
Also for this type of object you may not really need a dedicated repository, consider creating a single lookup service that provides query access for a group of similar objects of this nature.
If in your domain country is actually a VO (you don't want to maintain a thread of identity in the country name was changed etc.) which is the most common scenario, I would add a specialized class in the data access layer to return a list of all countries as VOs. I would also add caching (2nd level cache in NHibernate) to the country entity and list all countries query so that I don't have to hit the DB each time.
Actually, this is where CQRS really shines. CQRS acknowledges that you don't have to go through the domain layer in order to get some data for presentation purposes. In CQRS you just grab some data.
It sounds like countries are not in fact value objects here; they have distinct identities and are important for business purposes outside of your Person objects. They should become entities, and be treated in the fashion appropriate to them.
Think of it this way: let's say some volatile country had their current dictator overthrown and got a name change. The Person object's reference to a Country should still be valid, because the Country is not defined by its attributes (i.e. the string denoting its name), but by its identity.

Resources