using System;
using HRSystem.Domain.Common;
namespace HRSystem.Domain.Entities
{
public class Employee : Entity
{
private string _name;
private string _payrollNumber;
private DateTime _joinedOn;
public virtual string Name
{
get { return _name; }
set { _name = value; }
}
public virtual string PayrollNumber
{
get { return _payrollNumber; }
set { _payrollNumber = value; }
}
public virtual DateTime JoinedOn
{
get { return _joinedOn; }
set { _joinedOn = value; }
}
public static Employee Create(string role, string name, string payrollNumber, string department)
{
Employee employee = null;
if (role == "Manager")
{
employee = new Manager();
Manager manager = employee as Manager;
manager.Department = department;
manager.BecameManagerOn = DateTime.Now;
}
else
{
employee = new Employee();
}
employee.Name = name;
employee.PayrollNumber = payrollNumber;
employee.JoinedOn = DateTime.Now;
return employee;
}
public void Amend(string name, string payrollNumber, DateTime joinedOn)
{
_name = name;
_payrollNumber = payrollNumber;
_joinedOn = joinedOn;
}
}
}
And here is the code for the Manager entity:
using System;
namespace HRSystem.Domain.Entities
{
public class Manager : Employee
{
private string _department;
private DateTime _becameManagerOn;
public virtual string Department
{
get { return _department; }
set { _department = value; }
}
public DateTime BecameManagerOn
{
get { return _becameManagerOn; }
set { _becameManagerOn = value; }
}
}
}
Please note that these both ultimately inherit from the Entity class, which should be familliar to any regular users of NHibernate:
using System;
using HRSystem.Domain.Entities;
namespace HRSystem.Domain.Common
{
public class Entity
{
protected long? _id;
protected int? _hashCode;
public virtual long? Id
{
get { return _id; }
set { _id = value; }
}
public override bool Equals(object obj)
{
Entity other = obj as Entity;
if (other == null) return false;
if (!other.Id.HasValue && !_id.HasValue) return other == this;
if (!other.Id.HasValue || !_id.HasValue) return false;
return other.Id.Value == _id.Value;
}
public override int GetHashCode()
{
if (_hashCode.HasValue) return _hashCode.Value;
if (!_id.HasValue)
{
_hashCode = base.GetHashCode();
return _hashCode.Value;
}
return _id.GetHashCode();
}
}
}
So how do we model the promotion of an Employee to a Manager? Perhaps a method on the Employee called Promote, like the following code. Note that in order to change the Employee to a Manager, the extra parameters that a Manager has need to be supplied:
public void Promote(string department)
{
//Make the class I'm in a Manager, not an Employee...
}
The problem with this is that method would somehow have to change the type of the class it belongs to. This is not possible, not in C#, not in Java, not in any OO language.In Domain Driven Design, Eric Evans makes the case for factory methods. The arguments is that on a car, the methods represent things like the accelerator or brake, which change the state of the car. However, the car does not carry around the ability to build itself - that is done in a factory. But what if we really wanted to change the state of the car? I'm talking tuned engine, new alloys, new paint job, new ICE etc. Unfortunately my car doesn't have a button for that - I have to take it to the garage. When it comes back, it's hardly the same car. The car entity could have a myRide.Pimp() method, and what comes back from that is a whole new car.
For the Employee, the method would look something like this:
public virtual Manager Promote(string department)
{
Manager manager = new Manager();
manager.Id = _id;
manager.Name = _name;
manager.PayrollNumber = _payrollNumber;
manager.JoinedOn = _joinedOn;
manager.Department = department;
manager.BecameManagerOn = DateTime.Now;
return manager;
}
The code to promote an employee to the manager of ICT would look like this:
Manager manager = employee.Promote("ICT");
I'm not completely sure that Promote(string department) is the quite the right name for this, it should possibly be something like 'GetPromotedVersion(string department)', but I feel it is acceptable in this instance.The next stage is how to load the Employee and then persist it as a Manager, which I will cover in the next post.
No comments:
Post a Comment