I am trying to understand how and where to implement domain model factories. I have included my Company
aggregate as a demo of how I have done it.
I have included my design decisions at the end - I would appreciate any comments, suggestions, critique on those points.
The Company
domain model:
public class Company : DomainEntity, IAggregateRoot
{
private string name;
public string Name
{
get
{
return name;
}
private set
{
if (String.IsNullOrWhiteSpace(value))
{
throw new ArgumentOutOfRangeException("Company name cannot be an empty value");
}
name = value;
}
}
internal Company(int id, string name)
{
Name = name;
}
}
The CompanyFactory
domain factory:
This class is used to ensure that business rules and invariants are not violated when creating new instances of domain models. It would reside in the domain layer.
public class CompanyFactory
{
protected IIdentityFactory<int> IdentityFactory { get; set; }
public CompanyFactory(IIdentityFactory<int> identityFactory)
{
IdentityFactory = identityFactory;
}
public Company CreateNew(string name)
{
var id = IdentityFactory.GenerateIdentity();
return new Company(id, name);
}
public Company CreateExisting(int id, string name)
{
return new Company(id, name);
}
}
The CompanyMapper
entity mapper:
This class is used to map between rich domain models and Entity Framework data entities. It would reside in infrastructure layers.
public class CompanyMapper : IEntityMapper<Company, CompanyTable>
{
private CompanyFactory factory;
public CompanyMapper(CompanyFactory companyFactory)
{
factory = companyFactory;
}
public Company MapFrom(CompanyTable dataEntity)
{
return DomainEntityFactory.CreateExisting(dataEntity.Id, dataEntity.Name);
}
public CompanyTable MapFrom(Company domainEntity)
{
return new CompanyTable()
{
Id = domainEntity.Id,
Name = domainEntity.Name
};
}
}
The
Company
constructor is declared asinternal
.
Reason: Only the factory should call this constructor.internal
ensures that no other layers can instantiate it (layers are separated by VS projects).The
CompanyFactory.CreateNew(string name)
method would be used when creating a new company in the system.
Reason: Since it would not have been persisted yet, an new unique identity will need to be generated for it (using theIIdentityFactory
).The
CompanyFactory.CreateExisting(int id, string name)
method will be used by theCompanyRepository
when retrieving items from the database.
Reason: The model would already have identity, so this would need to be supplied to the factory.The
CompanyMapper.MapFrom(CompanyTable dataEntity)
will be used by theCompanyRepository
when retrieving data from persistence.
Reason: Here Entity Framework data entities need to be mapped into domain models. TheCompanyFactory
will be used to create the domain model to ensure that business rules are satisfied.The
CompanyMapper.MapFrom(Company domainEntity)
will be used by theCompanyRepository
when adding or updating models to persistence.
Reason: Domain models need to be mapped straight onto data entity properties so that Entity Framework can recognise what changes to make in the database.
Thanks