1

I've been struggling with this question for a while.

I'm specifically thinking within the object orientated domain model.

Let's say I have two entities. A supplier and a customer. There is a relationship that a supplier can have many customers, and a customer (in this case) can only have one supplier.

The issue I have is that neither object needs any behaviour of the other object i.e. the supplier object does not need to use any behaviour of the customer object and visa versa.

There is however still an association between them. The reason is that the problem domain requires that all a suppliers customers are destroyed if the supplier is destroyed. We also need to be able to retrieve a collection of all customers associated with a supplier.

How is this managed in the OO domain model? Who is responsible for the association?

Some may say that there should be a getCustomers() method on the supplier object and this is where the association lies. I don't really like this as it makes it difficult to close the supplier class (violation of Open Closed Principle). Every time we create a new type of class which has an association to a supplier, we have to add a get method to the supplier.

One thing I think could be used to model the association are repositories (from Eric Evens Domain Driven Design book). I guess it would be the Repository that then cares about this relationship? We could call selectCustomersFor(supplier_id) etc

Edit

The only reason I can see for having the association is for object retrieval criteria or object destruction (i.e. if user is destroyed, all customers will be destroyed). To me, it is not the responsibility of either object to retrieve or destroy itself. You could argue that the supplier should retrieve/destroy a customer, but this surely violates the Single Responsibility rule, and could also lead to Open Closed violation.

Why would we then bother to add the responsibility of association to an object thats doesn't use it? Its useless to the object. The association isn't useless though, I just feel something else should be responsible for it.

8
  • I like modeling this relationship in the database and querying for the data when I need it. Basically the selectCustomersFor(suppier_id) that you mentioned. I don't see anything wrong with having a list of customers in the supplier object or vice-versa. You said it violates the Open Closed Principle, but every supplier / customer needs to have 0 or more suppliers / customers associated with it. Sep 8, 2014 at 16:57
  • @gnat i have reword this question. The question now is Where does this type of association come from? How is it managed in the domain?
    – GWed
    Sep 8, 2014 at 17:08
  • putting get methods on the supplier class will likely cause OCP problems. What if I want to at a later date have a 'partners' class. I now need to add getPartners to suppliers. This violates OCP. Putting getUser on customer class - what does this give me? The only reason I can see to have the association is for object retrieval criteria and object destruction.
    – GWed
    Sep 8, 2014 at 17:22
  • 1
    I do not have an answer for you, but some follow-on questions that might help guide you toward the right solution for this situation. What behaviors do the supplier and customer need to invoke on each other, if any? If a third object has a supplier, does it need to invoke behavior on its customers? If it has a customer, does it need to invoke behavior on its supplier? Let the question of how you use the objects guide this. Using a repository (which may delegate to a data store) could be the right way too, but the question as written does not give enough information to provide a good answer
    – user22815
    Sep 8, 2014 at 18:43

4 Answers 4

0

Q:Why objects reference each other?
A:To make the model consistent and valid.

Let's try to model your domain. Supplier is an aggregate. Customer is an aggregate. Suppliers are created and managed in their bounded context. In this context I can create/update/delete/enable/disable suppliers.

Customers are managed in their bounded context. Any customer must be associated to a certain supplier. Why you ask? coz that's what the domain experts told us. So whenever a customer is created I'll pass it a supplierId value object.

But Suppliers and Customers don't need anything from each other? Actually they do. Each of them need to be valid and consistent in the system. A Customer must be associated with a certain Supplier to be a valid customer.

When you need to delete a Supplier you will delete it in its bounded context then send a domain event to the Customer's bounded context with the supplier's id. You will retrieve all suppliers associated to that supplier and delete them.

Remember the one aggregate per transaction rule.

In case you modeled everything as a single bounded context then in your application service start transaction, fetch the supplier from its repository, delete it, fetch the associated customers from their repository, delete them then commit the transaction.

This might be quick and dirty, but it may suffice your needs.

1

Sometimes an object doesn't use it's own relationships. A customer doesn't always use it's supplier in code, but others do want to use it. And by putting the relation in your domain model, you allow easy and quick access to this relationship.

When you hardly use the relationship it could be better to request the supplier from the repository.

But you also talk about deleting the customer when the supplier gets deleted. If you are using an ORM, changes are they can do this for you, but therefore you will probably need to have the relationship in you domain model (if you also map your domain model directly to the database) (This is at least true for Hibernate (java) / NHibernate (.NET)). When you write all your database queries by hand, it doesn't matter so much.

So I think it is just a matter of convenience vs. a pure domain model.

-1

This would be an example of a transitive association, through an association object like an order or invoice that references both Customers and Suppliers. If you have no such objects then your model is probably incomplete or decomposed beyond the point of usefulness.

2
  • But why would the invoice object need to know about either? My point still stands. The order object does not need to use the supplier or customer object. It has absolutely no use for any method that resides on the supplier or customer object. Why would we then bother to add the responsibility of association to the invoice object? Its useless to the object. The association isn't useless though, I just feel something else should be responsible for it.
    – GWed
    Sep 8, 2014 at 18:27
  • The invoice is a record of a transaction between a supplier and a customer. At the very least, the invoice needs to be able to get the names of the supplier and the customer when it prints itself.
    – TMN
    Sep 8, 2014 at 19:14
-1

There is a relationship that a supplier can have many customers, and a customer (in this case) can only have one supplier.

Surely there's a business-driven reason for you to say that. Why is it necessary for a customer to only have one supplier? Is there some crucial invariant you need to enforce? Is there something you can do to a supplier which will affect all the customers?

Generally a domain expert will come up with a rule like that because of some underlying principle. Your experts may not realise that it's not obvious to you why the rule exists, so you need to communicate with them! When you arrive at the underlying business principle, that is what you should try and represent in your code.

6
  • Why would either object be responsible for the association if they don't need the underlying object? I just feel that the supplier and customer class aren't responsible for the association, but something else in the domain model must be. What is it?
    – GWed
    Sep 8, 2014 at 18:29
  • This is the sort of question you should be asking to the domain experts you're working with, not to strangers on the internet ;) Sep 8, 2014 at 18:30
  • Its not a problem domain question. The problem domain requires the association. The implementation of this domain (i.e. in OO) is where my question lies. How do we implement this association?
    – GWed
    Sep 8, 2014 at 18:34
  • I'm trying to nudge you towards trying to find out why the problem domain requires the association. Such associations can be encoded however you like, really, but if you want to choose the best way you need to understand the meaning of the association within your problem domain. That's not something a stranger can help you with. Sep 8, 2014 at 18:39
  • Ah ok, understood. The reason is that its needed for object retrieval (get all customers of supplier) and for object destruction (if supplier is deleted, all its customers are deleted) –
    – GWed
    Sep 8, 2014 at 19:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.