Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > tightly coupled class design problem

Reply
Thread Tools

tightly coupled class design problem

 
 
Chocawok
Guest
Posts: n/a
 
      01-27-2006


Some of the classes in my app are graphical.

To encapsulate the graphical side of things I had created a class called
"sprite" which holds a bit map and knows how to draw itself etc.



The classes that are graphical contain a sprite object.



MyClass

{

private:

Sprite this_objects_sprite;

}





The sprite class requires a pointer to a "video surface". There is no way
around this. The pointer is required for the construction and drawing of the
sprite object.



My problem is this:



This design means that I have to pass the pointer to the video surface to
myclass in its constructor, e.g.



MyClass

{

private:

Sprite this_objects_sprite;



public:

MyClass(VideoSurface* s)

{

this_objects_sprite = new Sprite(VideoSurface* s);

...

...

}

....

....

}



Obviously this means all my graphical objects are tightly coupled to the
graphics system I am using. Also obviously (I think) is that this is
undesireable.



I was thinking of maybe arranging things so that the sprite is not
automatically instantiated in the container objects constructor.

That is, I construct my object THEN call a function to construct the objects
sprite, e.g.



MyClass c = new MyClass();

c.CreateSprite(VideoSurface* s);



But then this raised other issues like, how do I handle what happens if i
try to draw the object before creating its sprite.



Any thoughts on this?

Dean


 
Reply With Quote
 
 
 
 
Mike Wahler
Guest
Posts: n/a
 
      01-27-2006

"Chocawok" <> wrote in message
news:3NxCf.204940$ .uk...
>
>
> Some of the classes in my app are graphical.
>
> To encapsulate the graphical side of things I had created a class called
> "sprite" which holds a bit map and knows how to draw itself etc.
>
>
>
> The classes that are graphical contain a sprite object.
>
>
>
> MyClass
>
> {
>
> private:
>
> Sprite this_objects_sprite;
>
> }
>
>
>
>
>
> The sprite class requires a pointer to a "video surface". There is no way
> around this. The pointer is required for the construction and drawing of
> the sprite object.
>
>
>
> My problem is this:
>
>
>
> This design means that I have to pass the pointer to the video surface to
> myclass in its constructor, e.g.
>
>
>
> MyClass
>
> {
>
> private:
>
> Sprite this_objects_sprite;
>
>
>
> public:
>
> MyClass(VideoSurface* s)
>
> {
>
> this_objects_sprite = new Sprite(VideoSurface* s);
>
> ...
>
> ...
>
> }
>
> ...
>
> ...
>
> }
>
>
>
> Obviously this means all my graphical objects are tightly coupled to the
> graphics system I am using. Also obviously (I think) is that this is
> undesireable.
>
>
>
> I was thinking of maybe arranging things so that the sprite is not
> automatically instantiated in the container objects constructor.
>
> That is, I construct my object THEN call a function to construct the
> objects sprite, e.g.
>
>
>
> MyClass c = new MyClass();
>
> c.CreateSprite(VideoSurface* s);
>
>
>
> But then this raised other issues like, how do I handle what happens if i
> try to draw the object before creating its sprite.


A simple approach could be:

Continue to use a MyClass ctor (for all ctors) argument for your
pointer, but always give it a default value (e.g. 0). Then
have your draw functions check this pointer before using it.

-Mike


 
Reply With Quote
 
 
 
 
Jay Nabonne
Guest
Posts: n/a
 
      01-27-2006
On Fri, 27 Jan 2006 23:11:59 +0000, Chocawok wrote:

>

<snip>
>
> The classes that are graphical contain a sprite object.
>
>
>
> MyClass
>
> {
>
> private:
>
> Sprite this_objects_sprite;
>
> }
>
>
>
>
>
> The sprite class requires a pointer to a "video surface". There is no way
> around this.
> The pointer is required for the construction and drawing of the
> sprite object.
>
>


Question: when you say "There is no way around this.", do you mean that
the current class design requires it, or that some underlying issue
requires you to design the class this way? In other words, could you
change the Sprite class to not take the VideoSurface at construction time
but rather at draw time?

>
> My problem is this:
>
>
>
> This design means that I have to pass the pointer to the video surface to
> myclass in its constructor, e.g.
>
>
>
> MyClass
>
> {
>
> private:
>
> Sprite this_objects_sprite;
>
>
>
> public:
>
> MyClass(VideoSurface* s)
>
> {
>
> this_objects_sprite = new Sprite(VideoSurface* s);


This implies that "this_objects_sprite" is actually a "Sprite *" (not
"Sprite").

>
> ...
>
> ...
>
> }
>
> ...
>
> ...
>
> }
>
>
>
> Obviously this means all my graphical objects are tightly coupled to the
> graphics system I am using. Also obviously (I think) is that this is
> undesireable.
>
>
>
> I was thinking of maybe arranging things so that the sprite is not
> automatically instantiated in the container objects constructor.
>
> That is, I construct my object THEN call a function to construct the objects
> sprite, e.g.
>
>
>
> MyClass c = new MyClass();
>
> c.CreateSprite(VideoSurface* s);
>


That would work. If you can change Sprite's semantics, you could also
potentially still allow the construction of the sprite, but have an
"attach" method to later connect it to a video surface.

>
>
> But then this raised other issues like, how do I handle what happens if i
> try to draw the object before creating its sprite.


If the sprite member is a pointer, initialize it to 0 in the constructor
and check. Additionally, if somehow the "draw" method knows about the
video surface (e.g. it's passed as a parameter), you could create the
sprite the first time you try to draw if it hasn't been created yet.

- Jay

 
Reply With Quote
 
Daniel T.
Guest
Posts: n/a
 
      01-28-2006
In article <3NxCf.204940$> ,
"Chocawok" <> wrote:

> Obviously this means all my graphical objects are tightly coupled to the
> graphics system I am using. Also obviously (I think) is that this is
> undesireable.


The fact that you have a Sprite object contained within your MyClass
object is what is making it tightly coupled to the graphics system. If
you don't want that coupling, you need to abstract it out.

If you can't change the Sprite class, then you will have to use an
Adaptor.

class Image {
public:
virtual ~Image() { }
virtual void draw() = 0;
};

class SpriteAdaptor : public Image {
Sprite _sprite;
public:
SpriteAdaptor( VideoSurface* s ): _sprite( s ) { }
void draw() {
_sprite.draw();
}
};

class MyClass {
Image* _image;
public:
MyClass( Image* i ): _image( i ) { assert( i ); }
// call _image->draw() in some member-function
};

> I was thinking of maybe arranging things so that the sprite is not
> automatically instantiated in the container objects constructor.
>
> That is, I construct my object THEN call a function to construct the objects
> sprite, e.g.
>
>
>
> MyClass c = new MyClass();
>
> c.CreateSprite(VideoSurface* s);


You can do that, but the coupling still exists in that case. MyClass has
to include the Sprite header and possibly the VideoSurface header as
well.
 
Reply With Quote
 
davidrubin@warpmail.net
Guest
Posts: n/a
 
      01-28-2006

Chocawok wrote:
> Some of the classes in my app are graphical.
>
> To encapsulate the graphical side of things I had created a class called
> "sprite" which holds a bit map and knows how to draw itself etc.
>
>
>
> The classes that are graphical contain a sprite object.
>
>
>
> MyClass
>
> {
>
> private:
>
> Sprite this_objects_sprite;
>
> }
>
>
>
>
>
> The sprite class requires a pointer to a "video surface". There is no way
> around this. The pointer is required for the construction and drawing of the
> sprite object.
>
>
>
> My problem is this:
>
>
>
> This design means that I have to pass the pointer to the video surface to
> myclass in its constructor, e.g.


The broken part of this design is that Sprite "knows how to draw
itself", and hence must take a pointer to a Surface. Sprite sounds like
a value-semantic type to me, so what you need is a utility that draws
Sprites given a Sprite and a Surface:

class Sprite {...};

class MyObject {
Sprite d_sprite;
//...
public:
const Sprite& sprite() const { return d_sprite; }
};

struct DrawUtil {
static int draw(const Sprite& sprite, const Surface& surface);
};

 
Reply With Quote
 
Daniel T.
Guest
Posts: n/a
 
      01-28-2006
The following is a message I came across on comp.lang.c++, it sounded
like a good topic of discussion for comp.object as well, so I'm
forwarding it here...

========== Begin Forwarded Message ==========
From: "Chocawok" <>
Subject: tightly coupled class design problem
Date: Fri, Jan 27, 2006 6:11 PM

Some of the classes in my app are graphical.

To encapsulate the graphical side of things I had created a class called
"sprite" which holds a bit map and knows how to draw itself etc.



The classes that are graphical contain a sprite object.



MyClass

{

private:

Sprite this_objects_sprite;

}





The sprite class requires a pointer to a "video surface". There is no
way
around this. The pointer is required for the construction and drawing of
the
sprite object.



My problem is this:



This design means that I have to pass the pointer to the video surface
to
myclass in its constructor, e.g.



MyClass

{

private:

Sprite this_objects_sprite;



public:

MyClass(VideoSurface* s)

{

this_objects_sprite = new Sprite(VideoSurface*
s);

...

...

}

....

....

}



Obviously this means all my graphical objects are tightly coupled to the
graphics system I am using. Also obviously (I think) is that this is
undesireable.



I was thinking of maybe arranging things so that the sprite is not
automatically instantiated in the container objects constructor.

That is, I construct my object THEN call a function to construct the
objects
sprite, e.g.



MyClass c = new MyClass();

c.CreateSprite(VideoSurface* s);



But then this raised other issues like, how do I handle what happens if
i
try to draw the object before creating its sprite.



Any thoughts on this?

Dean
 
Reply With Quote
 
Moonlit
Guest
Posts: n/a
 
      01-28-2006
Hi,

Maybe you should abstract away the Graphics system as well as surfaces.

For instance assume Sprite should, for performance reasons, create some
surface in the graphics system (if that is possible for that graphics system
on GDI based system it would just use system memory).


For instance:
---------------------------------------------------------------------------------
#include <list>
using namespace std;

// Generic Class that holds a piece of memory to prepare sprite on (could be
located on the graphics card in system core or ....
class GRGB;
class GSprite;
class GSurface
{
private:
unsigned long Width,Height;
public:
GSurface( unsigned long Width, unsigned long Height ):
Width( Width ),
Height( Height )
{
}
// Draw
virtual void Prepare( unsigned long X, unsigned long Y, unsigned
long Width, GRGB *BunchOfRgbValues ) = 0;

};

class GGDISurface : public GSurface
{
public:
// New some memory from the heap on construction
GGDISurface( unsigned long Width, unsigned long Height ):
GSurface( Width, Height )

{
// Do stuff
}
// GDI Implementation draw on a piece of system memory, this is to
prepare the sprite
virtual void Prepare( unsigned long X, unsigned long Y, unsigned
long Width, GRGB *BunchOfRgbValues )
{
}
};

class GDirectXSurface : public GSurface
{
public:
// Get some memory from the graphics card on construction
GDirectXSurface( unsigned long Width, unsigned long Height ):
GSurface( Width, Height )
{}
// DirectX Implementation draw on the piece of memory on the
graphics card
virtual void Prepare( unsigned long X, unsigned long Y, unsigned
long Width, GRGB *BunchOfRgbValues )
{
}
};

class GGraphicsSystem
{
private:
std::list<GSprite*> SpriteList;
public:
virtual void AddSprite( GSprite *Sprite );
virtual GSurface *CreateSurface( unsigned long Width, unsigned long
Height ) = 0;
};

class GDirectXGraphicsSystem : public GGraphicsSystem
{
public:
GDirectXSurface *CreateSurface( unsigned long Width, unsigned long
Height )
{
}
};

class GSprite
{
private:
GSurface *Surface;
public:
GSprite( GGraphicsSystem * GraphicsSystem )
{
Surface = GraphicsSystem->CreateSurface( 200, 200 );
GRGB *Values;
Surface->Prepare( 10, 10, 100, Values );
}
// Called by graphic system when sprites need to be redrawn (to keep it
simple I assume the 'real' screen is also a surface
void Draw( GSurface *ScreenSurface )
{
// Draw myself GSurface should also contain some (virtual) methods to
draw GSurfaces on GSurfaces
}
};

int main( int ArgC, char *ArgV[] )
{
return 0;
}


Regards, Ron AF Greve

http://moonlit.xs4all.nl


"Chocawok" <> wrote in message
news:3NxCf.204940$ .uk...
>
>
> Some of the classes in my app are graphical.
>
> To encapsulate the graphical side of things I had created a class called
> "sprite" which holds a bit map and knows how to draw itself etc.
>
>
>
> The classes that are graphical contain a sprite object.
>
>
>
> MyClass
>
> {
>
> private:
>
> Sprite this_objects_sprite;
>
> }
>
>
>
>
>
> The sprite class requires a pointer to a "video surface". There is no way
> around this. The pointer is required for the construction and drawing of
> the sprite object.
>
>
>
> My problem is this:
>
>
>
> This design means that I have to pass the pointer to the video surface to
> myclass in its constructor, e.g.
>
>
>
> MyClass
>
> {
>
> private:
>
> Sprite this_objects_sprite;
>
>
>
> public:
>
> MyClass(VideoSurface* s)
>
> {
>
> this_objects_sprite = new Sprite(VideoSurface* s);
>
> ...
>
> ...
>
> }
>
> ...
>
> ...
>
> }
>
>
>
> Obviously this means all my graphical objects are tightly coupled to the
> graphics system I am using. Also obviously (I think) is that this is
> undesireable.
>
>
>
> I was thinking of maybe arranging things so that the sprite is not
> automatically instantiated in the container objects constructor.
>
> That is, I construct my object THEN call a function to construct the
> objects sprite, e.g.
>
>
>
> MyClass c = new MyClass();
>
> c.CreateSprite(VideoSurface* s);
>
>
>
> But then this raised other issues like, how do I handle what happens if i
> try to draw the object before creating its sprite.
>
>
>
> Any thoughts on this?
>
> Dean
>



 
Reply With Quote
 
Raghar
Guest
Posts: n/a
 
      01-28-2006
"Chocawok" <> wrote in
news:3NxCf.204940$ .uk:


>
> Some of the classes in my app are graphical.


Interesting, how could such ugly problem happen to them?

>
> To encapsulate the graphical side of things I had created a
> class called "sprite" which holds a bit map and knows how to
> draw itself etc.
>


It knows? And could it give that information to something that
is able to use it with knowledge how to talk to the graphic
device/s?

>
> The classes that are graphical contain a sprite object.


I hope quad/oct tree countains just pointers/references to
"sprite" / image/ managedImage objects.

> The sprite class requires a pointer to a "video surface".

There
> is no way around this. The pointer is required for the
> construction


Incorrect.

> and drawing of the sprite object.


If pointer to "drawing surface" / OGL is in different class,
that accepts "sprite" objects, then it's in the only place
where it need to be, in you case.


> This design means


Bad design. Imagine what would happen if that pointer would be
volatile.

> .........
> But then this raised other issues like, how do I handle what
> happens if i try to draw the object before creating its

sprite.
>


You have two possibilities. 1. Nothing. 2. Null pointer
exception.

 
Reply With Quote
 
unoriginal_username@yahoo.com
Guest
Posts: n/a
 
      01-28-2006
Chocawok wrote:
> Some of the classes in my app are graphical.
>
> To encapsulate the graphical side of things I had created a class called
> "sprite" which holds a bit map and knows how to draw itself etc.
>
> > MyClass


It seems that if some of your classes are inherently graphical, and
others are not, you can express this by synthesizing the types you need
using multiple inheritance:

class WithSprite : public MyClass, public Sprite
{
} ;

class WithoutSprite : public MyClass
{
} ;

Virtual functions (and perhaps another class) will allow you to deal
with differences between classes that are graphical and classes that
are not.

But again, all of this depends on your big picture.

-Le Chaud Lapin-

 
Reply With Quote
 
Chocawok
Guest
Posts: n/a
 
      01-28-2006
I think I have come to a decision.

I think the best solution is to have a Sprite class which handles the
graphics and drawing of itself.

BUT, and this is the new bit, construct the Sprite outside of the container
object. This way the containing object doesn't need to know ANY details of
how the sprite is constructed or how it draws iself.

e.g.

Sprite
{
bitmap i;
VideoSurface* drawingdestination;
Sprite(VideoSurface* s, bitmap b) { drawingdestination = s; i = b}
Draw();
}

MyClass
{
Sprite* s;
void MyClass();
void AttachSprite(Sprite* s) {this.s = s};
void Draw() {s.draw();}
}

main()
{
myobj = new MyClass();
myobj.AttachSprite(new Sprite(videoram, image));
myobj.Draw();
}

This means all the graphics details (DirectX or OpenGL or GDI etc) stay in
the one class, providing nice encapsulation.

I think i was getting confused, because I was trying to abstract away the
very fact that my objects have a graphical side to them. Which didn't make
any sense, because they are graphical in nature.

thanks very much for all your ideas.

Dean


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Class design with tightly bound iterator Jim Langston C++ 5 09-06-2007 05:31 AM
iterative algorithms + tightly coupled CPU with cloud of logic in FPGA wallge VHDL 2 01-05-2007 07:02 PM
Tightly Coupled Memories kishore.ln@gmail.com VHDL 2 10-30-2006 12:42 PM
VOIP Recommendations coupled with business DSL or business cable (Comcast)? mjb@jobsoft.com VOIP 5 07-31-2006 06:25 PM
CSS way to tightly right-align images? jersie0 HTML 6 11-16-2003 10:08 AM



Advertisments