How to model inheritance on DDD? - domain-driven-design

I am currently trying out DDD and reading Evans book. I have arrived at a model that has an aggregate whose root is Student. Now I need to have (or be able to distinguish) a RegisteredStudent and an EnrolledStudent (inherits RegisteredStudent). I don't know how to handle inheritance in DDD.
Should the 2 inherited classes be inside the aggregate? If so, are they also considered aggregate roots since their identity is the same as the root (there are only added properties to them)? If not, how do I give access to them from other entities?
Or should I not be using inheritance? Why?
And also, what if you have an entity in an aggregate that isn't a root, but you need it to inherit an entity outside? How should you go about it?

What you need to ask yourself here is whether a RegisteredStudent and an EnrolledStudent are different concepts. Are they not both students, but just in a different state?
In general, you should favor composition over inheritance.
Here's an example of what I would do. (Note that it's just my example, I don't know the domain, so it's not a definitive solution).
You could have a Student class, which is your aggregate root and then a few different state classes: Registered and Enrolled. That way you don't need to expose these state classes on the student but you could just expose methods on the Student. A small example in C#:
class Student
{
State _currentState;
void Enroll()
{
if(!_currentState is Registered)
throw new InvalidOperationException("Cannot enroll student who is not registered");
this._currentState = new Enrolled();
}
void Register(string name)
{
this._currentState = new Registered(name);
}
}
class StudentState{}
class Enrolled : StudentState
{}
class Registered : StudentState
{
public Registered(string name)
{
Name = name;
}
public string Name {get; private set;}
}
This is a simple application of the State design pattern, you could externalize more parts of it and build a complete state-machine, but I'll leave that up to you. (Also it's typed directly in to the SO-editor, so there could be syntax errors)
EDIT after comments
Whether you need to expose a State-property or not depends on the context. In general I would recommend not to do that, because you're exposing the internals of the Student. It would be better to expose a method called CanEnroll for example. That way you can change the internal implementation of your state pattern without affecting any clients.
As for question 3, it's hard to say without a use case. However, here are some guidelines:
Favor composition over inheritance (again, I know).
You can have a reference from inside an aggregate to the outer world, you shouldn't have a reference the other way around though.

Related

Aggregate or entity without business attributes

Regarding below excerpt, concerning cqrs and ddd, from Patterns, Principles, and Practices of Domain-Driven Design by Nick Tune, Scott Millett
Does it mean that domain model on command side can omit most of business attributes ?
How would it look like for eg Customer Entity?
Could Customer entity omit FirstName, Surname etc?
If so, where would these business attributes be? Only in read model in CustomerEntity?
Or maybe apart from CustomerEntity containing all business attributes there would also be CustomerAggregate wrapping CustomerEntity with 1:1 relation, and command object would operate on CustomerAggregate? (seems strange to me).
What does it mean "Customer entity desn't make sense"?
The text you pointed means that you do not have to model a reusable Entity for your whole system or even for your whole bounded context (Do not model reusable real life things). Doing this is a bad design.
You have to model an Aggregate that performs an action. You feed the Aggregate with only, and just only, the data needed to perform that action and the aggregate response, the changes the domain suffered, is what you have to persist.
Why Entities and V.O.'s then?
To model consistency, encapsulation and decoupling is the basic part but these are implementation details. For DDD what matters is that are different roles (or concepts).
When feeding the aggregate (constructor, function call parameters, etc) the aggregate has to know if it is working with entities and/or with V.O. to build its response.
If the domain action means a change in an attribute of a entity (something with unique identification in your whole system) the response of the aggregate (once all rules and invariants has been checked) should include the new attribute value and the identification of that entity that allows persist the changes.
So, by default, every aggregate has its own entity with the unique identification and the attributes needed for the aggregate action.
One aggregate could have a Customer entity with ID and its Name.
Another aggregate could have a Customer entity with ID and its Karma points.
So every aggregate has its own inner Customer entity to work with. When you feed an aggregate you pass Customer data (i.e. ID and name or ID and Karma points) and the aggregate treats that info as a entity (It is a matter of implementation details if there is a struct, class, etc internally to the aggregate to represent the entity).
One important thing: If you just need to deal with entities ID's then treat it as a V.O. (CustomerIdentityVO) because the ID is immutable and, probably, in that action you just need to write this CustomerIdentityVO in some field in persistence, not change any Customer attribute.
This is the standard vision. Once you start to identify common structures relevant to several aggregates or one aggregate that can perform several actions with the same data fed you start to refactoring, reusing, etc. It just a matter of good OOP design and SOLID principles.
Please, note that I am trying to be higly above of implementation details. I know that you almost always will have unwanted artifacts that depends of programing paradigm type, chosen programing language, etc. but this approach helps a lot avoiding the worse artifact you could have.
Recommended readings:
http://blog.sapiensworks.com/post/2016/07/29/DDD-Entities-Value-Objects-Explained
http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-1
http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-2
https://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-3
and
https://blog.sapiensworks.com/post/2016/08/19/DDD-Application-Services-Explained
for a complete puzzle vision.
If you are using Event Sourcing then it's true that you can model aggregates without adding attributes that they don't need for implementing the business logic.
Here's an example:
class Customer {
public Guid ID { get; private set; }
public Customer(Guid id, firstName, lastName, ...) {
ID = id;
this.AddEvent(new CustomerCreatedEvent(id, firstName, ....);
}
public void ChangeName(firstName, lastName) {
this.AddEvent(new CustomerRenamedEvent(this.ID, firstName, lastName),
}
}
Custom only has ID attribute because it needs it to add it to every event that it generates. FirstName and LastName are omitted as they are not needed even when ChangeName method is called. It only records an event that this happened. If your logic requires the FirstName then you can add it. You can omit any properties that you don't need.
Your Repository in this case will save only the events and won't care about the values of the attributes of the Customer.
On the Read side you will probably need these properties as you will display them to your users.
If your aggregates are not event sourced, then you probably will need more attributes on your aggregate to implement it's logic and they will be saved to the database.
Here's an example:
class Customer {
public Guid ID { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public void ChangeName(firstName, lastName) {
FirstName = firstName;
LastName = lastName;
}
}
In this case your Repository will need these properties as it will generate a query to update the database with the new values.
Not sure what "Customer entity doesn't make sense" means.

How to apply business rule in DTOs DDD

I need to apply business rules in a DTO, but this DTO has properties of N entities.
I wanted to know the correct way to validate this DTO.
Very common approach would be to wrap DTO into an Entity and implement business rules inside the Entity.
var state = new DTO();
var entity = new Entity(state);
//this will change the state in a consistent way according to business rules
entity.DoSomething1();
entity.DoSomething2();
//this is C#, so I can't get immutable version easily, but if your language allows that - you should return immutable state from entity. Or you can return a clone of the state
state = entity.State;
//store or do whatever you like with the state as long as you keep it immutable.
_repository.Save(state);
As DTO is just a data-transfer-object, it should never apply any business logics inside.
DTO has properties of N entities
The preferable way is to create an aggregate class for your case and apply business logics inside.
public class Entitity1
{
}
public class Entity2
{
}
public class EntityAggregate
{
public EntityAggregate(Entity1 entity1, Entity2 entity2) // constructor
{
this.entity1 = entity1;
this.entity2 = entity2;
}
public ExecuteYourBusinessCase()
{
... access entity1 and entity2 here and evaluate business logics
}
}
Also it's worth metioning that one of DDD ideas is to prevent creating of invalid objects. So your should guarantee that if domain entity has been created it is valid and DTO can always be created. Business logics remains a black box for the layer responsible for DTO creation
As already stated in other answers:
You shouldn't have business rules in your DTOs.
Although, when the topic is DDD, another very common approach to ensure that you'll always create valid domain objects is to use the Builder Pattern.
This pattern allows you to vary a product's representation. For example, a software may have a domain denominated Product, but - in real world representation - it may be a Service or a Material (I can sell a cellphone or a cellphone insurance), so two builders must be created (MaterialBuilder and ServiceBuilder, for ie) that builds the same domain object, the Product.
This pattern generally is used with a method chaining and leads to a fluent interface.

How to create a multilingual domain model

I am using domain-driven design and I have a pretty clear picture of my domain model. It contains over 120 classes and it is quite stable. We will implement it in .NET 4 and C#. The thing is, we need the model to be multilingual; some of the attributes need to be stored in multiple languages. For example, the Person class has a Position property of type string which should store a value in English (e.g. "Librarian") and Spanish (e.g. "Bibliotecario"). The getter for this property should return the English or Spanish version depending on some language parameter.
And here begin my questions. I am not sure how to parameterize this. I have exlpored two major ways to do it:
Use property collections. Position would not be a string but rather a Dictionary<Language, string>, which would let clients retrieve the person's position by language.
Keep simple, scalar properties, but make them return (or set) the value for one language or another depending on a globally known "current language" setting. The client code would set the working language, and then all objects would set and get values in that language.
Option 1 avoids global state, but it messes up the interface of almost every class in my model. On the other hand, option 2 is less expressive, since you can't tell what language you're going to get without looking at the global setting. Also, it introduces a dependency into every class on the global setting.
Please note that I am not interested in database or ORM implementations; I am working at the domain model level only.
I have two specific questions then:
Which is the best option (1 or 2) to achieve my goal of a multilingual domain model?
Are there other options that I haven't considered, and which are they?
Thank you.
Edit. Some have suggested that this is a user interface related issue, and thus can be tackled through globalisation/localisation support in .NET. I disagree. UI localisation works only if you know the localised literals that must be shown to the user at compile time, but this is not our case. My question involves multilingual data that is unknown at compile time, because it will be provided as user data at run-time. This is not a UI-related issue.
Edit 2. Please bear in mind that the Person.Position is just a toy example to illustrate the question. It's not part of the real model. Don't try to criticise it or improve upon it; there is no point in doing that. Our business requirements involve a lot of attributes that cannot be encoded as enum types or similar, and must stay as free text. Hence the difficulty.
Given the following:
Some use case involve setting the values for an object in all the
supported languages; others involve looking at the values in one given
language.
I would suggest going for both options. That means that the Person and all classes that hold multilingual content should keep that content in their state and:
The Position property should set/get the person's position in the
current user's language.
There should be a corresponding property or method for all
language setting/getting.
There should be a method for setting (or even switching if needed)
the user language. I would create an abstract class (e.g.
BaseMultilingualEntity) with an abstract SetLanguage(Language
lang) method and a CurrentLanguage getter. You need to keep
track of all the objects that derive from BaseMultilingualEntity
in some sort of registry that would expose language setting.
EDIT WITH SOME CODE
public enum Language {
English,
German
}
// all multilingual entity classes should derive from this one; this is practically a partly implemented observer
public abstract class BaseMultilingualEntity
{
public Language CurrentLanguage { get; private set; }
public void SetCurrentLanguage(Language lang)
{
this.CurrentLanguage = lang;
}
}
// this is practically an observable and perhaps SRP is not fully respected here but you got the point i think
public class UserSettings
{
private List<BaseMultilingualEntity> _multilingualEntities;
public void SetCurrentLanguage(Language lang)
{
if (_multilingualEntities == null)
return;
foreach (BaseMultilingualEntity multiLingualEntity in _multilingualEntities)
multiLingualEntity.SetCurrentLanguage(lang);
}
public void TrackMultilingualEntity(BaseMultilingualEntity multiLingualEntity)
{
if (_multilingualEntities == null)
_multilingualEntities = new List<BaseMultilingualEntity>();
_multilingualEntities.Add(multiLingualEntity);
}
}
// the Person entity class is a multilingual entity; the intention is to keep the XXXX with the XXXXInAllLanguages property in sync
public class Person : BaseMultilingualEntity
{
public string Position
{
set
{
_PositionInAllLanguages[this.CurrentLanguage] = value;
}
get
{
return _PositionInAllLanguages[this.CurrentLanguage];
}
}
private Dictionary<Language, string> _PositionInAllLanguages;
public Dictionary<Language, string> PositionInAllLanguages {
get
{
return _PositionInAllLanguages;
}
set
{
_PositionInAllLanguages = value;
}
}
}
public class Program
{
public static void Main()
{
UserSettings us = new UserSettings();
us.SetCurrentLanguage(Language.English);
Person person1 = new Person();
us.TrackMultilingualEntity(person1);
// use case: set position in all languages
person1.PositionInAllLanguages = new Dictionary<Language, string> {
{ Language.English, "Software Developer" },
{ Language.German, "Software Entwikcler" }
};
// use case: display a person's position in the user language
Console.WriteLine(person1.Position);
// use case: switch language
us.SetCurrentLanguage(Language.German);
Console.WriteLine(person1.Position);
// use case: set position in the current user's language
person1.Position = "Software Entwickler";
// use case: display a person's position in all languages
foreach (Language lang in person1.PositionInAllLanguages.Keys)
Console.WriteLine(person1.PositionInAllLanguages[lang]);
Console.ReadKey();
}
}
A domain model is an abstraction - it models a specific part of the world, it captures the concepts of a domain.
The model exists so developers can communicate in code the way domain experts communicate - using the same names for the same concepts.
Now, a Spanish expert and an English expert may use different words for the same concept, but the concept itself would be the same (one hopes, though language can be ambiguous and people do not always understand the same concept in the same way, but I digress).
The code should pick one human language for these concepts and stick to it. There is absolutely no reason for the model to consist of different languages in order to represent a single concept.
Now, you may need to show users of the application data and meta data in their language, but the concept does not change.
In this regard, you second option is the thing you should be doing - with .NET, this is normally done by looking at the CurrentThread.CurrentCulture and/or CurrentThread.CurrentUICulture and by using satellite assemblies that will contain localized resources.
My question involves multilingual data
[...]
Please note that I am not interested in database or ORM
implementations;
I can see a bit of contradiction in these 2 statements. Whatever the final solution, you'll have multilingual-specific structures in your database anyway as well as a mechanism that queries them to do the translation, right ?
The thing is, unless your domain really is about translation, I would try to keep it away from multilingual concerns as much as possible, for the same reason that you would try to make your domain persistence ignorant or UI ignorant.
Thus I would at the very least place the multilingual resolution logic in the Infrastructure layer. You could then for instance use aspects to only attach multilingual behavior to some properties, if you really need a trace of multi-language in your entities and don't want your persistence layer to handle all that transparently :
public class Person
{
[Multilingual]
public string Position { get; set; }
}
It contains over 120 classes and it is quite stable.
Not directly related to question, but you might want to consider the existence of multiple bounded contexts in your domain.
I agree with Oded that it seems in your scenario, language is a UI concern. Sure, the domain may be declared via combination of C# and English, what it represents is abstract. The UI would handle language with CultureInfo.CurrentCulture - effectively option #2.
A Person entity having a Position property doesn't govern the natural language used to represent the position. You may have a use case where you'd want to display a position in one language while it is originally stored in another. In this case, you can have a translator as part of the UI. This is similar to representing money as a pair of an amount and currency and then converting between currencies.
EDIT
The getter for this property should return the English or Spanish
version depending on some language parameter.
What determines this language parameter? What is responsible for ensuring that, say Position, is stored in multiple languages? Or is translation to be performed on the fly? Who is the client of the property? If the client determines the language parameter, why can't the client perform the translation without involving the domain? Are there any behaviors associated with multiple languages or is this only a concern for reading purposes? The point of DDD is to distill your core behavioral domain and shifts aspects related to querying data into other areas of responsibility. For example, you can use the read-model pattern to access the Position property of an aggregate with a specific language.
Make the User explicit!
I already encountered domains where the user's culture is a first class citizen in the domain but, in such situations, I model a proper value object (in your example I would use a Position class properly implementing IEquatable<Position>) and the User that is able to express such values.
Sticking to your example, something like:
public sealed class VATIN : IEquatable<VATIN> { // implementation here... }
public sealed class Position : IEquatable<Position> { // implementation here... }
public sealed class Person
{
// a few constructors here...
// a Person's identifier from the domain expert, since it's an entity
public VATIN Identifier { get { // implementation here } }
// some more properties if you need them...
public Position CurrentPosition { get { // implementation here } }
// some commands
public void PromoteTo(Position newPosition) { // implementation here }
}
public sealed class User
{
// <summary>Express the position provided according to the culture of the user.</summary>
// <param name="position">Position to express.</param>
// <exception cref="ArgumentNullException"><paramref name="position"/> is null.</exception>
// <exception cref="UnknownPositionException"><paramref name="position"/> is unknown.</exception>
public string Express(Position position) { // implementation here }
// <summary>Returns the <see cref="Position"/> expressed from the user.</summary>
// <param name="positionName">Name of the position in the culture of the user.</param>
// <exception cref="ArgumentNullException"><paramref name="positionName"/> is null or empty.</exception>
// <exception cref="UnknownPositionNameException"><paramref name="positionName"/> is unknown.</exception>
public Position ParsePosition(string positionName) { // implementation here }
}
And don't forget documentation and properly designed exceptions!
WARNING
There are at least two huge design smells in the sample model that you provided:
a public setter (the Position property)
a System.String holding business value
A public setter means either that your entity exposes its own state to clients regardless of its own invariants, or that such a property has no business value for the entity and thus should not be part of the entity at all. Indeed, mutable entities should always separate commands (that can change the state) and queries (that cannot).
A System.String with business semantic always smells of a domain concept left implicit, typically a value-object with equality operations (that implements IEquatable, I mean).
Be aware that a reusable domain model is quite challenging to obtain, since it requires more than two domain experts and a strong experience in ddd modeling. The worst "domain model" that I faced in my carreer was designed by a senior programmer with huge OOP skills but no previous modeling experience: it was a mix of GoF patterns and data structures that, in the hope to be really flexible, proved to be useless. After 200k €, spent in that effort, we had to throw it away and restart from scratch.
May be that you just need a good data model directly mapped to a set of simple data structures in C#: you'll never have any ROI from an upfront investment in a domain model, if you don't really need it!
It might be worth mentioning Apache's MultiViews feature and the way it delivers different content based on the browser's Accept-Language header.
So if a user requests 'content.xml', for example, Apache will deliver content.en.xml or content.sp.xl or content.fr.xml or whatever is available based on some prioritization rules.
Given the requirements I would probably try to model the position as an entity/value on its own. This object would not be a dictionary of translations but rather just be usable as a key into a domainDictionary.
// IDomainDictionary would be resolved based on CurrentThread.CurrentUICulture
var domainDict = container.Resolve<IDomainDictionary<Position>>();
var position = person.Position;
Debug.Writeline(domainDict.NameFor(position, pluralForm: 1));
Now assuming you need to dynamically create new positions when a suitable synonym doesn't exist you could probably keep the data somewhat tidy by using the IDomainDictionary as an source for auto complete suggestions in the UI.

Domain Driven Design - Entities VO's and Class Hierarchy

The shorter version of the Question: "Is it ok to have a superclass, with 2 subclasses, one is an entity the other is a Value Object?"
To longer version:
T have a Team superclass. The Team has the Master, Helpers and a Code.
Then i have the DefaultTeam, subclass of Team, which is an entity with an unique **Code**** has its domain identity.
Then i have the **ExecutionTeam, its a subclass of Team and has an extra attribute OriginalTeam:
public abstract class Team{
public string Code{ get; protected set; }
public Worker Master{ get; protected set; }
public IList<Worker > Helpers { get; protected set; }
...
}
public class DefaultTeam: Team
{
}
public class ExecutionTeam : Team
{
public virtual string Code { get { return OriginalTeam.Code; } }
public virtual DefaultTeam OriginalTeam { get; private set; }
...
}
The ExecutionTeam, is the team that executes a Task.
When a Task needs to be executed, we choose a DefaultTeam to execute it.
But we can change the Helpers from the DefaultTeam (the master never changes).
That team that executes the task, is a variation of the DefaultTeam (OriginalTeam), but with the Helpers that were chosen just for that Task.
The ExecutionTeam will have the same code has the OriginalTeam. So the ExecutionTeam has no unique identity.
If there are 10 executions of tasks by the same DefaultTeam, there will be 10 ExecutionTeams with the same code (with the same OriginalTeam). So ExecutionTeam is cannot be an Entity.
But having an Entity and a Value Object sharing the same superclass (both being Teams), is a bit strange. Maybe this domain model has something wrong.
Need opinions.
Thanks
What is it that makes the DefaultTeam a Value Object rather than an Entity? Isn't a DefaultTeam also an entity?
That being said, here are some comments:
Why do you need a special class for DefaultTeam? Can't a DefaultTeam simply be an ExecutionTeam, with certain specified values?
A DefaultTeam should probably be an instance of a Team that is associated with an application domain. For example, you might have a particular team that is generally used to solve problems with Project XYZ.
Instead of listing "DefaultTeam" as a property of the ExecutionTeam, you should probably have a "PreviousTeam" as a property of both the Team and ExecutionTeam classes.
This will be more generalizable, in case the team gets changed yet again.
Since Task is an important part of the domain and is assigned to a Team, it should probably be a property of Team.
"Helpers" doesn't seem an appropriate name for the team members. Why not just name them "Members" or "TeamMembers"?
"Master" is probably un-PC unless you are working in Dilbert land or dealing with a database :) You might want to change this to "Supervisor" or "Manager".
"Code" is probably a bad name in the context of your application, as it may easily be confused with programming code. You might want to use "Id" or "TeamId" instead.
Sounds like ExecutionTeam might be better modeled as an interface ICanExecuteTasks. Would that work for you? It would eliminate the issue you are struggling with..
As to your short question, if the ExecutionTeam was indeed a derived class of Team, (inheriting from team and representing an "IsA" relatoonship, then the answer is No, they cannot be of different types because of course, every ExecutionTeam isA Team, thgere is only one thing, which is both a Team and an ExecutionTeam at the same time... It cannot be both an entity Type and a value type at the same time.
But the way you have designed the classes, as you have structured things, ExcecutionTeam is not a derived class, it is a property of the DefaultTeam. This implies that they have a "HasA" relationship. THis implies that they are different, co-existing objects, one of which can be an entity and one of which can be a value type. But my gut tells me this is not an accurate mirror of your real domain model...

Can Aggregate root entity calls Repository

Is it possible for an Aggregate root entity to have a method in which it will call a Repository?
I know it should not but want to get confirmed as Eric's book is also not saying anything clearly :(
one more thing where can I get a unit testing example for domain-driven design?
This is a bit of a religious question.
Some see no problem with this, while others might believe it is heresy to do so.
While I've normally always kept my Repository away from my Domain Model (and had an upstream service object deal with the Repository), I have had a project that "required" having the Repository accessable from the Domain Model.
This was due to the Domain object needing to retrieve specific data based on business logic => using specification objects/Linq to nHibernate (the responsibility and knowledge of how to filter data belonged to that Domain Object) and/or performance reasons.
A caveat around doing this is how to get the reference to the Repository to the Domain object - in that case I utilized Constructor injection with an IOC tool.
Whether you should do this or not really depends on your solution/use case/technologies being used etc...
Can? -Yes.
Should? -No.
All answers are however context-sensitive, and you don't provide yours.
A generic advise would be to look for a "service" or "specification" type.
Behavior IS-WHAT-IT-IS. Eric calls a Repository like utility from a Brokerage Account entity called, "QueryService". He mentions that it's not a good design for a real project. So what do you do?
public class Clerk
{
public Clerk()
{
}
//Store Report in Database
public void File(Report);
{
ReportRepository.Add(Report);
}
}
You could do that, but it's probably best to tell the Clerk which Repository to use.
public class Clerk
{
private IReportRepository _reportRepository;
public Clerk(IReportRepository ReportRepository)
{
this._reportRepository = ReportRepository
}
//Store Report in Database
public void File(Report);
{
this._reportRepository.Add(Report);
}
}

Resources