C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

tightly coupled class design problem
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++)
View previous topic :: View next topic  
Author Message
Chocawok
Guest





PostPosted: Sat Jan 28, 2006 1:15 am    Post subject: tightly coupled class design problem Reply with quote



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
Back to top
Jay Nabonne
Guest





PostPosted: Sat Jan 28, 2006 1:15 am    Post subject: Re: tightly coupled class design problem Reply with quote



On Fri, 27 Jan 2006 23:11:59 +0000, Chocawok wrote:

Quote:

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?

Quote:

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").

Quote:

...

...

}

...

...

}



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.

Quote:


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
Back to top
Mike Wahler
Guest





PostPosted: Sat Jan 28, 2006 1:15 am    Post subject: Re: tightly coupled class design problem Reply with quote



"Chocawok" <nospam (AT) nospam (DOT) com> wrote in message
news:3NxCf.204940$D47.27169 (AT) fe3 (DOT) news.blueyonder.co.uk...
Quote:


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
Back to top
Guest






PostPosted: Sat Jan 28, 2006 10:33 am    Post subject: Re: tightly coupled class design problem Reply with quote

Chocawok wrote:
Quote:
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);
};
Back to top
Moonlit
Guest





PostPosted: Sat Jan 28, 2006 4:00 pm    Post subject: Re: tightly coupled class design problem Reply with quote

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" <nospam (AT) nospam (DOT) com> wrote in message
news:3NxCf.204940$D47.27169 (AT) fe3 (DOT) news.blueyonder.co.uk...
Quote:


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
Back to top
Daniel T.
Guest





PostPosted: Sat Jan 28, 2006 4:00 pm    Post subject: Re: tightly coupled class design problem Reply with quote

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" <nospam (AT) nospam (DOT) com>
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
Back to top
Raghar
Guest





PostPosted: Sat Jan 28, 2006 4:31 pm    Post subject: Re: tightly coupled class design problem Reply with quote

"Chocawok" <nospam (AT) nospam (DOT) com> wrote in
news:3NxCf.204940$D47.27169 (AT) fe3 (DOT) news.blueyonder.co.uk:


Quote:

Some of the classes in my app are graphical.

Interesting, how could such ugly problem happen to them?

Quote:

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?

Quote:

The classes that are graphical contain a sprite object.

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

Quote:
The sprite class requires a pointer to a "video surface".
There
is no way around this. The pointer is required for the
construction

Incorrect.

Quote:
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.


Quote:
This design means

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

Quote:
.........
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.
Back to top
Chocawok
Guest





PostPosted: Sat Jan 28, 2006 10:00 pm    Post subject: Re: tightly coupled class design problem Reply with quote

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
Back to top
Guest






PostPosted: Sat Jan 28, 2006 10:00 pm    Post subject: Re: tightly coupled class design problem Reply with quote

Chocawok wrote:
Quote:
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-
Back to top
I V
Guest





PostPosted: Sat Jan 28, 2006 11:00 pm    Post subject: Re: tightly coupled class design problem Reply with quote

Making the Sprite responsible for knowing what surface to draw itself
on looks like a good decision. However:

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

What happens if you call Draw on a MyClass object before you've called
AttachSprite? At the very least, MyClass::Draw needs to make sure it
has a valid sprite and take appropriate action (perhaps throw an
exception) if not.

However, that's not ideal, because this problem would only show up at
run time, and so you might miss it in your tests. If Draw is essential
to the function of MyClass, then a MyClass object is conceptually
incomplete without a Sprite, and that's a problem. All objects should
have all the information they need to function straight after they have
been constructed. So why not:

class MyClass
{
Sprite* sprite_;
public:
MyClass(Sprite* s)
: sprite_(s)
{ }

void draw()
{ s->draw(); }
};

This means you have to delay constructing the MyClass objects until you
can create the DrawingSurface and the Sprites; maybe that is difficult
for some reason, in which case you might have to go with your
AttachSprite method, but you should probably try and avoid that if you
can.

Quote:
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.

Yes, that sounds right.
Back to top
Guest






PostPosted: Sun Jan 29, 2006 12:00 am    Post subject: Re: tightly coupled class design problem Reply with quote

This is covered in a similar discussion here:
http://groups.google.com/group/comp.object/browse_thread/thread/d03f6621a23ff2c1/1e9631a3addff6f9#1e9631a3addff6f9

Just invert the control to the objects that contain the information and
it will be simple.
ie: Always ask the object with the information to do the work.

Rgs, James.
(http://www.jamesladdcode.com)
Back to top
JustBoo
Guest





PostPosted: Sun Jan 29, 2006 1:00 am    Post subject: Re: tightly coupled class design problem Reply with quote

On Sun, 29 Jan 2006 00:12:36 GMT, "Chocawok" <nospam (AT) nospam (DOT) com>
wrote:

Quote:
BTW, I'm not familiar with the syntax you've used in part of your code. I
presume:

MyClass(Sprite* s)
: sprite_(s)
{ }

does the same thing as:

MyClass(Sprite* s) { sprite_ = s};

Grab any good current book on C++ and read about the "Initialization
List."

Also the FAQ has a pretty bad article about it.
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6

Much Much Much Better Here:
http://www.goingware.com/tips/parameters/membervars.html

HTH - Good Luck
Back to top
Chocawok
Guest





PostPosted: Sun Jan 29, 2006 1:00 am    Post subject: Re: tightly coupled class design problem Reply with quote

Quote:
run time, and so you might miss it in your tests. If Draw is essential
to the function of MyClass, then a MyClass object is conceptually
incomplete without a Sprite, and that's a problem. All objects should
have all the information they need to function straight after they have
been constructed. So why not:

class MyClass
{
Sprite* sprite_;
public:
MyClass(Sprite* s)
: sprite_(s)
{ }

void draw()
{ s->draw(); }
};

This means you have to delay constructing the MyClass objects until you
can create the DrawingSurface and the Sprites; maybe that is difficult
for some reason, in which case you might have to go with your
AttachSprite method, but you should probably try and avoid that if you

I see your points and your right. Calling the constructor of MyClass with
the Sprite as a parameter seems the way to go.

Thanks for that.

BTW, I'm not familiar with the syntax you've used in part of your code. I
presume:

MyClass(Sprite* s)
: sprite_(s)
{ }


does the same thing as:

MyClass(Sprite* s) { sprite_ = s};


And one final thing, I notice you use an underscore in the sprite variable
name, "sprite_" and somewhere else in the thread someone used "_sprite". Is
there any convention being used here, and if so, what is it?

Thanks

Dean
Back to top
I V
Guest





PostPosted: Sun Jan 29, 2006 3:00 am    Post subject: Re: tightly coupled class design problem Reply with quote

Chocawok wrote:
Quote:
BTW, I'm not familiar with the syntax you've used in part of your code. I
presume:

MyClass(Sprite* s)
: sprite_(s)
{ }

does the same thing as:

MyClass(Sprite* s) { sprite_ = s};

Pretty much. There's a slightly subtle difference which is only likely
to be important if the member variable is itself an instance of a
class. Doing:

class MyClass
{
OtherClass other_;
public:
MyClass(OtherClass o)
{
other_ = o;
}
};

Calls the default constructor of OtherClass to create other_ , and then
the assignment operator to set other_ to o

Wheras:

MyClass(OtherClass o)
: other_(o)
{ }

doesn't call the default constructor of OtherClass, but calls the copy
constructor to make other_ be a copy of o. This may be significant if
the default constructor takes a long time, or if OtherClass doesn't
_have_ a default constructor. It's probably a good idea to use the
initializer list, as that makes it clear to people reading the source
that you are just initializing your members, rather than doing anything
else.

Quote:
And one final thing, I notice you use an underscore in the sprite variable
name, "sprite_" and somewhere else in the thread someone used "_sprite". Is
there any convention being used here, and if so, what is it?

It's a moderately common convention to mark member variables with an
underscore, either at the beginning or the end; some people use a
naming convention like m_member instead.
Back to top
Alf P. Steinbach
Guest





PostPosted: Sun Jan 29, 2006 3:00 am    Post subject: Re: tightly coupled class design problem Reply with quote

* JustBoo:
Quote:
On Sun, 29 Jan 2006 00:12:36 GMT, "Chocawok" <nospam (AT) nospam (DOT) com
wrote:

BTW, I'm not familiar with the syntax you've used in part of your code. I
presume:

MyClass(Sprite* s)
: sprite_(s)
{ }

does the same thing as:

MyClass(Sprite* s) { sprite_ = s};

Grab any good current book on C++ and read about the "Initialization
List."

Also the FAQ has a pretty bad article about it.
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6

What do you think is "bad"?


Quote:
Much Much Much Better Here:
http://www.goingware.com/tips/parameters/membervars.html

This article is sometimes misleading and incorrect.

Let's start with the very first sentence:

"Member variables must be initialized in the constructor's
initialization list."

That's false.

First part of sentence 2:

"Smart pointer members minimize dependencies"

That's generally false.

Second part of sentence 2:

"while allowing exception safety."

That's misleading: smart pointers don't just allow exception safety, and
their exception safety is not a secondary consideration.

Next follows a sub-heading:

"Minimize Dependencies by Storing Members as Pointers"

That's not bad advice, but there is no discussion of the trade-off
involved, notably efficiency.

First paragraph that section then says nothing remarkable, but is
followed by example code that won't compile. It's nothing dramatic (a
missing semicolon) but shows lack of attention to detail.

Then we get to a sub-sub-heading:

"The Initialization List"

and the first sentence of that section

"Note that it is terribly important that you initialize pointer
members (actually any member) of your objects in the constructor's
initialization list."

which is simply false, again. Some times (the FAQ lists some
situations) it's terribly important that you don't.

Third sentence of that section:

"If you don't always need to have a pointer member in existence during
the lifetime of your object, you may choose to initialize it to nil"

'nil' is Pascal terminology, there's no such thing in C++ (the author
probably means 0).

Ah, well, I'm not going to trash that article. As a motivational
article it's great. But as a technical resource it's not up to the
FAQ's standard of quality -- not even 10% in that direction.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.