I am reading the book Applying-Domain-Driven-Design-Pattern.
In its model design, it has the Order hold reference to Customer, but if it was me doing the design, i will probably have the Customer hold reference to Order.
So, the question, when designing unidirectional relationship, how to decide the direction?
I think if this were an order processing system where Orders are the operational-level concept and Customers provided the context for how to process orders, then an OrderService needs to have Orders refer to the Customer who made the Order. On the other hand, as others have pointed out, it's possible for a Customer can be queried for its orders. This is possible in a customer service system, where the help desk. In this case, I can see a CustomerService that needs Customers to have many Orders.
the answer to this is driven by the functionality of the application. If you need to query orders by customer, then your approach is correct. However, if customers are queried by their orders, then the model design is correct.
If you need to do both, then it's a bidirectional relationship and you may choose to model it as many-to-many.
A structure serves some function.
That is, think of how your classes will be used. Will Customer be queried for its orders? Will Order be queried for its Customer? If both, then you need a bidirectional relationship.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am trying to design a database that would be able to keep track of orders, and tracking information with as little repetition as possible. I own a company that gets products from multiple retailers that send the products to the customers directly. So for each order, there will be multiple products and multiple tracking links.
Here is the design of the db thus far:
This still is slightly repetitive because each order will have multiple rows in the order details and tracking tables. I was just wondering if there were smarter ways to go about designing this. Is this as normalized as possible?
Thanks
What I don't understand from your model are the business rules between tracking_details and order_details. Your model shows that tracking_item and product both have a retailer. So I might guess that there is a one-to-one relationship between tracking_details and order_details. It is a very good idea to list out such business rules and draw a diagram that spells them out.
Here is a model in UML notation I did a while ago. From what I can tell if you rename Contract to order in my diagram is pretty much equivalent to your model. My diagram tries to capture things like the business rules between what is in the things in the order (I called them LineItem, you called them order_details) and how it is shipped (I called them Delivery and you called them tracking_details):
I use the free online tool umletino to draw that UML diagram.
To really understand the business rules you need them to be explicitly spelt out. For example, the business rules of my model are:
A contract has many lineitems
A contract has many deliveries
A delivery to a location contains one or many lineitems
A lineitem is a quantity of a given product within a contract
A lineitem can only be in zero or one deliveries
Altering the lineitems within a contract updates the total cost of a contract
There are some other things in that high-level UML model. The black triangles imply 'aggregation' or 'ownership'. So the diagram indicates that the Contract (you called it order) controls the life-cycle of the items it owns below it. The implies that if I delete the order I will also delete it's Deliveries (you called those tracking_details) and it's LineItems (you called those order_details).
An additional facet of the UML diagram is that it marks some tables as <<Root Entity>>. This is a concept that is basically about how not to corrupt your database model. In my model the total cost of the contract/order must equal the sum of the costs of the order_details/lineitems. Yet I could write buggy code that screws things up. I could add or update lineitems/order_details and forget to update the total cost on the order table. The big idea of root entities is that you don't have code that just writes data behind the back of the order. The code that controls the order is responsible for updating the total quality and doing the insert/update/delete of the LineItems/order_details. That single code path ensures that the total quantity of the order always matches the sum of the LineItems/order_details within the database. The Product is also marked as a root entity and it might control it's own set of aggregate entities which are not shown on that diagram which is focusing on documenting only Contract/order.
In summary, I don't see any duplication in your model. If I was working on your project what I would like to see alongside the relational model are the business rules and ideas of how to organise code to help avoid corrupting the model or breaking the business rules. I would also like to understand the lifecycle of the things in your model such as aggregation. I encourage you to list out your business rules like I listed out mine above. Then try to draw a diagram (try that free tool at the link above) that captures all of the business rules. We call that a logical model. Then make the physical data model. (Warning: I wouldn't advise going crazy with UML only use enough to capture the key business ideas.)
To implement the physical model I needed one more table than implied by boxes in the UML. I needed a join table between delivery/tracking_details and the lineitems/order_details. That table would capture which delivery/tracking_detail was tracking which things within the order. If you list out the business rules and read through them it helps you uncover such details. My model says that a lineitem/order_detail can only be in one delivery. That business rule cannot be enforce with something like a foreign key constraint. Instead the single code path of my root entity ensure that all of the business rules around orders are checked in one place then unit tested logic would update all the associated tables. If you are using an OO language then that code would be in your Contract/order class. Other classes representing other root entities such as Product would enforce their own business rules and manage their own tables.
Your data model is reasonable as far as it goes. However, I do note that TrackingDetails and OrderDetails are both at the OrderId/ProductId levels.
That suggests that TrackingDetails should really have an OrderDetailsId instead of the OrderId and ProductId.
That said, I don't know if this is reasonable from a business perspective. OrderDetails doesn't have a "quantity", so I don't know if that is an oversight or if multiple products are different rows. Also, I don't know if a quantity of more than 1 could have split tracking information. That is, someone orders 100 foos, only 50 are in stock so 50 are shipped today and 50 next week.
Is there some rule of thumb, in which direction to make the association when designing domain model?
For example, we have products in the stock. Stock status of a product is a rather complex data structure, containing enumerations of multiple variations of the product either being in the stock, being out of stock or being bookable. Thus we make a seperate object of the stock status associated with the product. Now the question is, if product object should have a reference to it's stock status, or stock status have a reference to a particular product.
First solution feels like, it's not the real concern of product knowing it's stock state. Product is just a product, and maybe we should manipulate them in different context, where stocking is not a concern. In the other hand, stock status being a root feels awkward, as when thinking about stock, first we think about a product being in the stock.
How to decide, which entity acts as a root for the association?
You are assuming that both concepts are tightly coupled, meaning, they belong to the same bounded context. This means both models become dependent on each other - which may be something you don't want because it causes complexity you may not want. After all, you mentioned it yourself: "it's not the real concern of product knowing it's stock state". So why add a relation to it?
You could consider them as two separate bounded contexts - no direct relation between them, except for the product ID which links the two concepts.
Navigability is something you should simply neglect as it is something purely artificial. If two things are related, they know about each other. Actio et reactio. Gravity. Love. Try hard to find something that works only in one direction. Blackmail. Spy mirrors.
Introducing navigability indeed has only meaning in implementation phase. You try to decouple things in order to reduce dependencies, now for good. And what you actually do here is to attach role names towards the navigation. Which in turn makes the arrows superfluous.
TL;DR; Just don't use arrows in UML modeling. Leave them for the Powerpoint League.
First solution feels like, it's not the real concern of product knowing it's stock state. Product is just a product, and maybe we should manipulate them in different context, where stocking is not a concern. In the other hand, stock status being a root feels awkward, as when thinking about stock, first we think about a product being in the stock.
When we think about shopping carts, we think about products in the shopping cart. Yet most of the time, the useful way to model cart items is with a reference back to the product.
My guess would be that you need to be thinking more about Stock, and in particular about its life cycle; how tightly coupled are the lifetimes of the two different ideas? If you have a situation where a single Product has a relation to two different Stocks (one in the past, one in the present; one at this location, another at that location), then storing that relationship in the product isn't right.
I am using a table to centralize the addresses. Customers and Suppliers have a reference to address.
A Customer has an Address, an Address may or may not be associated with a Customer.
A Supplier has an Address, an Address may or may not be associated with a Supplier.
To ensure that an address is not associated with more than one Customer or Supplier, I have a unique index on the Customer and Supplier tables on AddressID column.
I am suspicious that this relationship is abnormal, because I am not able to map it using Entity-Framework with FluentAPI.
Edit:
In my real scenario, the address table will have many more columns.
In fact this is an adaptation to simplify a complex scenario where
the address table is a financial release and the tables customer and
supplier are representing the origin of the financial release, like
Sale and Purchase.
Your model seems reasonable. The merits of having a second table when you want to enforce a 1-1 relationship may not be obvious to everyone.
I can think of two good reasons off-hand:
You want the addresses in one place so you can treat all addresses equivalently (say geo-coding them, standardizing them, extracting features).
The address column is long and many queries do not require it, so you gain efficiency by not storing the address with the rest of the data ("vertical partitioning").
And there may be other reasons. I can't speak to why EF makes such relationships difficult to express.
In your current design this is not EF issue and by it self it cannot prevent you to assign the same address to a customer and to a supplier. If you go this path you are the sole responsible of enforce this uniqueness through business rules and validations in your model.
In the other hand, the correctness (or not) of your model design, apart from what Linoff points out in his answer, depends of the nature of your problem and what important and address is to your business. For example, if this is an app for Post Office, then the Address merits an individual table, as it will be one of the core concepts to your application. But if not, with the current approach you are going to add complexity to your model.
Update Edited to reflect clarifications requested by Chris Holmes below. Originally I was referring to a Terminal as a Site but changed it to better reflect my actual domain.
At heart, I think this is a question about modeling a many to many relationship between two root entities where the relationship itself carries some semantic meaning.
In my domain
You can think of a Terminal as a branch location of our company
A Terminal can have a relationship with any number of customers
A customer can have a relationship with any number of terminals (standard many to many)
A customer\terminal relationship means that a customer can potentially store products at the Terminal
This relationship can be enabled\disabled. To be disabled merely means you are temporarily not allowed to store product, so a disabled relationship is different from no relationship at all.
A customer can have many Offices
A Terminal that has a relationship with a customer (enabled or not) must have a default office for that customer that they communicate with
There are some default settings that are applied to all transactions between a Customer and a Terminal, these are set up on a Terminal-Customer Relationship level
I think my objects here are pretty clear, Terminal, Customer, Office, and TerminalCustomerRelationship (since there is information being stored specifically about the relationship such as whether it is enabled, default office, ad default settings). Through multiple refactorings I have determined that both Terminal and Customer should probably be aggregate roots. This leaves me with the question of how to design my TerminalCustomerRelationship object to relate the two.
I suppose I could make the traversal from Terminal to TerminalCustomerRelationship unidirectional toward the relationship but I don't know how to break the relation from the relationship to the customer, especially since it needs to contain a reference to an Office which has a relationship to a Customer.
I'm new to this stuff and while most of DDD makes perfect sense I'm getting confused and need a fresh outlook. Can someone give me their opinion on how to deal with this situation?
Please note that I say Relationship not relation. In my current view it deserves to be an object in the same way that a Marriage would be an object in an application for a wedding chapel. Its most visible purpose is that it relates two objects, but it has other properties that rightfully belong to it as well.
By your description, you definitely need a "TerminalCustomerRelationship" entity to track the associated information. I would also convert the 'IsEnabled' flag into a first class 'Event' entity with a timestamp - this gives you the ability to save a history of the state changes (a more realistic view of what's happening in the domain.)
Here's a sample application (in VS2008) that refects your problem. You can tweak/test the code until the relationships make sense. Run "bin/debug/TerminalSampleApp.exe" and right-click "Terminal->Create Example" to get started.
Let me know if you find it useful.
Names can often clarify an object's responsibilities and bring a domain model into focus.
I am unclear what a Site is and that makes the entire model confusing, which makes it difficult for me to offer better advice. If a Site were a Vendor, for instance, then it would be easy to rename SiteCustomerRelationship as a Contract. In that context it makes perfect sense for Contract to be its own entity, and have the the model look like Vendor-Contract-Customer-Office.
There are other ways to look at this as well. Udi has a decent post on this sort of many-to-many relationship here.
You should not have a object Like SiteCustomerRelationship, its DB specific.
If its truly DDD you should have a Relation like:
Aggregate<Site> Customer.Site
IEnumerable<Aggregate<Office>> Customer.Offices
and perhaps
Aggregate<Office> Customer.DefaultOffice
I am working on car dealership business domain model/UML class diagram.
I am new to modeling, so I would like to know how to validate the class diagram. It's very important for me to have an appropriate, if not 100 percent correct, class diagram to use further development (use cases, etc.).
Is it possible to build a completely incorrect model? Or are there only appropriate and less appropriate models?
If I have a Customer associated with SalesTeam modeling a customer being served by SalesTeam, is that wrong? I have seen in examples of Customer being associated with Order, Order with ItemOrder and ItemOrder with ItemInventory. Where the SalesTeam or Staff is associated with Order.
How do I validate my model and relationships?
To validate domain models, do the following.
Write use cases. During the writing, make sure you're using nouns and verbs in a consistent way. To be sure that your nouns make sense, be sure to record notes in the domain model.
Walk through each use case, following along on your domain model. At the entities there? Relationships required for navigation? Attributes of each entity?
Since it's a domain model, try to avoid describing things as classes -- they're usually real-world entities.
For example "customer entity in direct relationship with sales team entity" is something you'll learn from the use cases. For example, customers are associated with orders, but the order is created by the sales team. So, you have two navigation paths between customer and order: direct and via the sales team. Both appear (to me) to be true.
You must compare your domain model with your use cases to be sure both agree.
The short answer is that this is not very important.
Use your domain class diagrams to keep a note of what you think is in the domain, that is all. It is not your god, and it will not hurt you to change it as you go.
Domain experts should help you to validate the domain model.
As far as validating the specific relationships, as you develop the model further and investigate the collaborations between objects you will discover more and different relationships. You will need to revisit the domain model often during your analysis and development.
I don't think it matters that it's 'correct' up front (i.e. before you move onto looking at use cases and further analysis), only that it is useful - it gives you a conceptual model of the problem and what the main classes involved are. It isn't going to be finished until the software is no longer being developed or maintained.
If it represents the way you view the problem right now, it's good enough for you to start further analysis. Revise it as your view of the problem changes and you learn more.