I’m currently in the process of developing a domain model for a new application and have reached the stage where I need to define relationships with classes of different types that may perform the same role, and am confused as to the best way to define the relationship.
For example:
public class Car
{
public IDriver driver { get; set;}
public IPassenger passenger { get; set; }
}
public class Person : IDriver, IPassenger
{
}
public class Pet : IPassenger
{
}
In this case I want to be able to define that a diver of a car can be any class that implements IDriver and any passenger must implement IPassenger. In the case of a passenger it could be with a person or a pet. The interfaces in essence are defining the roles of each class.
What I want to understand is if in peoples opinions this is a good approach, or if the same thing could be accomplished using a different mechanism.
Hard to say with the information posted in the question...
Start with behavior, an acceptance test or a scenario of use. (I don't want to make up a scenario from thin air.)
Roles are relationships between collaborating objects. e.g. Object B may be a dependency, listener or a policy/strategy of Object A.
So now you need to design from Object A's perspective i.e. Outside-in. e.g. What does Car expect from its driver ? Those behaviors would translate to members of the Driver Role.
Related
What would be a rule of thumb when designing an aggregate in DDD?
According to Martin Fowler, aggregate is a cluster of domain objects that can be treated as a single unit. An aggregate will have one of its component objects be the aggregate root.
https://martinfowler.com/bliki/DDD_Aggregate.html
After designing aproximatelly 20 DDD projects I am still confused about the rule of thumb when choosing domain objects that would create an aggregate.
Martin Fowler uses order and line-items analogy and I don't think it is a good example, because order+line-items are really tightly bounded objects. Not much to think about in that example.
Lets try with car analogy where CarContent is a subdomain of a car dealer domain.
CarContent would consist of at least one or more aggregate/s.
For example we have this AggregateRoot (i am keeping it as simple as possible)
class CarStructureAggregate
{
public int Id {get; private set;}
public ModelType ModelType {get; private set;}
public int Year {get; private set;}
public List<EquipmentType> {get; private set;}
}
Alternative could be this (example B)
class CarStructureAggregate
{
public int Id {get; private set;}
public ModelType ModelType {get; private set;}
public int Year {get; private set;}
}
class CarEquipmentAggregate
{
public int Id {get; private set;}
public List<EquipmentType> {get; private set;}
}
Car can be created without equipment but it cannot be activated/published without the equipment (ie. this can be populated over two different transactions)
Equipment can be referenced trough CarStructureAggregate in example A or using CarEquipmentAggregate in example B.
EquipmentType could be an enum, or could be a complex class with many more classes, properties.
What is a rule of thumb when choosing between examples A and B?
Now imagine that car could have more information such as
photos
description
maybe more data about the engine
and CarStructureAggregate could be an extremely large class
So what is it that makes us split Aggregate into new Aggregates? Size? Atomicity of a transaction (although that would not be an issue since usually aggregates of a same sub domain are usually located on the same server)
Be careful about having too strong OO mindset. The blue book and Martin Fowler post are a little bit old and the vision it provides is too narrow.
An aggregate does not need to be a class. It does not need to be persisted. Theese are implementation details. Even, sometimes, the aggregate do things that does not implies a change, just implies a "OK this action may be done".
iTollu post give you a good start: What matters is transactional boundary. The job of an aggregate is just one. Ensure invariants and domain rules in an action that, in most of the cases (remember that not always), change data that must be persisted. The transactional boundary means that once the aggregate says that something may, and has, be done; nothing in the world should contradict it because, if contradiction occurs, your aggregate is badly designed and the rule that contradict the aggregate should be part of aggregate.
So, to design aggregates, I usualy start very simple and keep evolving. Think in a static function that recives all the VO's, entities and command data (almost DTO all of them except the unique ID of the entities) needed to check domain rules for the action and returns a domain event saying that something has be done. The data of the event must contain all data that your system needs to persist the changes, if needed, and to act in consequence when the event reach to other aggregates (in the same or different bounded context).
Now start to refactoring and OO designing. Supress primitive obsession antipattern. Add constraints to avoid incorrect states of entities and VO's. That piece of code to check or calculate someting related to a entity better goes into the entity. Put your events in a diet. Put static functions that need almost the same VO's and entities to check domain rules together creating a class as aggregate root. Use repositories to create the aggregates in an always valid state. And a long etc. You know; just good OOP design, going towards no DTO's, "tell, don't ask" premise, responsibility segregation and so on.
When you finish all that work you will find your aggregates, VO's and entities perfectly designed from a domain (bounded context related) and technical view.
Something to keep in mind when designing aggregates is that the same entity can be an aggregate in one use case and a normal entity in another. So you can have a CarStructureAggregate that owns a list of EquipmentTypes, but you can also have an EquipmentTypeAggregate that owns other things and has its own business rules.
Remember, though, that aggregates can update their own properties but not update the properties of owned objects. For example if your CarStructureAggregate owns the list of EquipmentType, you cannot change properties of one of the equipment types in the context of updating the CarStructureAggregate. You must query the EquipmentType in its aggregate role to make changes to it. CarStructureAggregate can only add EquipmentTypes to its internal list or remove them.
Another rule of thumb is only populate aggregates one level deep unless there is an overriding reason to go deeper. In your example you would instantiate the CarStructureAggregate and fill the list of EquipmentTypes, but you would not populate any lists that each EquipmentType might own.
I believe, what matters here is transactional boundary.
On one hand, you can't establish it more narrow than it is sufficient for preserving an aggregate's consistency.
On the other hand, you don't want to make it so large to lock your users from concurrent modifications.
In your example, if users should be able to modify CarStructure and CarEquipment concurrently - then I'd stick to implementation B. If not - it would be simpler to use A.
in a very simple sentence, I can say:
basically, a business use case that aims to change and consists of one or more relevant entities, value objects, and invariants based on the business in domain-driven design is aggregate. being a model command is important because if you only need to read, you don’t need an aggregate.
Well I am trying to apply domain driven design principles for my application, with a rich domain model that contains both data fields and business logic. I've read many DDD books, but it seems that their domain models(called entities) are very simple. It becomes a problem when I have a domain model with 10-15 data fields, such as the one below:
class Job extends DomainModel{
protected int id;
protected User employer;
protected string position;
protected string industry;
protected string requirements;
protected string responsibilities;
protected string benefits;
protected int vacancy;
protected Money salary;
protected DateTime datePosted;
protected DateTime dateStarting;
protected Interval duration;
protected String status;
protected float rating;
//business logic below
}
As you see, this domain model contains a lot of data fields, and all of them are important and cannot be stripped away. I know that a good rich domain model should not contain setter methods, but rather pass its data to constructor, and mutate states using business logic. However, for the above domain model, I cannot pass everything to the constructor, as it will lead to 15+ parameters in constructor method. A method should not contain more than 6-7 parameters, dont you think?
So what can I do to deal with a domain model with a lot of data fields? Should I try to decompose it? If so, how? Or maybe, I should just use a Builder class or reflection to initialize its properties upon instantiation so I wont pollute the constructor with so many arguments? Can anyone give some advice? Thanks.
What you've missed is the concept of a Value Object. Value objects are small, immutable objects with meaning in the respective domain.
I don't know the specifics of your domain, but looking at your Job entity, there could be a value object JobDescription that looks like this:
class JobDescription {
public JobDescription(string position, string requirements, string responsibilities) {
Position = position;
Requirements = requirements;
Responsibilities = responsibilities;
}
public string Position {get;}
public string Requirements {get;}
public string Responsibilities {get;}
}
This is C# code, but I think the idea should be clear regardless of the language you are using.
The basic idea is to group values in a way that makes sense in the respective domain. This means of course that value objects can also contain other value objects.
You should also ensure that value objects are compared by value instead of by reference, e.g. by implementing IEquatable<T> in C#.
If you refactor your code with this approach, you will get fewer fields on your entity, so using constructor injection (which is highly recommended) becomes feasible again.
Further notes regarding your example code that are not directly connected to the question:
The domain model is the whole thing, an entity is part of it. So your base class should be called Entity and not DomainModel.
You should make the fields of your class private and provide protected accessors where required to maintain encapsulation.
There's an awful lot going on in your Job domain model object - it seems to mix a huge number of concerns, and (to me at least) suggests a number of bounded contexts, some of which are easy to discern for the sake of making an example.
Remuneration (pay, benefits)
Organisational position (reporting line)
Person spec (skills)
Job specification (responsibilities)
etc.
When you consider the things that interact with your 'Job' model, are there any that need to inspect or mutate BOTH the Salary property and the Industry property, for example?
Without knowing the full nuances of the domain, the Salary you get for holding a position and the Industry you work in are not really connected, are they? Not a rhetorical point; these are the questions you NEED to ask the domain experts.
If they DON'T have any interaction then you have identified that these two things exist in two different BOUNDED CONTEXTS. The Salary side has no need of any interaction with the Industry side and vice versa, and even if they did, do they need to be held as state in the same process at the same time?
Think about the lifecycle of how a person becomes an employee; a person applies for a job. The job has a specification, salary range. The person attends an interview. The hirers offer the person the position. The person accepts. The person is now an employee, not a candidate any longer. The new employee is now accruing holiday and benefits and has a start date etc.
DDD teaches us that a single, unified view of the world rarely serves ANY of the concerns correctly. Please explore BOUNDED CONTEXTS - your software will be much more pliable and flexible as a result.
Could my domain model reference my repository interfaces? or better yet, containing my repositories definitions?
I ask because I was thinking about what I read on the limbo of internet that says that a model shouldn't know about its persistence, but I think if the repository exists due the model, I mean, to handle specific needs of its model, why not the model project define it?
Is it a problem/ bad design if I do the following?
public interface ISomethingThatNeedToBeAprovedRepository
{
void Save(SomethingThatNeedToBeAproved somethingThatNeedToBeAproved);
}
public class SomethingThatNeedToBeAproved
{
public int Status {get;set;}
public string Reason {get;set;}
public ISomethingThatNeedToBeAprovedRepository Repository{ get; set;}
public void Aprove(status, reason)
{
DoSomeAsserts();
Status = status;
Reason = reason;
Repository.save(this);
}
}
Yes, it can!
At given point you need to persist your aggregate so a repository is needed. I use to take IRepository inside my domain model, while infratructure details of Repository in another project.
No, it will be a bad design.
The domain model (this domain layer) should totally be independent of any other layer.
The repository interface and implementation should refer to the domain model to save and perform storage operations.
The answer is really it depends.
As #marianoc84 said, at some point, the application would really need to concern about persistence. The question here, is the particular domain model needs a concern about data persistence?
If it does, then it is make sense to put a repository inside the model.
On other side, having the repository inside 'may' makes unit test more challenging, and just be aware that generally speaking, the domain model could be distributed anywhere to pretty much up to application layer.
However, if the model does not really need to concern about persistence, then you don't really need a repository inside. The persistence could be done on other places such as having an 'ApprovalServices' which in this case, there could be several A, B, C, D and E that could be approved and have this to be persisted.
I think I've read 16,154 questions, blog posts, tweets, etc about DDD and best practices. Apologies for yet another question of that type. Let's say I have three tables in my database, User, Department, and UserDepartment. All very simple. I need to build a hierarchy showing what departments a user has access to. The issue is that I also need to show the parent departments of those that they have access to.
Is it best to have a GetDepartments() method on my user class? Right now I have a user service with GetDepartments(string userName), but I don't feel like that is the optimal solution. If user.GetDepartments() is preferred then how do I get access the repository to get the parent departments for those that the user has access to?
Don't think it matters, but I'm using the Entity Framework.
public class User
{
[Key]
public int UserId { get; private set; }
[Display(Name = "User Name")]
public string UserName { get; private set; }
[Display(Name = "Email")]
public string Email { get; private set; }
[Display(Name = "UserDepartments")]
public virtual ICollection<UserDepartment> UserDepartments { get; private set; }
public List<Department> GetDepartments()
{
// Should this be here? and if so, what's the preferred method for accessing the repository?
}
}
DDD is more about the behavior, which also mean it is TDA (tell, don't ask) oriented.
Normally you structure your aggregates in a way that you tell them what to do, not ask for information.
Even more, if some extra information is required by the aggregate in order to perform its behavior, it is typically not their job to figure out where to get this information from.
Now, when you are saying that your User aggregate has GetDepartments method, it raises a bell. Does the aggregate need this information in order to perform any kind of behavior? I don't think so, it is just you wanting some data to display.
So what I see here is that you are trying to structure your aggregates against your data tables, not against the behavior.
This is actually #2 error when applying DDD (#1 is not thinking about bounded contexts).
Again, aggregates represent business logic and behavior of your system. Which means that you don't have to read from aggregates. Your read side can be done much easier - just make a damn query to the DB.
But once you need to ask your system to do something - now you do it through aggregates: AppService would load one from the repository and call its behavior method.
That's why normally you don't have properties in your aggregates, just methods that represent behavior.
Also, you don't want your aggregates to be mapped to the data tables anyhow, it is not their job, but the job of repositories. Actually, you don't want your domain to have dependencies on anything, especially infrastructure.
So if you want to go for DDD direction then consider the following:
Structure your aggregates to encapsulate behaviors, not represent data tables
Don't make your domain dependant on infrastructure, etc.
Make repositories to be responsible to load/save aggregates. Aggregates themselves should know nothing about persistence, data structure, etc.
You don't have to read data through aggregates.
Think of #4 as your system has two sides: the "read" side when you just read the data and show them in the UI, and the "command" side when you perform actions.
The first one (read) is very simple: stupid queries to read the data in a way you want it. It doesn't affect anything because it is just reading, no side effects here.
The second one is when you make changes and that is going through your domain.
Again, remember the first rule of DDD: if you don't have business logic and behavior to model then don't do DDD.
I have implemented the command side of DDD using the domain model and repositories, but how do I implement the query side?
Do I create an entirely new domain model for the UI, and where is this kept in the project structure...in the domain layer, the UI layer, etc?
Also, what do I use as my querying mechanism, do I create new repositories specifically for the UI domain objects, something other than repositories, or something else?
From my understanding of CQRS you would create a set a DTOs that fulfil the requirements of the user interface screens or applications that may need to consume them.
Where this exists in the project is based on the requirements as it would depend if you were going to expose these DTOs via web services.
In which case I wouldn't put it in the Web Layer but rather in the Application layer or a dedicated Façade layer.
Then you would have a read only repository or data access layer which populates the DTOs directly. I think that the Query side of things should be optimized for read performance in which case direct queries/stored procedures on database views or tables and SqlDataReaders would do the best job here. But it would definitely be worth abstracting this access behind an interface so you can add a cached implementation later down the track.
If you're using an ORM and want to map from your Domain Entities to the DTOs then you could have a generic QueryRepository which has methods which take an ISpecification or similar construct for defining your queries then a DtoAssembler object for creating the Dtos from your Domain objects.
Then have an implementation has a first class object for each of the queries you are going to perform.
Here's a fairly contrived example but I hope it gives you an idea.
public interface ISpecification<T>
{
Expression<Func<T, bool>> Predicate { get; }
}
public class ActiveCustomersSpecification : ISpecification<Customer>
{
private Expression<Func<Customer, bool>> predicate;
public ActiveCustomersSpecification()
{
predicate = c => c.IsActive;
}
#region ISpecicfication<Customer> Members
public Expression<Func<Customer, bool>> Predicate
{
get { return predicate; }
}
#endregion
}
public interface IQueryRepository<T>
{
IQueryable<T> GetQuery(ISpecification<T> specification);
IEnumerable<T> FindAllBy(ISpecification<T> specification);
}
public class CustomerDtoAssembler
{
public CustomerDto AssembleFrom(Customer customer)
{
var customerDto = new CustomerDto
{
Id = customer.Id
};
return customerDto;
}
}
I think willbt has given you a really good starting point.
I would add that if you do opt to continue to use the ORM as the data-access strategy for queries you would be well-advised to consider defining a fetching strategy tailored to the data you expect you'll need to access (I'm thinking specifically about NHibernate here, by the way). What this means is you can decide whether to lazy-load or to eager-load the objects and collections associated with a particular Aggregate Root object.
The NCommon project by Ritesh Rao offers an excellent (work in progress) demonstration of how to define a different fetching strategy for different purposes.
Ritesh explains it really well in his blog.
Go ahead and have a look at the source:
here's the IFetchingStrategy interface
and this shows the use of fetching strategies in a unit test
In the test 'Repository_For_Uses_Registered_Fetching_Strategies' the call to
NHRepository<Order>().For<NHRepositoryTests>()
...causes the fetching strategies registered against the NHRepositoryTests class to be used, and therefore the OrderItems and Products will be eager loaded without messing about with NHibernate mapping configurations.