• Advertisement
Sign in to follow this  

Inversion of control across libraries

This topic is 900 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Alright so lets say I've got a little library for graphics called... "GraphicsLib", a Physics library called "PhysicsLib", and another to hold them together... the "EngineLib." How can I go about making sure that EngineLib is not entirely dependant on GraphicsLib and PhysicsLib? I've read about Inversion of control/dependency injection and it sounds like it's the right thing for this, but it's left me a little bit puzzled.

 

What I've read about dependency injection is that you would create an interface and then inject the actual object you want it to be into the object using it. So in this example lets there would be an interface for the graphics and physics and then the Engine class would have a setter for each of those interfaces.

 

Now that's pretty straight forward but what happens when the graphics system isn't part of the same library? the interface needs to exist in both sections, the engine needs to know of the interfaces existence so it can call all of its functions yes? but then the graphics and physics libs need to know of their respective interfaces as well so they can inherit from them. Is Dependency injection really not the tool for the job here or am I just thinking about things all wrong?

 

I've also thought of an alternative where there is another library that both the "Engine" and the "Physics/Rendering" libs use that contains interfaces for everything the engine might use but... that seems like it could be a bit of a stretch to force this to work.

Share this post


Link to post
Share on other sites
Advertisement

Why can EngineLib not be dependant? Would you ever use engine without graphics and physics? If so, perhaps the stuff that is common to both graphics and physics can be broken out into it's own lib?

 

I'm not an expert by any means, but i have dealt with an issue similar to what i think you are describing. I bundled up anything math related into it's own library. The graphics library objects includes the headers it needs from this, and the physics library behaves the same way. The engine includes the graphics, physics, and math headers, and the application being worked on includes the engine headers. Since the actual translation units exist only once in their respective libs, I have no issues including each library into the application.

 

I've even kept the graphics library as agnostic as possible, and created one library that implements a dx9 version(which is what all of my existing code was based on), and another for DX11(which i have slowly been implementing), and yet another for gl4(which i've barely done anything with. The engine only knows about the base graphics library, while the app has the choice of including/linking to the implementation it wants.

#include "GraphicsDX9.h"
App game(new GraphicsEngineDX9( ... ), new PhysicsEngine(...), new InputEngine(...));

GraphicsEngineBase * renderer = game.GetGraphics();

// or

#include "GraphicsGL4.h"
App game(new GraphicsEngineGL4( ... ), new PhysicsEngine(...), new InputEngine(...));

GraphicsEngineBase * renderer = game.GetGraphics();

// etc

Yes it's a bit of the PITA, but it works well enough for what i need.

 

Edited by Burnt_Fyr

Share this post


Link to post
Share on other sites

Why can EngineLib not be dependant? Would you ever use engine without graphics and physics? If so, perhaps the stuff that is common to both graphics and physics can be broken out into it's own lib?

 

I'm not an expert by any means, but i have dealt with an issue similar to what i think you are describing. I bundled up anything math related into it's own library. The graphics library objects includes the headers it needs from this, and the physics library behaves the same way. The engine includes the graphics, physics, and math headers, and the application being worked on includes the engine headers. Since the actual translation units exist only once in their respective libs, I have no issues including each library into the application.

 

I've even kept the graphics library as agnostic as possible, and created one library that implements a dx9 version(which is what all of my existing code was based on), and another for DX11(which i have slowly been implementing), and yet another for gl4(which i've barely done anything with. The engine only knows about the base graphics library, while the app has the choice of including/linking to the implementation it wants.

#include "GraphicsDX9.h"
App game(new GraphicsEngineDX9( ... ), new PhysicsEngine(...), new InputEngine(...));

GraphicsEngineBase * renderer = game.GetGraphics();

// or

#include "GraphicsGL4.h"
App game(new GraphicsEngineGL4( ... ), new PhysicsEngine(...), new InputEngine(...));

GraphicsEngineBase * renderer = game.GetGraphics();

// etc

Yes it's a bit of the PITA, but it works well enough for what i need.

Yes, this sounds a lot like what I am trying to do. My confusion comes from the three separate libraries in your example (Engine lib, GraphicsGL4 lib, and the Graphics DX9 lib) all needing to know of some kind of abstract/interface GraphicsEngine class. In your example it looks like App game's constructor take some kind of abstract GraphicsEngine pointer, so app must know of this abstract class. In that case GraphicsEngineDX9 and GraphicsEngineGL4 must both also know about this abstract class, as they would be children of it so they can be passed into that constructor. Each of these classes are in different libraries though, so where does this abstract class exist? Does a copy of it just exist in all the libraries? If it exists in the Engine so that App can use it in its constructor, then how will GraphicsEngineDX9 or GraphicsEngineGL4 know about it? If it exists in GraphicsEngineDX9 then the engine would contain it since it contains the GEDX9 Lib, but then would a copy of it have to exist in GEGL4? That seems a little odd to me, but maybe it is fine? Perhaps I'm just missing some concept of abstract classes that is important here?

 

 

"Since the actual translation units exist only once in their respective libs, I have no issues including each library into the application." 

There might be something I'm missing in what you are saying though, because I'm not entirely sure what you mean by "translation unit."

Edited by ThePointingMan

Share this post


Link to post
Share on other sites


My confusion comes from the three separate libraries in your example (Engine lib, GraphicsGL4 lib, and the Graphics DX9 lib) all needing to know of some kind of abstract/interface GraphicsEngine class.

 

You would have to have another Core lib that they all depend on which has the interfaces required (I think the only common one would be IUpdateable and IInitializable?). This is how I have done it in my engine.

Share this post


Link to post
Share on other sites

You are getting that wrong. Dependency injection is one thing, Inversion of control is another thing.

first of all you have to get clear what a dependency is this depends also on the language:

 

CodeLevel Dependencies:

C++:

-You are dependent on headers that a class include, every header may add extra compile time and may break code because you inadvertently use some of the indirectly included headers.

-If you properly design code you increase number of dependencies => public interface, header of concrete class, implementation of concrete class

 

C#:

- importing is more about resolve name ambiguities (infact if you import a class, you do not need to import returned types of methods)

- no separation of implementation so if you have a interface you get only 2 files not 3 like in C++.

 

Class Dependencies:

The proper way to manage dependencies is to pass ALL YOU NEED to class constructors, and (most times) use some interface or abstract class to separate construction from behaviour (when you create a concrete class, you have code dependant on that concrete class, but when you pass the class around you are only dependent only on its interface).

 

You need to pass stuff by interface into constructors => that make the code damn easy to test (you can implement the interface with a mock and test the behaviour of the class using that interface).

 

Inversion of Control:

Hollywood principle, don't call us, we'll call you. When you do not have control over "main". Usually there are complex frameworks that provide a lot of functionality you have just to implement some interface and you will get called. Usually this removes a lot of control from you and most times it is hard to make such frameworks cooperate each other, usually those frameworks are something really big that do a bit of everything (Unity3D, Qt etc..)

 

Inversion Of Control applied to dependency injection ( aka DependencyInjection framework, aka InversionOfControlContainer)

This is especially important when you design code only around behaviour (you don't mind where a class is provided, you just assume the class is present). You will find designing code this way leads to simpler code because you have "to think less"(the first times you think much more, but after you get that everything becomes even more natural). But then how do you glue the code togheter? that's responsibility of a dependency injection framework. I think the bests are the ones that are lightweight (it is very possible to provide so much functionality in less than 2000 lines of code, i believe some have around 1500 infact).

Think to irrlicht, you have a IVideoDriver, a ISceneManager a IGUIManager. All these classes are created from a root (IDevice), since irrlicht do not use a proper framework you have to create the root from a C-style function, then you use the root to create other usefull classes, and if you look at implementation you will find that the root is creating stuff by calling constructors and passing zilliong arguments to the classes, if it has used a dependency injection framework irrlicht would not need any root, instead you just create classes that take as constructor parameter only what they need, that would have resulted in much simpler code both on engine and client sides (just most software from 10 years ago in C++ never use a proper framework but instead do Dependency injection manually in some way)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement