I have a problem with regards to entity design. As I've read, when you design a DDD entity, the constructor should contain the values needed for an entity to "exist". For example, in the domain I am working on, a Class entity cannot exist without a Section and a Level:
public class Class
{
public Class(short id, string section, Level level)
{
ID = id;
Section = section;
Level = level;
}
//
// Properties
//
public short ID { get; private set; }
public string Section { get; private set; }
public Level Level { get; private set; }
//
// Methods
//
public static IList<Class> GetClassesByTeacher(short teacherID)
{
List<Class> classes = new List<Class>();
classes.Add(new Class(1, "a", null));
classes.Add(new Class(2, "b", null));
classes.Add(new Class(3, "c", null));
return classes;
}
}
Here Level is also an entity. As I am not yet finished in the design, Level's contructor might also contain an entity SchoolYear. What bothers me is for me to call GetClassesByTeacher method, I need to instantiate a Class along with other entities (Level, and also SchoolYear, needed in Level's constructor).
Is this the correct? I think it's bothersome when I just want to call the method. Are there other ways? I considered making it static but others said testability would suffer. I'm not sure if CQRS is one of the solution for what I want to do as I haven't yet read too much about it, but if it is, are there any other techniques aside from CQRS I can employ, or is it when going DDD, this is how it really is? Or is my entity design incorrect?
You should reconsider you domain model, as you actually say it seems there something wrong.
I may refer to Single Responsibility Principle (SRP) in which any class should have one one reason to change. In your example, what happens if we added a new field to 'Class', we will modify 'Class' it self and is right, but what happens if we decide that the listing should be on reversal order, or if you need a new type of list taking into account only interim teachers... you should change 'Class' but 'Class' has nothing to do with listings.
To answer you question, you might take a look at Repository pattern. Repositories are where you could ask for these type of listings.
I might split Class into two:
In summary:
public class Class
{
public Class(short id, string section, Level level)
{
ID = id;
Section = section;
Level = level;
}
//
// Properties
//
public short ID { get; private set; }
public string Section { get; private set; }
public Level Level { get; private set; }
}
public class ClassRepository
{
private IList<Class> contents;
//
// Methods
//
public IList<Class> GetClassesByTeacher(short teacherID)
{
List<Class> classes = new List<Class>();
for (Class elem: contents) {
if (elem.getTeacher().equals(teacherID) {
classes.Add(elem);
}
}
return classes;
}
}
repository = new ClassRepository;
level1 = new Level();
repository.Save(new Class(1, "a", level1));
repository.Save(new Class(2, "b", level1));
repository.Save(new Class(3, "c", level1));
result = repository.GetClassesByTeacher(1);
There are other details like using a ClassRepositoryInterface and implement with an InMemoryClassRepository, you will miss also Teacher information in class, as long as one one teacher drives the class, if not you might change how to filter by teacher, etc, etc.
I'm not a Java developer and the code will not compile but I expect you get the idea.
The GetClassesByTeacher
method does indeed belong in some kind of repository or service class. Your Class
entity is meant to represent an instance of that thing in the real world. An entity is not meant to provide instances (say, from some underlying persistence) - they are only meant to represent them. A ClassRepository
would be a way to provide instances of the Class
entity into your domain.
You also mentioned that Class
cannot exist without a Level
. You are speaking about aggregates here. There is a lot of DDD material online with regards to designing aggregates. Here are a couple:
When an entity needs another entity to exist, should it always be an aggregate?
No, just because entity A depends on entity B's existence, it doesn't mean that entity A needs to belong to entity B's aggregate.
As now I have a model in which many entities (like Class, Level, Subject, Adviser, Teacher, etc.) exists only in a certain SchoolYear (an entity). Is it OK for an aggregate to get that large?
An aggregate this large could result in performance and consistency issues.
Vaughn Vernon covers exactly these problems in his three-part Effective Aggregate Design series. It's a bit daunting if you aren't familiar with DDD lingo, but I highly recommend this read!
Also, by what you said, the Entity should not use the repository. If some business logic in the Entity needs database access for it to be processed, should it directly use DAL?
Entities should not know anything about repositories or services (or anything else, for that matter). They should not have any dependency on any other 'layer' in the system. Everything can know about your entities, but your entities shouldn't know about anything else. Provide me with an example of why you would want an entity to call on a repository and maybe I can provide a better answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With