Circular Dependency and how to work around it.

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
L1FeMaKeR
Posts: 32
Joined: September 16th, 2013, 4:45 pm

Circular Dependency and how to work around it.

Post by L1FeMaKeR » May 13th, 2014, 4:12 pm

Quite often I got the problem of Circular Dependency.
I would like to know which tricks you guys know to work around that problem.
For example I have this problem (cut some code which would not have something to do with that problem)

GraphicSystem.h:

Code: Select all

#include "VertexObject.h"

struct Vertex
{
	D3DXVECTOR3			Position;				// Position of Vertex
	D3DCOLOR			DiffuseColor;			// Color of Vertex
	D3DXVECTOR2			Texture;					// Coordinates for the Textures
};

// One Polygon with 3 Vertices
struct Triangle
{
	Vertex Vertices[3];
};

class GraphicSystem
{
	// Functions
public:
GraphicSystem(HWND hWnd);
~GraphicSystem();	
void DrawVertexObj( VertexObject* Object);

};
The Graphicsystem has the Vertex Structure and the Triangle Structure. To Render the VertexObject class it would be cool if I just give it the Object and the GraphicSystem class would do all rendering for me

Code: Select all

#include "GraphicSystem.h"
class VertexObject
{
	// Functions
public:
	VertexObject();
	~VertexObject();

	// Members
private:
	std::vector<Triangle> m_Tris;	// A std::Vector containing every Triangle of the Object
	UCHAR m_numTris;		      // Amount of Triangles in the Object
	
};
This VertexObject needs to know the Triangle Structure because it is based on many triangles.
But This will end in an circular dependency. How could I get rid of this problem?

But the generell question remains. What tricks do you know how to avoid situations like this?

Thanks!

User avatar
LuX
Posts: 1492
Joined: April 22nd, 2012, 12:33 pm
Location: Finland

Re: Circular Dependency and how to work around it.

Post by LuX » May 13th, 2014, 4:58 pm

What you do is define all the stuff you need in multiple places in a separate file.
In this case you could define "Vertex" and "Triangle" in "VertexObject.h", then include that into "Graphics.h". Optionally you could define "Vertex" and "Triangle" in it's own file "Something.h", then include that into "VertexObject.h" and "Graphics.h".
ʕ •ᴥ•ʔ

User avatar
SpaceAnimation
Posts: 245
Joined: July 15th, 2013, 3:31 am

Re: Circular Dependency and how to work around it.

Post by SpaceAnimation » May 13th, 2014, 5:09 pm

Hey life maybe its a design problem. Circular dependency, was at first such a pain to debug, didnt know what it was and why I had this problem.

Pretty much you have made two structures or classes or a combo of those that rely on eachother but then you get this header loop as if one of the files cannot include the header it relies on as its already been defined in the other file... right?

My trick is to not design it that way. I vaguely remember a teacher of mine coming up with a solution though is was a very stretched solution and I put that into the basket of things i shouldn't do on a regular basis... thus I try not to make two classes that depend on each other.

I would just put the struct triangle and vertex in the file vertexObject as that is what needs it. The graphicsSystem file doesn't use it, It uses a vertexObject which is made up of triangle - which in turn is made up of vertex. To sum up you have them in the wrong file to begin with :p

sorry if thats not the answer you wanted but I would avoid this type of problem as I can't see the benefit, but I would rethink that idea if someone can convince me of why it would be a good idea... hhhmmm :)

One type of structure could be visualised as a tree branch. As it grows new branches are made at a node and they split off into other directions and this process continues, but never does any of the new branches grow back into previously made branches. So as you make new classes you want to link to those adjacent classes but never make a recursive link - link back to one that has already been linked. Basically structures are not loops, they are containers that hold and separate information. Discrete processes in functions should be generating loops for simulation purposes that use that data being held in structures.

Depending on how the data is structured into containers one can create rules and ordering of how that information can be accessed and found. If you can create a structure that holds information in such a way that is can be accessed quickly - without much work having been done. A well designed structure can automate data access intuitively.

If you have a bowl and you want to make fruit salad you might want to include an apple and an orange into your bowl to make the combination of the two and now you have access to both fruits in the one bowl. But it would be unreasonable to make an apple tree grow oranges but then how can you make the orange tree now grow apples if %50 of the time you might get either an apple or an orange as an apple tree has already been converted into an orange tree and is no longer an apple tree it is an appleOrange tree and now you cant make an orangeApple tree and you no longer have an apple tree.

LOL, if that make you confused then you now understand circular dependency and why I avoid it.
Spacey :geek:

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Circular Dependency and how to work around it.

Post by chili » May 14th, 2014, 3:56 am

Solving circular dependency is pretty straightforward in cases where there is a clear master-slave / client-server / high level-low level relationship.

Just write it so that the lower level (server) part doesn't need knowledge of the layers above it. In your case, delete the line #include "VertexObject.h" and change void DrawVertexObj( VertexObject* Object) to void DrawVertexObj( class VertexObject* Object) (i.e. forward declare VertexObject). Then in Graphics.cpp you can include VertexObject.h and properly define the incomplete forward declared VertexObject.

There are other ways of solving the problem too. You can declare an interface at the low level that the high level layers will inherit from. That can solve some nasty situations that the above solution won't fix.
Chili

L1FeMaKeR
Posts: 32
Joined: September 16th, 2013, 4:45 pm

Re: Circular Dependency and how to work around it.

Post by L1FeMaKeR » May 14th, 2014, 9:53 am

I guess the best way to go around this problem in generell is to create a Typedef.h for every selfmade Datatype that needs to be known by more than one implementation (class).
DirectX and Windows does the same afaik (d3d9types.h or windef.h).
In this particular problem I could make an "Graphictypedef.h", which would include every Graphictypedefs I would need in different places.

A real Problem I got is, that I don't know much about Code-Architecture. I've found a few information about this mighty think called "interfaces", which seem to be very practical once you set them up. But I had a hardtime rearly using them correctly.

On the other hand I got problems thinking about a good way to handle data access in a way that:
for example the Gameclass itself would store the Data (for example the 3DObjects), but couldn't do anything with it. It would pass a pointer/reference to the Graphicclass. The Graphicclass on the other hand would have all the acces to the data it needs to do it's job (renderin' and stuff).

- One way I've come up this would be using interfaces. The Gameclass only knows one interface to the data, which give the Gameclass very limited acces to the data (almost none). On the other Hand the Graphicclass knows interfaces which would give the Graphicclass all the acces it needs.

- Maybe I could use the Server/Client Stuff chilli used with the mouse classes in the framework.
Meaning the GameClass would know a Data-Client Class Version. and GraphicClass would know a Data-Server Class Version. With Polymorphism and the pointer tricks chilli mentioned it could be realised.
So the Gameclass would have the data but It uses a pointer of the base class (client class) to store them, and so Gameclass wouldn't have acces to the Data directly. And when the Graphicclass would get the Data as an Pointer, it would store it in a pointer of the derived class (server class).
With this way Graphicclass would have acces to the Data to render stuff etc. I could easily create more derived classes which would give only a certain amount of access.
One derived class only gives access to the data, so the 3D Graphic could render it
One derived class only gives access to the data, so that an Physikclass could move the objects etc.
This would mean I would have more Server than clients and would maybe break the concept of client server, but would give me a way to handle dataaccess correctly.

Would be interested in what you guys think about that?

engi
Posts: 161
Joined: April 7th, 2014, 6:00 am
Location: Brazil

Re: Circular Dependency and how to work around it.

Post by engi » May 16th, 2014, 1:19 am

Forward declarations will be enough in almost all scenarios
0x5f3759df

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Circular Dependency and how to work around it.

Post by chili » May 16th, 2014, 1:20 pm

Yeah brah, you're overthinking this one. Just forward declare vertex object in your graphics header and you're done.
Chili

L1FeMaKeR
Posts: 32
Joined: September 16th, 2013, 4:45 pm

Re: Circular Dependency and how to work around it.

Post by L1FeMaKeR » May 17th, 2014, 12:32 pm

Never got forward declaration to work. Possibly doing that wrong:
I Put

Code: Select all

class VertexObject;
in Graphicsystem.h

and a Instance of that class called "Test"
Then the compiler says:
Graphicsystem::Test uses undefined class "VertexObject"

User avatar
LuisR14
Posts: 1248
Joined: May 23rd, 2013, 3:52 pm
Location: USA
Contact:

Re: Circular Dependency and how to work around it.

Post by LuisR14 » May 17th, 2014, 7:21 pm

well you would put the forward decl in the global scope before the class(es) that uses it, or you could add the "class" keyword everywhere you declare a variable of the class to forward decl.
always available, always on, about ~10 years c/c++, java[script], win32/directx api, [x]html/css/php/some asp/sql experience. (all self taught)
Knows English, Spanish and Japanese.
[url=irc://irc.freenode.net/#pchili]irc://irc.freenode.net/#pchili[/url] [url=irc://luisr14.no-ip.org/#pchili]alt[/url] -- join up if ever want real-time help or to just chat :mrgreen: --

Post Reply