473,232 Members | 1,480 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,232 software developers and data experts.

Creating and Maintaing Heavy and Light Versions of Classes

Hello

I have a library of calculationally intensive classes that is used both by a
GUI based authoring application and by a simpler non-interactive rendering
application. Both of these applications need to serialise the classes
to/from the same files but only the GUI app needs the full range of class
methods.

Now, the rendering app needs to be ported to multiple OS's but the GUI
doesn't. In order to reduce the time/cost of porting I'd like to create two
versions of the classes - one that only contains the data plus minimum
methods (mostly copy-construct plus serialisation and a few others) and one
with the full range of methods.

My initial thought was to define the simple classes as bases classes and
then derive the full classes from these. However, some of the base classes
would contain members which are themselves classes which need to be
simplified and if I converted these to the simpler classes then it's not
clear how I could recover the full functionality in the derived versions of
these. Hope that makes sense ;-)

Does anyone have any suggestions about how to handle this problem - would
templates be a way around, or maybe smart pointers?

Thanks
Jack

Jul 22 '05 #1
9 1609
"Jack" wrote...
Hello

I have a library of calculationally intensive
classes that is used both by a GUI based authoring
application and by a simpler non-interactive
rendering application. Both of these applications
need to serialise the classes to/from the same files
but only the GUI app needs the full range of class
methods.

Now, the rendering app needs to be ported to multiple
OS's but the GUI doesn't. In order to reduce the
time/cost of porting I'd like to create two versions
of the classes - one that only contains the data
plus minimum methods (mostly copy-construct plus
serialisation and a few others) and one with the full
range of methods.

My initial thought was to define the simple classes
as bases classes and then derive the full classes
from these. However, some of the base classes would
contain members which are themselves classes which
need to be simplified and if I converted these
to the simpler classes then it's not clear how I
could recover the full functionality in the derived
versions of these. Hope that makes sense ;-)

Does anyone have any suggestions about how to handle
this problem - would templates be a way around, or
maybe smart pointers?

Thanks Jack


It's hard to make a recommendation without more information, but I
don't think memory management is at the heart of your difficulties, so
I don't see how smart pointers help. Templates might be useful, but
it's hard to say without knowing the details of your classes.

I would just create two independent classes:

struct LightWidget { /*...*/ };

struct Widget
{
explicit Widget(const LightWidget&) { /*...*/ }
};

Use LightWidget when it's all you need (rendering) and create a full
Widget when you have to (GUI). Widget can either be initialized from
data in LightWidget or -- if your design permits -- Widget can store a
LightWidget object and build functionality on top of it, perhaps just
forwarding some common operations (like serialization).
Jul 22 '05 #2

"Derek" <no**@none.com> wrote in message
news:bt************@ID-46268.news.uni-berlin.de...

It's hard to make a recommendation without more information, but I
don't think memory management is at the heart of your difficulties, so
I don't see how smart pointers help. Templates might be useful, but
it's hard to say without knowing the details of your classes.

I would just create two independent classes:

struct LightWidget { /*...*/ };

struct Widget
{
explicit Widget(const LightWidget&) { /*...*/ }
};

Use LightWidget when it's all you need (rendering) and create a full
Widget when you have to (GUI). Widget can either be initialized from
data in LightWidget or -- if your design permits -- Widget can store a
LightWidget object and build functionality on top of it, perhaps just
forwarding some common operations (like serialization).


Thanks for taking the time...

The problem I have is that Widget itself contains a member of type SubWidget
which also needs to have a LightSubWidget counterpart. So the question is
how to create the Widget/SubWidget object from the
LightWidget/LightSubWidget object - in a way which is reliable and easy to
maintain.

So far the only simple way I can think of achieving this is to bracket all
the heavy code within #ifdefs and set a compiler directive appropriately. It
would be nice if there were some better mechanism for maintaining two
related sets of objects (in separate source files). But is there?

Thanks
Jack
Jul 22 '05 #3

Jack wrote:
....
Now, the rendering app needs to be ported to multiple OS's but the GUI
doesn't. In order to reduce the time/cost of porting I'd like to create two
versions of the classes - one that only contains the data plus minimum
methods (mostly copy-construct plus serialisation and a few others) and one
with the full range of methods.

....

Why not separate the GUI completely from your "data" classes ?

Robert
Jul 22 '05 #4
> "Jack" wrote:
It's hard to make a recommendation without more
information, but I don't think memory management is at
the heart of your difficulties, so I don't see how smart
pointers help. Templates might be useful, but it's hard
to say without knowing the details of your classes.

struct LightWidget { /*...*/ };

struct Widget
{
explicit Widget(const LightWidget&) { /*...*/ }
};

Use LightWidget when it's all you need (rendering) and
create a full Widget when you have to (GUI). Widget can
either be initialized from data in LightWidget or -- if
your design permits -- Widget can store a LightWidget
object and build functionality on top of it, perhaps just
forwarding some common operations (like serialization).
Thanks for taking the time...

The problem I have is that Widget itself contains a member
of type SubWidget which also needs to have a LightSubWidget
counterpart. So the question is how to create the
Widget/SubWidget object from the LightWidget/LightSubWidget
object - in a way which is reliable and easy to maintain.


You lost me. I don't see problem with reliability or easy of
maintenance if classes have a light core version and a heavier
decorator that adds functionality (and perhaps data), as long as one
can be converted to the other. In my mind the portable core code can
go in the core class and the uglier code that you don't want to port
can inhabit the heavyweight decorator class. If you do this for all
Widgets and SubWidgets, conversion should be straight forward.

But I don't have the whole picture, so I'm willing to take your word
that this approach won't work for you.
So far the only simple way I can think of achieving this
is to bracket all the heavy code within #ifdefs and set a
compiler directive appropriately. It would be nice if there
were some better mechanism for maintaining two related sets
of objects (in separate source files). But is there?

Thanks Jack


My approach requires some refactoring, which may require more effort
than you are able or willing to invest. But if you are using #ifdefs
to build two separate classes from the same source code, then I
suspect a redesign may be what is needed.

Jul 22 '05 #5

"Derek" <no**@none.com> wrote in message
news:bt************@ID-46268.news.uni-berlin.de...

You lost me. I don't see problem with reliability or easy of
maintenance if classes have a light core version and a heavier
decorator that adds functionality (and perhaps data), as long as one
can be converted to the other. In my mind the portable core code can
go in the core class and the uglier code that you don't want to port
can inhabit the heavyweight decorator class. If you do this for all
Widgets and SubWidgets, conversion should be straight forward.

But I don't have the whole picture, so I'm willing to take your word
that this approach won't work for you.

First off, thanks for your time.

Let me try to illustrate with some pseudo code...

First we have the core classes (I'm omitting LightSubWidget)

class LightWidget
{
public:
LightWidget();
LightWidget(const LightWidget& src);
LightWidget& operator=(const LightWidget& src);
void Serialize( CArchive& ar );
protected:
double m_data;
LightSubWidget m_sub;
};

These classes now have all the functionality needed by the render app.

And now I want to derive the main classes which need more functionality

class SubWidget : public LightSubWidget
{



So far the only simple way I can think of achieving this
is to bracket all the heavy code within #ifdefs and set a
compiler directive appropriately. It would be nice if there
were some better mechanism for maintaining two related sets
of objects (in separate source files). But is there?

Thanks Jack


// Lots of complicated stuff..
void calculate();
void doSomethingTricky();
}

So far so good, but now what about Widget itself?

I can't just have

class Widget : public LightWidget
{
// Lots of complicated stuff..

void useSubWidgets()
{
m_sub.calculate();
}

void useMoreSubWidgets()
{
m_sub.doSomethingTricky();
}
};

because in this case the new members are expecting m_sub to be of type
SubWidget and not LightSubWidget. I'd need to be forever casting m_sub from
LightSubWidget to SubWidget.

What I'd really like is a way of doing this implicitly.


My approach requires some refactoring, which may require more effort
than you are able or willing to invest. But if you are using #ifdefs
to build two separate classes from the same source code, then I
suspect a redesign may be what is needed.


I agree that #ifdefs doesn't feel right but it does at least get around the
problem of having to port a whole load of code that isn't actually used.

Thanks
Jack
Jul 22 '05 #6
[ Sorry, the previous post was a little screwed up - I've fixed it up below]
"Jack" <Ja**@nowhere.in.particular> wrote in message
news:bt**********@hercules.btinternet.com...

"Derek" <no**@none.com> wrote in message
news:bt************@ID-46268.news.uni-berlin.de...

You lost me. I don't see problem with reliability or easy of
maintenance if classes have a light core version and a heavier
decorator that adds functionality (and perhaps data), as long as one
can be converted to the other. In my mind the portable core code can
go in the core class and the uglier code that you don't want to port
can inhabit the heavyweight decorator class. If you do this for all
Widgets and SubWidgets, conversion should be straight forward.

But I don't have the whole picture, so I'm willing to take your word
that this approach won't work for you.

First off, thanks for your time.

Let me try to illustrate with some pseudo code...

First we have the core classes (I'm omitting LightSubWidget)

class LightWidget
{
public:
LightWidget();
LightWidget(const LightWidget& src);
LightWidget& operator=(const LightWidget& src);
void Serialize( CArchive& ar );
protected:
double m_data;
LightSubWidget m_sub;
};

These classes now have all the functionality needed by the render app.

And now I want to derive the main classes which need more functionality

class SubWidget : public LightSubWidget
{
// Lots of complicated stuff..
void calculate();
void doSomethingTricky();
}

So far so good, but now what about Widget itself?

I can't just have

class Widget : public LightWidget
{
// Lots of complicated stuff..

void useSubWidgets()
{
m_sub.calculate();
}

void useMoreSubWidgets()
{
m_sub.doSomethingTricky();
}
};

because in this case the new members are expecting m_sub to be of type
SubWidget and not LightSubWidget. I'd need to be forever casting m_sub

from LightSubWidget to SubWidget.

What I'd really like is a way of doing this implicitly.


My approach requires some refactoring, which may require more effort
than you are able or willing to invest. But if you are using #ifdefs
to build two separate classes from the same source code, then I
suspect a redesign may be what is needed.

I agree that #ifdefs doesn't feel right but it does at least get around

the problem of having to port a whole load of code that isn't actually used.

Thanks
Jack

Jul 22 '05 #7
Thinking a bit more about my problem, it seems to me that what I really need
is a mechanism for declaring data members as virtual in the same way as
member functions can be virtual.

So ideally it would be great if I could have

class LightWidget
{
public:
/* core stuff */

virtual LightSubWidget m_sub;
};
and then define

class Widget : public LightWidget
{
public:
/* tricky stuff */

virtual SubWidget m_sub;
};

But unfortunately that's not allowed

The best I can come up with is

class Widget :public LightWidget
{
public:
Widget() : m_subW ((SubWidget&)m_sub)) {};

/*tricky stuff

SubWidget& m_subW;
};

But would that have any unforeseen side-effects?

Thanks
Jack
Jul 22 '05 #8
On Wed, 07 Jan 2004 19:05:28 +0000, Jack wrote:
Hello

I have a library of calculationally intensive classes that is used both by a
GUI based authoring application and by a simpler non-interactive rendering
application. Both of these applications need to serialise the classes
to/from the same files but only the GUI app needs the full range of class
methods.

Now, the rendering app needs to be ported to multiple OS's but the GUI
doesn't. In order to reduce the time/cost of porting I'd like to create two
versions of the classes - one that only contains the data plus minimum
methods (mostly copy-construct plus serialisation and a few others) and one
with the full range of methods.

My initial thought was to define the simple classes as bases classes and
then derive the full classes from these. However, some of the base classes
would contain members which are themselves classes which need to be
simplified and if I converted these to the simpler classes then it's not
clear how I could recover the full functionality in the derived versions of
these. Hope that makes sense ;-)

Does anyone have any suggestions about how to handle this problem - would
templates be a way around, or maybe smart pointers?


I think what you need is the visitor design pattern. This allows you to
define extra operations (but not data!) on the classes in a simple way.
You would keep your classes simple, all the GUI stuff goes into visitors
and have to be included only in the GUI app.

This has the added benefit of decoupling your classes from the GUI used, a
worthwile aproach anyhow. It'll make porting the GUI easier as well.

If your full classes contain extra data, some simple macro's migth help.

#if defined(__Windows)
class GUIWidgetInfo { ... };
#elif defined(__SomeOtherWindowingSystem)
class GUIWidgetInfo { ... };
#elif defined(NOGUI)
class GUIWidgetInfo {};
#else
#error "No GUI defined"
#endif

class Widget {
GUIWidgetInfo gwi_;
...
};

But this is not very elegant. If nothing else, it couples GUI to non-GUI
data. If you need extra state to be kept you might create wrapper objects
that contain these basic objects and use a visitor to add functionality to
these basic objects.

HTH,
M4

Jul 22 '05 #9
On Thu, 8 Jan 2004 10:13:53 +0000 (UTC), "Jack"
<Ja**@nowhere.in.particular> wrote:

"Derek" <no**@none.com> wrote in message
news:bt************@ID-46268.news.uni-berlin.de...

You lost me. I don't see problem with reliability or easy of
maintenance if classes have a light core version and a heavier
decorator that adds functionality (and perhaps data), as long as one
can be converted to the other. In my mind the portable core code can
go in the core class and the uglier code that you don't want to port
can inhabit the heavyweight decorator class. If you do this for all
Widgets and SubWidgets, conversion should be straight forward.

But I don't have the whole picture, so I'm willing to take your word
that this approach won't work for you.

First off, thanks for your time.

Let me try to illustrate with some pseudo code...


Your problem seems to stem from closely coupling gui and non-gui code.

First we have the core classes (I'm omitting LightSubWidget)

class LightWidget
{
public:
LightWidget();
LightWidget(const LightWidget& src);
LightWidget& operator=(const LightWidget& src);
void Serialize( CArchive& ar );
protected:
double m_data;
LightSubWidget m_sub;
};
The above is all non-gui, so it isn't a "Widget". GUI and non-gui code
should be separated into separate classes and heirarchies. This is a
fundamental tenet of good OO GUI app design (model, view, controller,
etc.) The GUI code depends on the non-GUI code, but not vice-versa.
Instead, how about:

class Data //or Model?
{
public:
Data();
Data(const Data& src);
Data& operator=(const Data& src);
void Serialize( CArchive& ar );
protected:
double m_data;
SubData m_sub;
};

(obviously a better name is required)

These classes now have all the functionality needed by the render app.

And now I want to derive the main classes which need more functionality

class SubWidget : public LightSubWidget
{


Instead, how about:

class SubData
{
//...
};

class SubWidget
{
SubData* data; //can point to Data::m_sub if necessary
//...
};

class Widget
{
SubWidget* subwidget;
Data* data;
//...
};

Remember that inheritence should be a quite rarely used OO tool -
usually containment is far more appropriate. Reserve inheritence for
when you have polymorphic behaviour you want to change, by implenting
an abstract base class. Don't be afraid of writing forwarding
functions to contained objects where appropriate, since you end up
with much more flexible heirarchies that if you use inheritence.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #10

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

Similar topics

2
by: Matt | last post by:
I'm new to Java but experienced with PL/SQL. I've found what appears to be strange behaviour (a bug?) when attempting to create java stored objects using the UNIX version of Oracle SQL*PLUS...
2
by: T. Elsas | last post by:
Has anyone used MySQL in a public web site environment that receives 1 - 1.5 million sessions/day? Sessions are mostly content and light commerce. Site spikes to 3 million sessions/day about 4...
4
by: Altramagnus | last post by:
I have 30 - 40 type of different window. For each type I need about 20 instances of the window. When I try to create them, I get "Error creating window handle" My guess is there is a maximum...
26
by: Wouter van Teijlingen | last post by:
Dear Readers, This is my first post to this group. I was pointed to this group in a other vb group, so i have better luck here! For my learning curve of VB .NET i want to make a traffic...
5
by: Steve R. Hastings | last post by:
Hello. I have written a module called PyAtom. It is designed to make it really easy to create an Atom syndication feed. Atom is a format similar to RSS, but with some additional features. ...
25
by: John Salerno | last post by:
Just a quickie for today: Is it common (and also preferred, which are two different things!) to create a function that has the sole job of calling another function? Example: for fun and...
3
by: Imre | last post by:
Hi! I've got some questions regarding heavy use of virtual inheritance. First, let's see a theoretical situation, where I might feel tempted to use a lot of virtual inheritance. Let's...
26
by: nyathancha | last post by:
Hi, How Do I create an instance of a derived class from an instance of a base class, essentially wrapping up an existing base class with some additional functionality. The reason I need this is...
4
by: Henrik Dahl | last post by:
Hello! Is it possible to use Visual Studio 2005 or, secondarily, Visual Studio .NET 2003 to create ActiveX controls which may be consumed by VB 6.0 programs, i.e. dealt with on forms in the...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...

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.