I am trying to apply DDD to the design of a Release Management system.
Domain Entities
Project
: The project/product/system.ProjectEnvironment
: The environments (Test, Staging, Prod) that exist for this project. Each project has its own defined environments.-
ProjectVersion
: A specific version of the project. This would be associated with a deployment package.
Aggregate Boundary
From this I would have Project
be the aggregate root and ProjectEnvironment
and ProjectVersion
be aggregates of Project
. Neither of these can exist without Project
.
Repository
I would then only have a ProjectRepository
which would provide persisted Projects
with all the included ProjectVersion
and ProjectEnvironment
aggregates (and consequently can only be accessed through their respective Project
).
Questions
-
Should there be a
VersionRepository
and aEnvironmentRepository
? AGetVersionById()
method on theProductRepository
sounds wrong. But then wouldn’t supplying multiple repositories threaten the aggregate boundary? -
Should there be a ‘ProjectService’ which would handle and validate the aggregates using the three repositories? In order to safeguard against invalid data, client code would only be able to reference the ‘ProjectService’.
If your ProjectVersion
does not make sense without a Project
then there’s no need to have a repository of them. All versions for a project should be contained wtihin the aggregate. Furthermore your aggregate itself is where your validation should take place. This ensures that your aggregate is always consistent and valid.
public class Project {
private List<ProjectVersion> Versions = new List<ProjectVersion>();
public void AddVersion(Version version, string notes) {
if(Versions.Any(x => x.Version > version)) {
throw new Exception("Invalid version given. Version cannot be lower than the highest current version.");
}
Versions.Add(new ProjectVersion(this, version, notes));
}
}