I'm hoping someone has read Implementing DDD ( Vernon ), since all of my questions reference it
In article we can see from Figure 6 that both BankingAccount and PayeeAccount represent the same underlying concept of Banking Account BA
1. On page 64 author gives an example of a publishing organization, where the life-cycle of a book goes through several stages ( proposing a book, editorial process, translation of the book ... ) and at each of those stages this book has a different definition.
Each stage of the book is defined in a different Bounded Context, but do all these different definitions still represent the same underlying concept of a Book, just like both BankingAccount and PayeeAccount represent the same underlying concept of a BA?
2.
a) I understand why User shouldn't exist in Collaboration Context ( CC ), but instead should be defined within Identity and Access Context IAC ( page 65 ). But still, do User ( IAC ), Moderator ( CC ), Author ( CC ), Owner ( CC ) and Participant ( CC ) all represent the same underlying concept of a Customer?
b) If yes, doesn't then CC contain several model elements ( Moderator, Author, Owner and Participant ) which represent the same underlying concept of a Customer, just like both BankingAccount and PayeeAccount represent the same underlying concept of a BA?
c - If Moderator, Author ... don't represent the underlying concept of Customer, then what underlying concept(s) do they represent?
3. In an e-commerce system, the term Customer has multiple meanings ( page 49 ): When user is browsing the Catalog, Customer has different meaning than when user is placing an Order.
But do these two different definitions of a Customer represent the same underlying concept, just like both BankingAccount and PayeeAccount represent the same underlying concept of a BA?
UPDATE:
1.
I'd say that they don't have the same concept of book. Your proposal
stage probably wont have the concept of a book at all and the
editorial process probably wont use the concept of book either,
they'll probably refer to a Proposal and a Draft respectively, which
would be completely different things to a book.
As far as I can tell, author is implying that the concept of a book will indeed be modeled in all stages?
2.
The concept of Customer isn't mentioned in his example and your
e-commerce definition of customer wouldn't fit the model of
Moderators, Author, Owner, etc. You'd be best off modelling this
around your own distinct business needs.
Perhaps to avoid the confusion, instead of naming the underlying concept a Customer I should use a different name for it, maybe a Consumer. In any case, I used the name Customer for an underlying concept, which I assumed model elements such as User, Moderator, Author all represent.
3.
The two different meanings of customer in the two different contexts
probably wont have a basic underlying type. I doubt that during
browsing of the catalogue you'd be interested in the customer's name,
address, etc. whereas when placing the order you'd be interested in
these things, but less interested in what the last 10 products they
visited were.
But the whole point of DDD is that you model selected aspects of reality. In other words, aren't customer's name, address and its browsing history all properties of the same underlying concept of a Customer? As such, if the team is working on Catalog, it will model only those aspects/properties of an underlying Customer concept that are relevant to the browsing ( browsing history ... ), while team working on placing an order will model only those aspects of an underlying Customer concept that are relevant to placing an order ( address, name ... )?
thanks
I'm on the last few pages of the book and it's been a good read. Personally I'd have liked to see more examples using his 3 fictitious software products.
I'd say that they don't have the same concept of book. Your proposal stage probably wont have the concept of a book at all and the editorial process probably wont use the concept of book either, they'll probably refer to a Proposal and a Draft respectively, which would be completely different things to a book.
The concept of Customer isn't mentioned in his example and your e-commerce definition of customer wouldn't fit the model of Moderators, Author, Owner, etc. You'd be best off modelling this around your own distinct business needs.
The two different meanings of customer in the two different contexts probably wont have a basic underlying type. I doubt that during browsing of the catalogue you'd be interested in the customer's name, address, etc. whereas when placing the order you'd be interested in these things, but less interested in what the last 10 products they visited were. The two different context's concepts of Customer might only share a unique Customer id.
Related
In many applications, I deal with users and finance companies (as an example) and I have long been struggling to model the relationship between the two according to Domain Driven Design principles.
In my system I can do the following:
Add a user to an existing finance company.
Add a finance company to an existing user.
I believe both are aggregate roots... Finance Company and User.
How do I model the relationship between the 2? Is it FinanceCompany.Users? or User.FinanceCompanies? Is it neither? Or am I missing knowledge of some key DDD concept(s)? The problem is if I choose one way over the other, the code is more understandable / clear from one aggregate root entry point, but not the other. Sometimes there are cases where it makes more sense to navigate to a Finance Company and add users to it, and other times there are cases where it makes more sense to navigate to a specific user and add finance companies to the user.
Is there some better way to approach this, maybe through repository methods? Is there some key concept I am not getting or understanding here? It doesn't feel right to assume the relationship between Finance Company and User belongs under either of the 2 ARs. When I store the relationship I have to store it in a table named FinanceCompanyUsers or UserFinanceCompanies, but it still doesn't seem clear.
Would I have code such as FinanceCompany.AddUser() and User.AddFinanceCompany()? or is there some completely different approach for relationships such as this?
You have already determined that both User and FinanceCompany are aggregates so each has its own life-cycle.
The problem with many domains is that we don't have a complete understanding of the relationships. As another example we can take an Order and a Product. Both are aggregates but would we have Order.AddProduct() or Product.AddOrder()? In this case it seems pretty obvious in that an Order contains a limited subset of Product entries whereas a Product may very well contain many orders and we are not really too interested in that relationship since it is a rather weak relationship. A Product can exist and be valid without any orders attached but an Order is pretty useless without at least one product entry. This means that the Order has an invariant imposed in terms of its OrderItem entries. In addition to this we have enough knowledge about this hackneyed example that we know we are going to need an associative entity (in relational theory speak) since we need additional information regarding the relationship and entering the fray would be our OrderItem table. Curiously I have not seen it called OrderProduct.
The guidance I would suggest is to pick the most appropriate side.
However, if no side is a true winner and both aggregates can exist without a relationship to the other in terms of an invariant perhaps the relationship itself is an aggregate as you have certainly alluded to. Perhaps it isn't only a UserFinanceCompany aggregate but perhaps there is a concept that is missing from the ubiquitous language that the domain experts refer to. Perhaps something like Auditor or some such that represents that relationship. This is akin to the OrderItem or OrderLine concept as opposed to OrderProduct.
i'm trying to apply the domain driven design in a little project
i want to separate the authentication of rest of the users logic,
i'm using a value object for the id (userID) in the beginning i have the userID in the same level(package) of the users but I realize when i separate bounded context for authentication and user, they share a common value object for the userID, so my question is where supose that i have to put the common or share value objects? is correct if i created a packages called commons?
It is recommended to not share models between bounded contexts, however, you can share IDs and even simple Value objects (like Money).
The general rule is that you may share anything that is immutable or that changes very infrequently and IDs rarely change structure (here immutability refers to the source code and value immutability).
Packages called "common" usually refers to reusable concepts that you use in your projects, so that you don't have to code them in every project. There it's usual to put base abstract objects and interfaces, for entities, value objects, etc.
But it's not your case about userId. What you are saying is to put userId in a "shared kernel" model. It is an option, but usually it is not recommended.
From my point of view:
The auth BC has the concepts id,login,password,role,etc.
The user BC has concepts like name,surname,address,age,etc, but it also has to have the id, that it gets from auth BC.
From what I know, you have 2 options:
(1) Authentication BC shares "id" concept explicitly, i.e. it has a shared kernel. So "id" concept would belong to user BC model too.
(2) Authentication BC is a generic BC. So you have to integrate the user BC with the auth BC to get the id from it.
First of all, I personally see this as an context mapping question at code level, where you are effectively looking to have a shared kernel between multiple bounded contexts.
This depends on the business really. You typically need to consider the following questions:
How do different teams responsible for each bounded context collaborate with each other? If it's 1 team maintaining all the related bounded contexts, it might be OK, but it's multiple teams have different objectives, it leads to the next point.
How do you plan to maintain this shared kernel over time? In general, this shared kernel will need to change to adapt to business changes.
For more detailed arguments, there are plenty of resources out there about context mapping, such as Vaughn Vernon's book "Implementing Domain Driven Design".
I'm building an application that manages most of the LOB stuff at my company. I'm trying to wrap my head around DDD... starting with customer management. Many examples are very, very simple in regards to the domain model which doesn't help me much.
My aggregate root is a Customer class, which contains a collection of Addresses (address book), a collection of Contacts, and a collection of communication history.
Seems like this aggregate root is going to be huge, with functions to modify addresses, contacts (which can have x number of phone numbers), and communication.
E.G.
UpdateCustomerName(...)
SetCustomerType(...) // Business or individual
SetProspect(...) // if the customer is a prospect
SetDefaultPaymentTerms(...) // line of credit, etc. for future orders
SetPreferredShippingMethod(...) // for future orders
SetTaxInfo(...) // tax exempt, etc.
SetCreditLimit(...)
AddAddress(...)
RemoveAddress(...)
UpdateAddress(...)
VerifyAddress(...)
SetDefaultBillingAddress(...)
SetDefaultShippingAddress(...)
AddContact(...)
UpdateContact(...)
RemoveContact(...)
SetPrimaryContact(...)
AddContactPhoneNumber(...)
RemoveContactPhoneNumber(...)
UpdateContactPhoneNumber(...)
AddCommunication(...)
RemoveCommunication(...)
UpdateCommunication(...)
etc.
I've read that value objects don't have identity. In this system, each address (in the database) has an ID, and has a customerId as the foreign key. If Address is it's own aggregate root, then I wouldn't be able to have my business logic for setting default billing / shipping. Many examples have value objects without an ID... I Have no idea how to persist the changes to my Customer table without it.
Anywho, feels like I'm going down the wrong path with my structure if its going to get this ginormous. Anyone do something similar? Not sure how I can break down the structure and maintain basic business rules (like making sure the address is assigned to the customer prior to setting it as the default billing or shipping).
The reason that you're butting up against the issue of where business logic should lie is because you're mixing bounded contexts. LoB applications are one of the typical examples in DDD, most of which show the application broken up into multiple bounded contexts:
Customer Service
Billing
Shipping
Etc.
Each bounded context may require some information from your Customer class, but most likely not all of it. DDD goes against the standard DRY concept when approaching the definition of entities. It is OK to have multiple Customer classes defined, one for each bounded context that requires it. In each bounded context, you would define the classes with properties and business logic to fulfill the requirements within that bounded context:
Customer Service: Contact information, contact history
Billing: Billing address, payment information, orders
Shipping: Line items, shipping address
These bounded contexts can all point to the same database, or multiple databases, depending on the complexity of your system. If it is the same database, you would set up your data access layer to populate the properties required for your bounded context.
Steve Smith and Julie Lerman have a fantastic course on Pluralsight called Domain-Driven Design Fundamentals that covers these concepts in depth.
I'm implementing a college system, and I'm trying to use DDD. I'm also reading the blue book. The basics entities of the system are Institution, Courses, Professors and Students. This system will allow a lot of Institutions, each having its courses, students and professors.
Reading about aggregates, all entities fits inside the aggregate Institution, because doesn't exists courses without Institution, the same for students and professors. Am I right thinking in that way?
In some place the professors will access the courses that they teach. Using this approach, should I always access the courses through Institution? This implementation seems strange to me, so I ask myself if Professor, as Students should be their own AR and have their Repository.
Even though you have accepted an answer I am adding this anyway since a comment is too short.
This whole aggregate root business trips up just about everyone when starting out with DDD. I know, since I have been there myself :)
As mentioned, a domain expert may be helpful in some cases but keep in mind that ownership does not imply containment. An Order typically belongs to a Customer but the Customer is not the AR for an Order since an Order can exist without a Customer. You may think: "But wait, that isn't really true!". This is where is comes down to rules. When I walk into a clothing store I can purchase a pair of shoes. I am a customer but they have no record of me other than a receipt I can produce. I am a cash customer. Perhaps my particular brand of shoe is not in stock but I can still order it. They will contact me once it arrives and that will probably be that and I'll in all likelihood still not be registered in any computer system. However, that same store is registered as a Customer with their supplier.
So why this long-winded story? Well, if it is possible to have an Entity stand alone with only a Value Object representing the owner then it is probably going to be an AR. I can include some basic customer information in a CustomerDetails value object in an Order? So the Order can be an AR.
No let's take a look at an OrderLine. Can I include some basic OrderDetails information on an OrderLine? This feels odd since a number of order lines constitute an Order. So it isn't quite as natural.
In the same way a GrapeBunch has to have a GrapeStem and a collection of GrapeBerry objects.
This seems to imply that if anything can be regarded as optional it may indicate that the related instance is an AR. If, however, a related instance is required then it is part of the AR.
These ideas are very broad but may serve as guidelines to consider your structure.
One more thing to remember is that an AR should not be instanced in another AR. Rather use the Id or a Value Object representing the relationship.
I think you're missing some transactional analysis - what typically changes together as part of the same business transaction, and how frequently ? One big aggregate is not necessarily a problem if only 2 users collaborate on it with only a few changes per day, but with dozens of concurrent modifications it could become a contention point.
Besides the data inventory and data structuration aspect of the problem, you want to have an idea of how the system will be used to make educated aggregate design decisions.
Something that might help you to separate those entities into different aggregate roots is to ask you: Which one of those must be used together? This is usually helpful as a first coarse filter.
So, for example, to add a student to a course, you don't need the Institution?
In your example about a professor accessing the courses he teaches. Can he access them by providing his professor id rather than the professor entity? I he provides the professor id, then the entities won't be associated by a reference but by an id.
Lots of this concepts have evolved a lot since the blue book was written 12 years ago. Even though the blue book is a really good book, I suggest you to also read the red book (Implementing Domain-Driven Design by Vaughn Vernon). This book has a more practical approach to DDD and shows more modern approaches, such as CQRS and Event Sourcing.
A professor and a student can exist in their own right, indeed they may associate themselves with institutions. An institution exists in its own right. A course may exist in its own right (what if the same course is offered at more that one institution, are they the same?)... The domain expert would best advise on that (infact they should advise and guide the entire design).
If you make an aggregate too big you will run in to concurrency issues that can avoided if you find the right model.
Some PDFs I recommend reading are here:
http://dddcommunity.org/library/vernon_2011/
In my current project (e-commerce website), we have different Bounded Context like: billing, delivery or payment in our checkout process.
On top of this, depending on what the customer will buy, the checkout process will be different. So depending on the content of her cart the number of steps in the checkout process can be different, or we won't/will ask her for certain informations.
So should one create a different bounded context for each different type of checkout process ?
For example, the Order aggregate root will be different depending on the checkout process
EticketsOrder (in this context we don't need a delivery address so we won't ask one to the user)
Ticket BillingAddress
ClothesOrder (in this context we need a delivery address and there will be an additional step in the checkout process to get this)
Clothes BillingAddress DeliveryAddress
This separation will imply to create two different domain entities even thought they have similar properties.
What's the best way to model this kind of problem ? How to find the context boundary ?
A bounded context is chiefly a linguistic boundary. A quote from the blue book (highlighted key part):
A BOUNDED CONTEXT delimits the applicability of a particular model so
that team members have a clear and shared understanding of what has
to be consistent and how it relates to other CONTEXTS. Within that
CONTEXT, work to keep the model logically unified, but do not worry
about applicability outside those bounds. In other CONTEXTS, other
models apply, with differences in terminology, in concepts and rules,
and in dialects of the UBIQUITOUS LANGUAGE.
A question to ask is whether the different types of orders created are entirely distinct aggregates, or are they all order aggregates with different values. Is there a need to consider order as a whole regardless of how they were created? I've build and worked with ecommerce systems where different types of orders were all modeled as instances of the same aggregate, just with different settings and there were no linguistic issues. On the other hand, the orders in your domain may be different enough to warrant distinct contexts.
I often consider BC boundaries from the perspective of functional cohesion. If you segregate orders into two BCs will there be a high degree of coupling between them? If so, that may be a sign that they should be combined into one BC. On the other hand, if the only place that the BCs interact is for reporting purposes, there is no need to combined them.
It appears as though you may have missed a bounded context. When this happens one tends to try and fit the functionality into an existing BC. The same thing happens to aggregate roots. If something seems clumsy or it doesn't make sense try to see whether you haven't missed something.
In your example I would suggest a Shopping BC (or whatever name makes sense). You are trying to fit your checkout process into your Order BC. Your Shopping BC would be responsible for gathering all the data and then shuttling it along to the relevant parts.
The product type selected will determine whether a physical delivery is required.
Hope that helps.