Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid Circular Dependency

I am developing a travel management application. The design in question is something like following :

Each person in a tour is designated as a Traveler. Each Traveler has a Passport. Now, a Traveler can be a MainMember or a SubMember, depending on whether or not he is the head of the family. A MainMember decides stuff like TourPackage, total amount for his travelling family, etc. A SubMember is dependent on the MainMember while travelling. So, if a MainMember is deleted, all its SubMembers have to be deleted as well.

So, A Traveler has a Passport. (One to One relationship) A Traveler is either a MainMember or a SubMember. (one-to-zero/one between Traveler-MainMember and Traveler-SubMember) A MainMember may have several SubMembers. (one-to-many) A SubMember has only one MainMembers. (many-to-one)

My current ERD is something as follows.

Traveler ER Diagram

As you can see, the three tables - Traveler, MainMember and SubMember - have formed a circular dependency. I am not sure if it will hurt my application, though. If I delete a Traveler who is a MainMember, then 1. A record from Traveler is deleted. 2. Its relevant MainMember record is deleted. 3. The SubMember records dependent on MainMember are deleted. 4. The Traveler records of SubMembers are deleted.

Though it doesn't seem to be a problem, as a Traveler-MainMember delete will always delete only Traveler-SubMember(s). Still, I have a bad feeling about this.

Can anyone guide me to a better design?

UPDATE -

While waiting for the replies, I came up with another design, based on @Daveo's reply. Basically, Traveler contains self-referential foreign key. It would be used by the SubMember records to identify their parents.

Here is the ERD for that.

ERD with Self Referential table

Now, as there was no issue of circular dependency in my previous design, as pointed by @Branko, I would like to know which design is better?

Also, which design would be better to implement through Hibernate? I think the second approach might lead to complexity while implementing through Hibernate.

I would also appreciate some pointers regarding the implementation patterns (inheritance in Hibernate entities, etc.) for the design that you prefer.

like image 265
Jayesh Bhoot Avatar asked Feb 21 '13 09:02

Jayesh Bhoot


People also ask

How can circular dependencies be avoided?

Circular dependencies can be introduced when implementing callback functionality. This can be avoided by applying design patterns like the observer pattern.

How do I get rid of circular dependency detection?

Here is how to fix circular dependency detected in Google Sheets: The first method is changing the cell range so that the formula doesn't contain the cell the formula is in. In the example above, we reduced the range to B2:B5—the formula in cell B6.

How do you handle cyclic dependency?

A cyclic dependency is an indication of a design or modeling problem in your software. Although you can construct your object graph by using property injection, you will ignore the root cause and add another problem: property injection causes Temporal Coupling. Instead, the solution is to look at the design closely.

How do you avoid circular dependencies in Python?

Change Name of working python script: Changing the name of the Working file different from the module which is imported in the script can avoid the Circular Imports problem. Import the module: Avoid importing objects or functions from a module that can cause Circular Imports.


2 Answers

As you can see, the three tables - Traveler, MainMember and SubMember - have formed a circular dependency.

No, this is not a circular dependency - no "node" in this graph can reach itself by following graph "edges" in their proper direction1. It would be more accurately described as "merged" or even (proto) "diamond-shaped" dependency.

And no, it will not hurt your application.2

You are effectively implementing inheritance (aka category, subclassing, subtyping, generalization hierarchy etc.), using "each class in separate table" approach. This approach is clean, but cannot guarantee presence3 and exclusivity4 out of box. There are ways to amend it so it does, and there are other implementation strategies for inheritance that can, but they have their own pros and cons.

In my opinion, your model is just fine for what you are trying to accomplish and enforcing the presence/exclusivity at the application level is probably lesser evil than suffering the cons of trying to enforce it at the database level.


1 "Direction" is from referencing to referenced table. Traveller doesn't reference MainMember nor SubMember and therefore breaks the cycle.

2 Unless you are on a DBMS (such as MS SQL Server) that doesn't support referential actions on such "merged" dependencies (in which case you'd need to implement ON CASCADE DELETE through triggers).

3Traveller cannot exist alone (cannot be "abstract"), it must be MainMember or SubMember.

4Traveller cannot be both MainMember and SubMember.

like image 190
Branko Dimitrijevic Avatar answered Sep 28 '22 00:09

Branko Dimitrijevic


I would only have two tables in the database.

Traveller and Password

Traveller will have a Parent_Id field which will link back to the Traveller table and will store who the Main/Head traveller is. Also store fields common to either Main/Sub member in this table like contact number

Then using inheritance and ORM create two different classes in your actual application. MainMember and SubMember MainMember would be all rows in Traveller where Parent_Id is null SubMember would be all rows in Traveller where Parent_Id is not null

like image 32
Daveo Avatar answered Sep 28 '22 02:09

Daveo