Reputation: 12972
I have just started a project to make my employer a management software. I have a niggling, but potentially simple, query that I can't seem to find any information on.
Is it prudent/good practice to have a 2 way 'has a' relationship between objects. So can, for example, a Client
object 'have a' Site
, and then the Site
'has a' Client
, where the Client
object is the Client
that 'has' the Site
?
public class Client {
Site site;
}
public class Site {
Client client;
}
Is there anything objectionable (no pun intended) to this, or is it fine? I am currently creating a mock-up UML for the project, and this has been bothering me.
Upvotes: 20
Views: 6240
Reputation: 85779
Is there anything objectionable to this, or is it fine?
There's no definitive answer to this. The best answer is: it depends to the design of your application.
When to use it
If your Client
object should navigate to the Site
object and your Site
object should navigate to the Client
object, then the current example in your code is fine. Still, probably you will need some way to associate these elements, probably by an additional id field on one of the classes or in both.
If it happens that you work with a framework that helps you to bind the classes automatically like Hibernate, then maintaining the circular reference won't be a problem for you.
When not to use it
Basically, for text serialization, since it will generate an infinite loop. As already mentioned in Raibaz's answer, a library like Jackson will fall into infinite loop while serializing Client
or Site
class into a JSON string1. Note that this is also valid when serializing to other String
data like passing the objects through a JAX-WS web service in XML (more info: What happens to generic class in jax-ws webservice?).
1 This can be solved using annotations (@Something
) that belong to a specific library e.g. @JsonManagedReference
and @JsonBackReference
from Jackson library, as noted by @SimonAndréForsberg, but the downside of this solution is that your classes will have tight coupling with the library.
Upvotes: 4
Reputation: 86391
It's common to have a mutual association between objects.
For example, in some user interface toolkits, a visual component will have references to its children, and each child may have a reference to its parent.
The term has-a is frequently used to communicate ownership of one object by another. When this is true, the relationship is usually one-way.
One good definition of these terms is provided in "The Unified Modeling Language User Guide", by Booch, Rumbaugh and Jacobson:
Aggregation -- A plain association between two classes represents a structual relationship between peers, meaning that both classes are conceptually at the same level, no one more important than the other. Sometimes, you will want to model a "whole/part" relationship, in which one class represents a larger thing (the "whole"), which consists of smaller things (the "parts"). This kind of relationship is called aggregation, which represents a "has-a" relationship, meaning that an object of the whole has objects of the part.
Upvotes: 2
Reputation: 2339
I'd try to stick to 1-way relationship whenever possible. 2-way relationships makes two classes tied together and a change in one of them causes the other to change two. Ask yourself if such relation is really natural...
If you have to, just make sure both are interfaces or at least one of them is.
Upvotes: 1
Reputation: 174
It is common, but I would consider how loosely coupled you want the child object to be from its parent. If you have the reference to the parent from the child object then you will not be able to reuse the object with another parent / no parent.
Upvotes: 2
Reputation: 9700
It's quite normal and quite common to have a bidirectional association like the one in your example.
The only caveat you may want to consider is when you are going to serialize your objects, for instance in json using Jackson or any other library, you should exclude one of the two sides of the association from serializing to avoid ending in an infinite loop.
Upvotes: 1