Does it make sense to make subsets of an Entity if you consider their usage in the application differently? IE. I take my entity and define a new entity with only some of the attributes of the first. Now I have 2 Entities that overlap but are used differently but ultimately persist in same datatable. These Entities will be accessed through different repositories...
I am only starting to learn about DDD myself, so if I am wrong please comment and let me know. Here are my thoughts though:
If the entity is going to be accessed through a different repository, I think it deserves its own class. Additionally, the bits that overlap now may not overlap in the future, and if you use a shared base class, you will probably be more likely to try adapting things at that point, which will dirty up your domain.
If the two classes are part of separate sub-domains, they probably should be separate. My thoughts are based around parts of an example I remember hearing in Rob Connery's interview on Hanselminutes. A product has several properties that are important to consumers (pricing, description, etc), and several properties that are important to warehouse personnel (location in the warehouse, weight, dimensions, etc). The implication to me in that episode was that the two products should be defined separately in the domain, instead of being defined once and shared.
If by "usage in the application" you mean you'll display different parts in different views, then I'd suggest you use a presentation pattern like Fowler describes in his Presentation Model (or if your developing a WPF app you can use the more WPF-specialized version called Model-View-ViewModel (MVVM)).
But if you by "usage" mean that you'll use different attributes of the entity in different sub-domains or part of your domain, then I agree with Chris; You'd probably be better off breaking them into different entities. The reason being that in your domain model you should reflect how the entity is used in that specific (sub)domain. And if you're using different parts of the entity under different circumstances, they probably have different meanings in these settings which again should be reflected in the naming of the entities. And if it were me, I'd probably make one repository for each of the entities. Having a 1:1 mapping between entities and repositories seems to make sense in most cases as far as I've experienced. But then again; just like Chris, Rob Conery and 90% of the developers trying to do DDD; I'm fairly new to the DDD-game and so my experiences might be overruled by someone more experienced :)
Related
I have a few microservices that reuse similar models i.e.
RepairService
InventoryService
AuctionService
An Item (Cars, Bikes, etc) can be found in each of these services and each time I add new properties or a new item type, I then end up duplicating these models in 3 places
I thought about putting these models in a fourth library "ItemService" but since these models have different methods in each service, then InventoryService would be able to repair items, etc
But what if my "ItemService" only contained interfaces for these models (Just the state not the methods) which the other services then implement, so you could find ICar in the ItemService, package it into RepairService which then implements it and adds methods to repair a car.
I can't seem to find anywhere on the internet about having domain entities implement interfaces, so I'm not 100 percent sure
Cheers
In a previous project we ended up creating a separate library with all the common stuff used by different microservices. I think it is similar situation with what you describe here. The difference seems to be we used only plain beans for the models (not recommended when you do DDD, I know).
Taking this difference into account, what about using a Decorator?
This means you define the common properties/behavior in a common library, and them decorate them with the needed responsibilities in each service you use?
And I would not worry about having domain entities implement interfaces, if you think it is useful, just do it. I cannot think of any disadvantage.
I have a bit of a write-up around the same concept.
The point is that the various bounded contexts do something different on the same thing so even though there would be a unique identifier for a specific instance of, say, Car you would have different implementations of that class in the various bounded contexts. In many, if not most, cases you would probably have a class with a more relevant name in each particular BC.
Only a single one of the bounded contexts would, however, be the system of record for the entry.
I have an assignment for school, where I have to create a domain model of a specific e-commerce site that delivers complete grocery bags to people's homes. (http://www.linasmatkasse.se/)
It's quite basic. Chose a bag, create account (with info), pay.
My question is, what exactly should be included in the model (in general)? In other words, where does the lines of the domain end? For instance, should delivery and suppliers be included? They aren't technically part of the website itself, by still play a role.
Thanks in advance!
What is domain
Let us take some theme/subject. It could be grocery delivery, satellites, swallows observations, anything. Let us name this theme "AAA"
domain model for AAA is a "profi IT" word for model for AAA. That's all.
All elements specific to AAA that you'll set in your model, belong to domain. I don't know, why the old good word theme is not used. It is a pity. But the term is already accepted.
So, delivery and suppliers are in your domain. And also much more specific words belonging to grocery. And to bags. And to people's homes - addresses, drive ways in and out - everything that is relevant to your theme.
The domain sets your vocabulary. And that one is really important - you should use the vocabulary used by your clients and not to invent new words, such as "domain" for "theme" :-)
And first you should define your Use case diagram, later- State machine diagram, Deployment diagram, Component diagram, Communication diagram, Sequence/Activity/Time/Interaction Overview diagrams, and at last - class, object and composite structure diagrams. You needn't make all of them, but SOME are necessary.
Every entity that models an entity in reality is a part of the domain. In your example, delivery and suppliers should be a part of the domain model. Basically any entity that has a defined behavior should be modeled as a part of the domain. Many times it seems like the domain model components aren't a part of the website and this is actually normal, the front-end is a way of viewing the domain model, it doesn't need to expose everything within the domain.
I usually find it easy to think about what entities are logical components of the business model in the real world and I only remove one if I find that it is redundant, unnecessary or can be encapsulated within another entity.
About the entities that are not the part of IT system
Do not ignore the pure human operations. On the contrary. Put them here, only their use cases will connect not actor-(sub)system, but actor-actor. And seeing them is very good for better planning the system as a whole. When ignoring them it is impossible to create a system good for user. The IT system is an integral component of the larger system, and we are creating the larger one really, with planning the support, processes, exchange of info, divisions and dependencies.
Too often had I problems with programmers who are blind to anything out of IT system border. And often it is impossible to make them think out of these borders. As a result, the system is blind to the real needs of the user, too. So we have that sad picture of user-hating software.
It is very useful to start to study the problem/domain/theme from entities that are out of the IT system, and to create firstly the diagram, that considers IT system as merely one of many blocks.
I've got a question on my mind that has been stirring for months as I've read about DDD, patterns and many other topics of application architecture. I'm going to frame this in terms of an MVC web application but the question is, I'm sure, much broader. and it is this: Does the adherence to domain entities create rigidity and inefficiency in an application?
The DDD approach makes complete sense for managing the business logic of an application and as a way of working with stakeholders. But to me it falls apart in the context of a multi-tiered application. Namely there are very few scenarios when a view needs all the data of an entity or when even two repositories have it all. In and of itself that's not bad but it means I make multiple queries returning a bunch of properties I don't need to get a few that I do. And once that is done the extraneous information either gets passed to the view or there is the overhead of discarding, merging and mapping data to a DTO or view model. I have need to generate a lot of reports and the problem seems magnified there. Each requires a unique slicing or aggregating of information that SQL can do well but repositories can't as they're expected to return full entities. It seems wasteful, honestly, and I don't want to pound a database and generate unneeded network traffic on a matter of principle. From questions like this Should the repository layer return data-transfer-objects (DTO)? it seems I'm not the only one to struggle with this question. So what's the answer to the limitations it seems to impose?
Thanks from a new and confounded DDD-er.
What's the real problem here? Processing business rules and querying for data are 2 very different concerns. That realization leads us to CQRS - Command-Query Responsibility Segregation. What's that? You just don't use the same model for both tasks: Domain Model is about behavior, performing business processes, handling command. And there is a separate Reporting Model used for display. In general, it can contain a table per view. These tables contains only relevant information so you can get rid of DTO, AutoMapper, etc.
How these two models synchronize? It can be done in many ways:
Reporting model can be built just on top of database views
Database replication
Domain model can issue events containing information about each change and they can be handled by denormalizers updating proper tables in Reporting Model
as I've read about DDD, patterns and many other topics of application architecture
Domain driven design is not about patterns and architecture but about designing your code according to business domain. Instead of thinking about repositories and layers, think about problem you are trying to solve. Simplest way to "start rehabilitation" would be to rename ProductRepository to just Products.
Does the adherence to domain entities create rigidity and inefficiency in an application?
Inefficiency comes from bad modeling. [citation needed]
The DDD approach makes complete sense for managing the business logic of an application and as a way of working with stakeholders. But to me it falls apart in the context of a multi-tiered application.
Tiers aren't layers
Namely there are very few scenarios when a view needs all the data of an entity or when even two repositories have it all. In and of itself that's not bad but it means I make multiple queries returning a bunch of properties I don't need to get a few that I do.
Query that data as you wish. Do not try to box your problems into some "ready-made solutions". Instead - learn from them and apply only what's necessary to solve them.
Each requires a unique slicing or aggregating of information that SQL can do well but repositories can't as they're expected to return full entities.
http://ayende.com/blog/3955/repository-is-the-new-singleton
So what's the answer to the limitations it seems to impose?
"seems"
Btw, internet is full of things like this (I mean that sample app).
To understand what DDD is, read blue book slowly and carefully. Twice.
If you think that fully fledged DDD is too much effort for your scenario then maybe you need to take a step down and look at something closer to Active Record.
I use DDD but in my scenario I have to support multiple front-ends; a couple web sites and a WinForms app, as well as a set of services that allow interaction with other automated processes. In this case, the extra complexity is worth it. I use DTO's to transfer a representation of my data to the various presentation layers. The CPU overhead in mapping domain entities to DTO's is small - a rounding error when compared to net work calls and database calls. There is also the overhead in managing this complexity. I have mitigated this to some extent by using AutoMapper. My Repositories return fully populated domain objects. My service layer will map to/from DTO's. Here we can flatten out the domain objects, combine domain objects, etc. to produce a more tabulated representation of the data.
Dino Esposito wrote an MSDN Magazine article on this subject here - you may find this interesting.
So, I guess to answer your "Why" question - as usual, it depends on your context. DDD maybe too much effort. In which case do something simpler.
Each requires a unique slicing or aggregating of information that SQL can do well but repositories can't as they're expected to return full entities.
Add methods to your repository to return ONLY what you want e.g. IOrderRepository.GetByCustomer
It's completely OK in DDD.
You may also use Query object pattern or Specification to make your repositories more generic; only remember not to use anything which is ORM-specific in interfaces of the repositories(e.g. ICriteria of NHibernate)
In Domain Driven Design are collection properties of entities allowed to have partial values?
For example, should properties such as Customer.Orders, Post.Comments, Graph.Vertices always contain all orders, comments, vertices or it is allowed to have today's orders, recent comments, orphaned vertices?
Correspondingly, should Repositories provide methods like
GetCustomerWithOrdersBySpecification
GetPostWithCommentsBefore
etc.?
I don't think that DDD tells you to do or not to do this. It strongly depends on the system you are building and the specific problems you need to solve.
I not even heard about patterns about this.
From a subjective point of view I would say that entities should be complete by definitions (considering lazy loading), and could completely or partially be loaded to DTO's, to optimized the amount of data sent to clients. But I wouldn't mind to load partial entities from the database if it would solve some problem.
Remember that Domain-Driven Design also has a concept of services. For performing certain database queries, it's better to model the problem as a service than as a collection of child objects attached to a parent object.
A good example of this might be creating a report by accepting several user-entered parameters. It be easier to model this as:
CustomerReportService.GetOrdersByOrderDate(Customer theCustomer, Date cutoff);
Than like this:
myCustomer.OrdersCollection.SelectMatching(Date cutoff);
Or to put it another way, the DDD model you use for data entry does not have to be the same as the DDD model you use for reporting.
In highly scalable systems, it's common to separate these two concerns.
After reading Evan's and Nilsson's books I am still not sure how to manage Data access in a domain driven project. Should the CRUD methods be part of the repositories, i.e. OrderRepository.GetOrdersByCustomer(customer) or should they be part of the entities: Customer.GetOrders(). The latter approach seems more OO, but it will distribute Data Access for a single entity type among multiple objects, i.e. Customer.GetOrders(), Invoice.GetOrders(), ShipmentBatch.GetOrders() ,etc. What about Inserting and updating?
CRUD-ish methods should be part of the Repository...ish. But I think you should ask why you have a bunch of CRUD methods. What do they really do? What are they really for? If you actually call out the data access patterns your application uses I think it makes the repository a lot more useful and keeps you from having to do shotgun surgery when certain types of changes happen to your domain.
CustomerRepo.GetThoseWhoHaventPaidTheirBill()
// or
GetCustomer(new HaventPaidBillSpecification())
// is better than
foreach (var customer in GetCustomer()) {
/* logic leaking all over the floor */
}
"Save" type methods should also be part of the repository.
If you have aggregate roots, this keeps you from having a Repository explosion, or having logic spread out all over: You don't have 4 x # of entities data access patterns, just the ones you actually use on the aggregate roots.
That's my $.02.
DDD usually prefers the repository pattern over the active record pattern you hint at with Customer.Save.
One downside in the Active Record model is that it pretty much presumes a single persistence model, barring some particularly intrusive code (in most languages).
The repository interface is defined in the domain layer, but doesn't know whether your data is stored in a database or not. With the repository pattern, I can create an InMemoryRepository so that I can test domain logic in isolation, and use dependency injection in the application to have the service layer instantiate a SqlRepository, for example.
To many people, having a special repository just for testing sounds goofy, but if you use the repository model, you may find that you don't really need a database for your particular application; sometimes a simple FileRepository will do the trick. Wedding to yourself to a database before you know you need it is potentially limiting. Even if a database is necessary, it's a lot faster to run tests against an InMemoryRepository.
If you don't have much in the way of domain logic, you probably don't need DDD. ActiveRecord is quite suitable for a lot of problems, especially if you have mostly data and just a little bit of logic.
Let's step back for a second. Evans recommends that repositories return aggregate roots and not just entities. So assuming that your Customer is an aggregate root that includes Orders, then when you fetched the customer from its repository, the orders came along with it. You would access the orders by navigating the relationship from Customer to Orders.
customer.Orders;
So to answer your question, CRUD operations are present on aggregate root repositories.
CustomerRepository.Add(customer);
CustomerRepository.Get(customerID);
CustomerRepository.Save(customer);
CustomerRepository.Delete(customer);
I've done it both ways you are talking about, My preferred approach now is the persistent ignorant (or PONO -- Plain Ole' .Net Object) method where your domain classes are only worried about being domain classes. They do not know anything about how they are persisted or even if they are persisted. Of course you have to be pragmatic about this at times and allow for things such as an Id (but even then I just use a layer super type which has the Id so I can have a single point where things like default value live)
The main reason for this is that I strive to follow the principle of Single Responsibility. By following this principle I've found my code much more testable and maintainable. It's also much easier to make changes when they are needed since I only have one thing to think about.
One thing to be watchful of is the method bloat that repositories can suffer from. GetOrderbyCustomer.. GetAllOrders.. GetOrders30DaysOld.. etc etc. One good solution to this problem is to look at the Query Object pattern. And then your repositories can just take in a query object to execute.
I'd also strongly recommend looking into something like NHibernate. It includes a lot of the concepts that make Repositories so useful (Identity Map, Cache, Query objects..)
Even in a DDD, I would keep Data Access classes and routines separate from Entities.
Reasons are,
Testability improves
Separation of concerns and Modular design
More maintainable in the long run, as you add entities, routines
I am no expert, just my opinion.
The annoying thing with Nilsson's Applying DDD&P is that he always starts with "I wouldn't do that in a real-world-application but..." and then his example follows. Back to the topic: I think OrderRepository.GetOrdersByCustomer(customer) is the way to go, but there is also a discussion on the ALT.Net Mailing list (http://tech.groups.yahoo.com/group/altdotnet/) about DDD.