0

I am trying to follow the DDD, and I have a doubt about modeling this example situation:

I have an entity Employee:

public class Employee{
   public Int32 Id {get;set;}
   public String Name {get;set;}
   public Decimal Salary {get;set;}
   public List<Retirement> Retirements {get;set;}
}

Is it common to all employees, a name and salary. But some may have ill health retirements. Each retirement is associated with an Employee, so I have this entity:

public Retirement {
   public Int32 Id {get;set;}
   public DateTime Begining {get;set;}
   public DateTime End {get;set;}
   public Employee Employee {get;set;}
}

My doubt is:

  • Does Employee entity really need a list of Retirement ??

(An employee exist w/o a retirement, BUT retirement does not exist w/o Employee)

  • If I have to get all employees that is retired today, is it more "logical" to search into Employee or into Retirement?
  • When I hire an employee I do not expect him to be retired. It is not a common feature. Does it change Employee behavior?
Tiago B
  • 1,937
  • 14
  • 34
  • 1
    Retirement is a dependent class of Employee. When there is no Employee there is no Retirement. But the reverse is not true. What you can do is add Retirement as one of the attributes in the employee class, And you search down the Employee whose retirement is Today on that attribute. – Miller Aug 19 '13 at 19:13
  • I may have given a bad example with this Retirement class. But my doubt is that Retirement is not common to all employees. That way I will have null attributes in most employees and for me thats wierd. – Tiago B Aug 19 '13 at 19:45
  • In DDD you can have multiple domain models. From the other comments it sounds like you need a retirement bounded context with a domain model optimized to support retired employees. Trying to make a "one size fits all" model can quickly get out of control. – Cerad Aug 19 '13 at 20:29

3 Answers3

2

Definitely, this is a data model, not a domain model.

To get started to DDD you should read the blue book a couple of times.

Here a few problems of the code you posted:

  1. Entities should be identified by shared identifiers, not Int32.
  2. The identity of an entity can't change: it can expose a readonly property, but not a mutable one
  3. Entities should be properly encapsulated: their state should change only as an effect of commands, but you are exposing it through properties
  4. Bounded contexts are key concepts in DDD: you should ponder with the domain expert if Employees and Retirements belong to the same one.
  5. If Employees and Retirements belong to the same bounded context, you should relate them via identifiers, not direct object reference.
  6. Each entity should hold only that state strictly required to enforce its invariants (those relevant within the context boundaries).

So, to answer to your questions:

  • Does Employee entity really need a list of Retirement ??

No. It could need to expose an immutable set of Retirement (eg and IEnumerable<Retirement>), if it has commands like void Retire(DateTime from, DateTime to) (obviously with proper exceptions). However, if this case Retirement would be a value object, not an entity; something like:

public sealed Retirement {
   public Retirement (DateTime begining, DateTime end)
   {
       Begining = begining;
       End = end;
   }
   public DateTime Begining {get; private set;}
   public DateTime End {get; private set;}
}
  • If I have to get all employees that is retired today, is it more "logical" to search into Employee or into Retirement?

Probably, you should have only one repository for Employees, even for those that have retired.

Generally, in OO languages, one repository for each type of entity is the best choice.

  • When I hire an employee I do not expect him to be retired. It is not a common feature. Does it change Employee behavior?

You should model invariants' violations with exceptions. If an employee cannot be retired in the same day it was hired, you should throw a specific exception documented in the Retire command.

Giacomo Tesio
  • 7,144
  • 3
  • 31
  • 48
1

First off, your question is not clear at all.

Second problem i see is Retirement class having an end date ? what s that for?

I would go with the following design:

class Employee{

   public Int32 Id {get;set;}
   public String Name {get;set;}
   public Decimal Salary {get;set;}
   public bool IsRetired {set;get;}
   public virtual Retirement Retirement{set;get;} 

}

I would get the retired employees today as follows:

employees.Where(x=>x.Retirement.Beginning < Datetime.Today);

If you have a history of retirements you can have a design as follows:

class Employee{

   public Int32 Id {get;set;}
   public String Name {get;set;}
   public Decimal Salary {get;set;}
   public bool IsRetired {set;get;}
   public virtual IEnumerable<Retirement> Retirements{set;get;} 
}
DarthVader
  • 52,984
  • 76
  • 209
  • 300
  • I just tried to create an example scenario. My real situation is way too complicated to put here. I would like to know the best way to design the "HAS-A" situation, where A doesnt need B, but B needs A to exist. – Tiago B Aug 19 '13 at 19:41
  • The way i answered would give you a HAS-A relationship. If you dont need Retirement it can be null. If you need it, you can populate it. – DarthVader Aug 19 '13 at 19:44
  • Is it good to have an attribute on a class, that is not common to the most instaces of that class? I mean, is not common to an employee get retired. It may happen few times, and for a few employees. Thats not a general behavior. – Tiago B Aug 19 '13 at 19:48
  • Now you reach my point. Isnt it wierd for you to have all new Employees with an empty Retirements? When I hire an employee I dont expect him to be retired. Retirement is not a feature of an employee, its a situation that can happen to a few of them. Did you understand my point of view? – Tiago B Aug 19 '13 at 20:12
  • I understand your point, while you can have different designs, this would work just fine. and it is simple. – DarthVader Aug 20 '13 at 06:08
0

Agree with @DarthVader. It' better for being so(Employee --> Collection< Retirement >) for now because there is few further requiment known.

Maybe it's a little weired to have a maybe-empty retirements in employee, but this hides the detail(When will the employ retire, Has he/she already retired, for example) from the employee's client.

Yugang Zhou
  • 7,123
  • 6
  • 32
  • 60