Well I am trying to apply domain driven design principles for my application, with a rich domain model that contains both data fields and business logic. I've read many DDD books, but it seems that their domain models(called entities) are very simple. It becomes a problem when I have a domain model with 10-15 data fields, such as the one below:
class Job extends DomainModel{
protected int id;
protected User employer;
protected string position;
protected string industry;
protected string requirements;
protected string responsibilities;
protected string benefits;
protected int vacancy;
protected Money salary;
protected DateTime datePosted;
protected DateTime dateStarting;
protected Interval duration;
protected String status;
protected float rating;
//business logic below
}
As you see, this domain model contains a lot of data fields, and all of them are important and cannot be stripped away. I know that a good rich domain model should not contain setter methods, but rather pass its data to constructor, and mutate states using business logic. However, for the above domain model, I cannot pass everything to the constructor, as it will lead to 15+ parameters in constructor method. A method should not contain more than 6-7 parameters, dont you think?
So what can I do to deal with a domain model with a lot of data fields? Should I try to decompose it? If so, how? Or maybe, I should just use a Builder class or reflection to initialize its properties upon instantiation so I wont pollute the constructor with so many arguments? Can anyone give some advice? Thanks.
What you've missed is the concept of a Value Object. Value objects are small, immutable objects with meaning in the respective domain.
I don't know the specifics of your domain, but looking at your Job
entity, there could be a value object JobDescription
that looks like this:
class JobDescription {
public JobDescription(string position, string requirements, string responsibilities) {
Position = position;
Requirements = requirements;
Responsibilities = responsibilities;
}
public string Position {get;}
public string Requirements {get;}
public string Responsibilities {get;}
}
This is C# code, but I think the idea should be clear regardless of the language you are using.
The basic idea is to group values in a way that makes sense in the respective domain. This means of course that value objects can also contain other value objects.
You should also ensure that value objects are compared by value instead of by reference, e.g. by implementing IEquatable<T>
in C#.
If you refactor your code with this approach, you will get fewer fields on your entity, so using constructor injection (which is highly recommended) becomes feasible again.
Further notes regarding your example code that are not directly connected to the question:
The domain model is the whole thing, an entity is part of it. So your base class should be called Entity
and not DomainModel
.
You should make the fields of your class private
and provide protected
accessors where required to maintain encapsulation.