Ich versuche zu verstehen, wie und wo Domänenmodellfabriken implementiert werden sollen. Ich habe mein Company
Aggregat als Demo aufgenommen, wie ich es gemacht habe.
Ich habe meine Entwurfsentscheidungen am Ende aufgenommen - ich würde mich über Kommentare, Vorschläge und Kritik zu diesen Punkten freuen.
Das Company
Domain-Modell:
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;
}
}
Die CompanyFactory
Domain Factory:
Diese Klasse wird verwendet, um sicherzustellen, dass Geschäftsregeln und Invarianten beim Erstellen neuer Instanzen von Domänenmodellen nicht verletzt werden. Es würde sich in der Domänenschicht befinden.
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);
}
}
Der CompanyMapper
Entity Mapper:
Diese Klasse wird verwendet, um Rich-Domain-Modelle und Entity Framework-Datenentitäten zuzuordnen. Es würde sich in Infrastrukturschichten befinden.
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
};
}
}
Der
Company
Konstruktor wird als deklariertinternal
.
Grund: Nur die Factory sollte diesen Konstruktor aufrufen.internal
stellt sicher, dass keine anderen Ebenen es instanziieren können (Ebenen werden durch VS-Projekte getrennt).Die
CompanyFactory.CreateNew(string name)
Methode wird beim Erstellen einer neuen Firma im System verwendet.
Grund: Da es noch nicht beibehalten worden wäre, muss eine neue eindeutige Identität dafür generiert werden (unter Verwendung derIIdentityFactory
).Die
CompanyFactory.CreateExisting(int id, string name)
Methode wirdCompanyRepository
beim Abrufen von Elementen aus der Datenbank verwendet.
Grund: Das Modell hätte bereits eine Identität, daher müsste diese an das Werk geliefert werden.Das
CompanyMapper.MapFrom(CompanyTable dataEntity)
wird von verwendet,CompanyRepository
wenn Daten aus der Persistenz abgerufen werden.
Grund: Hier müssen Entity Framework-Datenentitäten Domänenmodellen zugeordnet werden. DasCompanyFactory
wird verwendet, um das Domänenmodell zu erstellen, um sicherzustellen, dass die Geschäftsregeln erfüllt werden.Das
CompanyMapper.MapFrom(Company domainEntity)
wird von verwendet,CompanyRepository
wenn Modelle zur Persistenz hinzugefügt oder aktualisiert werden.
Grund: Domänenmodelle müssen direkt auf Datenentitätseigenschaften abgebildet werden, damit Entity Framework erkennen kann, welche Änderungen in der Datenbank vorgenommen werden müssen.
Vielen Dank
CompanyFramework.CreateExisting
Konstrukt? Eine Sache, die ich nicht als Schwäche sehe, ist dieIIdentityFactory
. Wenn die IDs aus einer Datenbank generiert werden, sollten Sie über eine Mechanik verfügen, die dies verspottet, um Unit-Tests mit einer Datenbank zu ermöglichen.IIdentityFactory
. In DDD müssen Entitäten ab dem Zeitpunkt der Erstellung eine Identität haben. Leider haben wir nicht den Luxus,Guid
Typen verwenden zu können. Wir müssenint Ids
aus der Datenbank generieren, bevor Persistenz auftritt. Ein weiterer Grund für eine Fabrik.