473,661 Members | 2,440 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Dependency Inversion Principle Dilemma

Hi,

According to Robert Martin's Dependency Inversion Principle,
http://www.objectmentor.com/resources/articles/dip.pdf,
when there is a need to test the type of an object, the
code inside the "switch cases" should be placed into the
parent class.

However, I am finding that this conflicts with the other
principles -- the objects now must know details about
objects outside their own encapsulation.

For example, using the Shape class:
class Shape
{
virtual void draw() = 0;
};

class Square
: public Shape
{
void draw();
};

class Triangle
: public Shape
{
void draw();
};

The above "draw" methods must know something about the
external environment in order to draw their shape. I
believe this conflicts with the Integration Separation
Principle as well as the K.I.S.S. (Keep It Simple (and)
Stupid).

So how does one implement (or not violate) the Dependency
Inversion principle without violating the encapsulation
by require details of external interfaces?
Can one keep a Triangle simplified so it is just a
Triangle class?

Otherwise, one would have to keep modifying the base
Shape class everytime a new display device comes up.
{Or any other entity that would need to know the
type of shape}.
--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.l earn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 22 '05 #1
12 2431
This will only be a "me too" answer, I'm afraid.

Thomas Matthews wrote:
Hi,

According to Robert Martin's Dependency Inversion Principle,
http://www.objectmentor.com/resources/articles/dip.pdf,
when there is a need to test the type of an object, the
code inside the "switch cases" should be placed into the
parent class.

However, I am finding that this conflicts with the other
principles -- the objects now must know details about
objects outside their own encapsulation.

For example, using the Shape class:
class Shape
{
virtual void draw() = 0;
};

class Square
: public Shape
{
void draw();
};

class Triangle
: public Shape
{
void draw();
};

The above "draw" methods must know something about the
external environment in order to draw their shape. I
believe this conflicts with the Integration Separation
Principle as well as the K.I.S.S. (Keep It Simple (and)
Stupid).
That's exactly the problem that I have with this. A triangle should not
know that it can be drawn, or what class is responsible for drawing
triangles. It should only be a container for the three vertices and
maybe contain some triangle specific functions (area, center of mass or
whatever).
So how does one implement (or not violate) the Dependency
Inversion principle without violating the encapsulation
by require details of external interfaces?
Can one keep a Triangle simplified so it is just a
Triangle class?
Sorry, I don't know any good way, but I'd be interested in it, too.
Otherwise, one would have to keep modifying the base
Shape class everytime a new display device comes up.
{Or any other entity that would need to know the
type of shape}.


Not only the base class, but also every derived one. And if you want to
reuse your class hierarchy e.g. for writing a file conversion tool
can't draw at all, you'd either have to make a dummy renderer or edit
all the classes to remove the draw function.

Jul 22 '05 #2
On Thu, 18 Dec 2003 18:32:54 GMT, Thomas Matthews <Th************ *************** *@sbcglobal.net > wrote:
class Shape
{
virtual void draw() = 0;
};

class Square
: public Shape
{
void draw();
};

class Triangle
: public Shape
{
void draw();
};

The above "draw" methods must know something about the
external environment in order to draw their shape. I
believe this conflicts with the Integration Separation
Principle as well as the K.I.S.S. (Keep It Simple (and)
Stupid).
Apart from the above being nonsense C++ (it would be better with
'struct' instead of 'class') this is off-topic in this group.

Try instead e.g. [comp.programmin g].

So how does one implement (or not violate) the Dependency
Inversion principle without violating the encapsulation
by require details of external interfaces?


Use an abstract interface.
struct ICanvas
{
virtual void setPixel( Point const& pos, Color const& aColor = Color::black ) = 0;
};
struct Shape
{
virtual void drawAt( Point const& upperLeft, ICanvas& aCanvas ) = 0;
};

Jul 22 '05 #3
Thomas Matthews wrote:
Hi,

According to Robert Martin's Dependency Inversion Principle,
http://www.objectmentor.com/resources/articles/dip.pdf,
when there is a need to test the type of an object, the
code inside the "switch cases" should be placed into the
parent class.
That's the traditional OO approach. Sometimes it's appropriate, but
often it's not.
However, I am finding that this conflicts with the other
principles -- the objects now must know details about
objects outside their own encapsulation.

For example, using the Shape class:
class Shape
{
virtual void draw() = 0;
};

class Square
: public Shape
{
void draw();
};

class Triangle
: public Shape
{
void draw();
};

The above "draw" methods must know something about the
external environment in order to draw their shape. I
believe this conflicts with the Integration Separation
Principle as well as the K.I.S.S. (Keep It Simple (and)
Stupid).

So how does one implement (or not violate) the Dependency
Inversion principle without violating the encapsulation
by require details of external interfaces?
Can one keep a Triangle simplified so it is just a
Triangle class?

Otherwise, one would have to keep modifying the base
Shape class everytime a new display device comes up.
{Or any other entity that would need to know the
type of shape}.


// Use overloaded functions.

namespace Shapes
{
class Shape { /* ... */ };
class Square: public Shape { /* ... */ };
class Triangle: public Shape { /* ... */ };
}

namespace Display
{
void draw( Shapes::Shape const& ) { /* ... * }
void draw( Shapes::Square const& ) { /* ... * }
void draw( Shapes::Triangl e const& ) { /* ... * }
}

Jul 22 '05 #4
Alf P. Steinbach wrote:
On Thu, 18 Dec 2003 18:32:54 GMT, Thomas Matthews <Th************ *************** *@sbcglobal.net > wrote:

class Shape
{
virtual void draw() = 0;
};

class Square
: public Shape
{
void draw();
};

class Triangle
: public Shape
{
void draw();
};

The above "draw" methods must know something about the
external environment in order to draw their shape. I
believe this conflicts with the Integration Separation
Principle as well as the K.I.S.S. (Keep It Simple (and)
Stupid).

Apart from the above being nonsense C++ (it would be better with
'struct' instead of 'class') this is off-topic in this group.

Try instead e.g. [comp.programmin g].

I believe that technically you are correct that is is not so
much a language issue as an OO one.

The classes are nonsense but are the typical example used
by many authors and instructors. I thought this would
be more familiar to readers than my current implementation.
So how does one implement (or not violate) the Dependency
Inversion principle without violating the encapsulation
by require details of external interfaces?

Use an abstract interface.
struct ICanvas
{
virtual void setPixel( Point const& pos, Color const& aColor = Color::black ) = 0;
};
struct Shape
{
virtual void drawAt( Point const& upperLeft, ICanvas& aCanvas ) = 0;
};

In your example, the Shape class still has a drawAt method.
If I want to store shapes into a database, then I would have
to change the Shape class and add a method for database
access:
enum Action_Type(DB_ STORE, DB_RETRIEVE, DB_SEARCH};

struct Shape /* or class */
{
virtual void draw(); // or drawAt
virtual void database(Action _Type);
};

In my application, a Reference Database System, references can
be created by Text_Stream, User_Interface and Database. In a
simple situation, the Text_Stream creates a reference subobject
(like book, magazine, newspaper, etc.) and returns a pointer
to the base class, "Reference" . The next step is to display
the object via the User_Interface. This is where the dilemma
begins. I would like to have each reference stored in a
different "view" (i.e. page, listbox, panel, etc.) based on
its kind (type). For example, all of the books would be
displayed together as will all the magazines.

The D.I.P. states that the objects should have a "display"
method. However, in order for the object to display its
data, it must know some details about the User_Interface.
Thus the violation of the Integration Separation Principle (ISP).

Although one idea is to create an interface class for
references with interactions with the User_Interface:
struct Reference
{
};

struct Reference_with_ UI
: public Reference
{
virtual void display(/*???*/);
};

struct Book
// : public Reference /* original inheritance */
: public Reference_with_ UI
{
virtual void display(/* ??? */);
}

The above implementation takes the interface out of the
base class, but the child classes still have to know
details about the User_Interface (such as which view
to display in).

Perhaps, as you suggested, I should move this over to
news:comp.progr amming or news:comp.objec t.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.l earn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 22 '05 #5
Jeffrey Schwab wrote:
Thomas Matthews wrote:
Hi,

According to Robert Martin's Dependency Inversion Principle,
http://www.objectmentor.com/resources/articles/dip.pdf,
when there is a need to test the type of an object, the
code inside the "switch cases" should be placed into the
parent class.

That's the traditional OO approach. Sometimes it's appropriate, but
often it's not.

Agreed. Sometimes pure OO is dificult.
However, I am finding that this conflicts with the other
principles -- the objects now must know details about
objects outside their own encapsulation.

For example, using the Shape class:
class Shape
{
virtual void draw() = 0;
};

class Square
: public Shape
{
void draw();
};

class Triangle
: public Shape
{
void draw();
};

The above "draw" methods must know something about the
external environment in order to draw their shape. I
believe this conflicts with the Integration Separation
Principle as well as the K.I.S.S. (Keep It Simple (and)
Stupid).

So how does one implement (or not violate) the Dependency
Inversion principle without violating the encapsulation
by require details of external interfaces?
Can one keep a Triangle simplified so it is just a
Triangle class?

Otherwise, one would have to keep modifying the base
Shape class everytime a new display device comes up.
{Or any other entity that would need to know the
type of shape}.

// Use overloaded functions.

namespace Shapes
{
class Shape { /* ... */ };
class Square: public Shape { /* ... */ };
class Triangle: public Shape { /* ... */ };
}

namespace Display
{
void draw( Shapes::Shape const& ) { /* ... * }
void draw( Shapes::Square const& ) { /* ... * }
void draw( Shapes::Triangl e const& ) { /* ... * }
}

Now the dilemma moves to the draw() function. The draw()
function needs to get the data from the Shape. Although
I do like this version better.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.l earn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 22 '05 #6
Thomas Matthews wrote:
The D.I.P. states that the objects should have a "display"
method. However, in order for the object to display its
data, it must know some details about the User_Interface.
Thus the violation of the Integration Separation Principle (ISP).


Not necessarily. By definition a "shape" is a displayable thing,
so it can certainly possess *some* knowledge about that. Ideally,
that knowledge should be very abstract and designed to work with
varying types of displays.

I think a good technique--which you've touched on already--is that
your draw methods take a parameter that is an interface to the
"canvas". By deriving from the "canvas" class, you can allow your
shapes to drawn on anything.

--
|_ CJSonnack <Ch***@Sonnack. com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ _______________ ____| Call: 1-800-DEV-NULL |
|______________ _______________ _______________ _|_____________ __________|
Jul 22 '05 #7
Thomas Matthews wrote:
Jeffrey Schwab wrote:
Thomas Matthews wrote:
Hi,

According to Robert Martin's Dependency Inversion Principle,
http://www.objectmentor.com/resources/articles/dip.pdf,
when there is a need to test the type of an object, the
code inside the "switch cases" should be placed into the
parent class.


That's the traditional OO approach. Sometimes it's appropriate, but
often it's not.


Agreed. Sometimes pure OO is dificult.
However, I am finding that this conflicts with the other
principles -- the objects now must know details about
objects outside their own encapsulation.

For example, using the Shape class:
class Shape
{
virtual void draw() = 0;
};

class Square
: public Shape
{
void draw();
};

class Triangle
: public Shape
{
void draw();
};

The above "draw" methods must know something about the
external environment in order to draw their shape. I
believe this conflicts with the Integration Separation
Principle as well as the K.I.S.S. (Keep It Simple (and)
Stupid).

So how does one implement (or not violate) the Dependency
Inversion principle without violating the encapsulation
by require details of external interfaces?
Can one keep a Triangle simplified so it is just a
Triangle class?

Otherwise, one would have to keep modifying the base
Shape class everytime a new display device comes up.
{Or any other entity that would need to know the
type of shape}.


// Use overloaded functions.

namespace Shapes
{
class Shape { /* ... */ };
class Square: public Shape { /* ... */ };
class Triangle: public Shape { /* ... */ };
}

namespace Display
{
void draw( Shapes::Shape const& ) { /* ... * }
void draw( Shapes::Square const& ) { /* ... * }
void draw( Shapes::Triangl e const& ) { /* ... * }
}

Now the dilemma moves to the draw() function. The draw()
function needs to get the data from the Shape. Although
I do like this version better.


The information needed by the display can be provided by accessors in
the Shape classes. If the information needed to display the objects
really should not be public, but is an implementation detail, then so is
the act of displaying. In that case, draw *should* be a member of the
original Shape classes.

-Jeff

Jul 22 '05 #8
> The above "draw" methods must know something about the
external environment in order to draw their shape. I
believe this conflicts with the Integration Separation
Principle as well as the K.I.S.S. (Keep It Simple (and)
Stupid).


The solution is that the draw method should draw to an
abstract device context. Thus you will not need to modify
any of the shape family of classes when a new display device
is introduced.

BTW, Here is another article on the Dependency Inversion Principle:
http://www.eventhelix.com/RealtimeMa..._principle.htm

Sandeep
--
http://www.EventHelix.com/EventStudio
EventStudio 2.0 - Generate Sequence Diagrams and Use Case Diagrams in
PDF
Jul 22 '05 #9
EventHelix.com wrote:
The above "draw" methods must know something about the
external environment in order to draw their shape. I
believe this conflicts with the Integration Separation
Principle as well as the K.I.S.S. (Keep It Simple (and)
Stupid).
The solution


/A/ solution. ;)
is that the draw method should draw to an
abstract device context. Thus you will not need to modify
any of the shape family of classes when a new display device
is introduced.

BTW, Here is another article on the Dependency Inversion Principle:
http://www.eventhelix.com/RealtimeMa..._principle.htm

Sandeep
--
http://www.EventHelix.com/EventStudio
EventStudio 2.0 - Generate Sequence Diagrams and Use Case Diagrams in
PDF


Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
12580
by: Ken | last post by:
Hi. Can anyone refer me to any articles about the compatibility between c++ polymorphism and real-time programming? I'm currently on a real-time c++ project, and we're having a discussion about whether we should allow polymorphism. Our system is not embedded and does not need to be as real-time as, say, a pacemaker. But it does involve updating displays based on radar input. So a need for something close to real-time is desired...
3
7202
by: DJTN | last post by:
I'm getting the following error when I try to compile my setup project in VS 2002. I have re-installed the .net framework 1.1 and it didnt solve the problem. WARNING: Unable to find dependency 'mscorlib' (Signature='B77A5C561934E089' Version='1.0.5000.0') of assembly 'System.dll' WARNING: Unable to find dependency 'mscorlib' (Signature='B77A5C561934E089' Version='1.0.5000.0') of assembly 'System.Windows.Forms.dll' WARNING: Unable to...
2
2621
by: Tanari | last post by:
I'm interested in learning about using Context Inversion of Control in c++, but all of the examples I can find use C# or Java. Can someone direct me to an example of Context IoC written in C++? Thank-you. http://www.gotw.ca/resources/clcm.htm for info about ]
14
2982
by: pamelafluente | last post by:
Hi guys, I have a hard problem :) I have the following situation: <span onmouseover = "SelectionEffect()"> <div style="width: 50px; height: 50px; background-color:#FFE4E1"></div> </span>
3
427
by: lancered | last post by:
Hi dear all, I am using Python2.4.2+NumPy1.0.1 to deal with a parameter estimation problem with the least square methods. During the calculations, I use NumPy package to deal with matrix operations, mostly matrix inversion and trasposition. The dimentions of the matrices used are about 29x19,19x19 and 29x29. During the calculation, I noticed an apparent error of inverion of a 19x19 matrix. Denote this matrix as KK, U=KK^ -1, I found...
2
2131
by: sweetchuck74 | last post by:
Nowadays, DI (Dependency Inversion) is one of the widely used design pattern. It provides several benefits, such as (1) loose coupling between component (2) effective and easy testing (component testing or unit testing) What are the drawbacks or disadvantages of using DI? Thank you very much for your answer in advance.
3
4968
by: PeteJ | last post by:
Hello all.. I wrote code in C to invert n x n matrices, where 1<n<39 and the matrices are guaranteed to be invertible. Prior to this task, I haven't really seen linear algebra since my sophmore year of undergrad, but I believe my algorithm implements Gaussian elimination. I append an identity matrix to the right of the one I wish to invert, use row addition to first turn the lower matrix to zeroes and then turn the upper matrix to zeroes, and...
5
2089
by: jayagowri | last post by:
Can anyone explain me the concept of inversion of control in spring pls
3
2000
by: Danno | last post by:
Just that simple question....out of curiosity.
0
8428
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8851
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8754
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8630
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7362
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5650
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4177
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4343
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
1984
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.