Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Domain driven design: How to deal with complex models with a lot of data fields?

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.

like image 884
Lord Yggdrasill Avatar asked Oct 11 '15 16:10

Lord Yggdrasill


People also ask

What problem does Domain-Driven Design Solve?

The domain-driven approach is here to solve the complexity of software development. On the other hand, you can use emergent design when the challenge is simple. However, when your application is complex, the complexity will only grow, and so will your problems. Domain-driven design bases on the business domain.

Which of approach we can use for Domain-Driven Design?

Domain-Driven Design is a concept introduced by a programmer Eric Evans in 2004 in his book Domain-Driven Design: Tackling Complexity in Heart of Software. It is an approach for architecting software design by looking at software in top-down approach.

Is Domain-Driven Design still relevant?

Domain Driven Design (DDD) has recently gained additional popularity, as evidenced by new books, conference talks, and even complete conferences dedicated to it), and lots of trainings – including some by our very own colleagues here at INNOQ.

What are the strategies in extracting and formulating domain specific design principles?

Thus, we have developed three strategies for extracting and formulating domain-specific design principles: (1) analyze the best hand-designed visualizations in the domain, (2) examine prior research on the perception and cognition of visualizations, and, when necessary, (3) conduct new user studies that investigate how ...


Video Answer


2 Answers

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.

like image 188
theDmi Avatar answered Sep 20 '22 05:09

theDmi


There's an awful lot going on in your Job domain model object - it seems to mix a huge number of concerns, and (to me at least) suggests a number of bounded contexts, some of which are easy to discern for the sake of making an example.

  1. Remuneration (pay, benefits)
  2. Organisational position (reporting line)
  3. Person spec (skills)
  4. Job specification (responsibilities)
  5. etc.

When you consider the things that interact with your 'Job' model, are there any that need to inspect or mutate BOTH the Salary property and the Industry property, for example?

Without knowing the full nuances of the domain, the Salary you get for holding a position and the Industry you work in are not really connected, are they? Not a rhetorical point; these are the questions you NEED to ask the domain experts.

If they DON'T have any interaction then you have identified that these two things exist in two different BOUNDED CONTEXTS. The Salary side has no need of any interaction with the Industry side and vice versa, and even if they did, do they need to be held as state in the same process at the same time?

Think about the lifecycle of how a person becomes an employee; a person applies for a job. The job has a specification, salary range. The person attends an interview. The hirers offer the person the position. The person accepts. The person is now an employee, not a candidate any longer. The new employee is now accruing holiday and benefits and has a start date etc.

DDD teaches us that a single, unified view of the world rarely serves ANY of the concerns correctly. Please explore BOUNDED CONTEXTS - your software will be much more pliable and flexible as a result.

like image 38
Matt Avatar answered Sep 21 '22 05:09

Matt