A Design Problem

M

Mousam

Hi All,
First of all forgive me for the length of this post.

I am developing one library for some text editor. In this library
I want to provide a set of C++ classes which will enable client (of
the library) to add tool bars to the text editor. The requirements
are:

-> Client can add as many tool bars as he wants to add.
-> In each toolbar there will be some tools. Tools can be of button
type or list box type like in MS word a tool bar can contain either
buttons or list box (For simplicity consider these two types of tool
only).

I took following approach to design the solution of above problem.

-> There will be a class say ToolBarMgr which will manage the
collection of all tool bars.
-> There will be a class say ToolBar which will manage collection of
all tools of this toolbar. This class will also contain information
particular to a toolbar.

Now I am bit confused about the design of Tool class because there
will be several functionalities which will be valid for button type of
tool but does not make sense for list box type of tool and vice
versa. Say e.g button tool can have one API to change the image of
button but this API does not make any sense to have in list box tool.

There are two approaches which I can think of to design the Tool
class.

1st Approach:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-> There will be a class called Tool which will contain information
common to all type of tools. Say e,g it will contain toolbar ID to
which this tool is associated.
-> There will be two more classes say ButtonTool and ListBoxTool which
will inherit from Tool class and contain information specific to their
type.
-> Tool class will have all the methods which can be called on at
least one type of tool and have the default implementation which will
just throw some exception.
-> ButtonTool and ListBoxTool class will override their specific
methods.
-> In this approach if client calls a method which is invalid for this
tool object, he will get an exception.

Main Advantages of this approach:
->Client will always deal with Tool class. So, addition/deletion of
any tool type will not affect exisiting client code.

Main Disadvantages of this approach:
-> Methods which do not make sense to be defined for some classes
will still be inherited from Tool class. Say e.g API to change the
button image does not make sense to be in ListBoxTool class but still
this method will get inherit from Tool class.
-> Addition/Deletion of tool type class will mean to add/remove some
APIs from Tool class also.


2nd Approach:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-> There will be a class say Tool which itself will not be templatized
but will contain member templates similar to the class boost::any.
This class will contain information which will be common for all type
of tools. Also this class will contain the object of ButtonTool class
or ListBoxTool class or anything.
-> Tool class will also contain one method say GetObject() which will
also be templatized and will return the object it contains. Before
returning object the GetObject() method will make sure that it is
returning correct type of object. If it can not return correct type of
object it will throw some exception. So its implementation will be
something like this

template <typename ValueType>
ValueType* Tool::GetObject()
{
If(the ValueType typeid is same as that of type id of the
object Tool class contains)
{
return address of the object
}
else
{
throw some exception
}
}

-> So now if client is having object of the Tool class and if he knows
the exact type of tool; Tool class contains, he will call the
GetObject() method of the Tool class to get the exact type of tool
and then can call methods on that tool directly. But if the client
does not know the exact type of tool; Tool class contains, still he
can call the common methods (methods which are applicable to all type
of tools).

Main Advantages of this approach:
-> Addition/Deletion of tool type class will not affect any class in
the library. We just need to add new class for new tool type or
delete the existing class for that tool type.
-> Methods which are specific to a tool type will belong to its class
only which makes sense.

Main Disadvantages of this approach:
-> Addition/Deletion of tool type class may affect client code bcoz
now client code will deal with concrete classes.
-> I am using Visual Studio6 as my IDE which has lots of bugs with
the templates. So in some cases I have to use some ugly
workarounds.


It would be great if some one can please suggest me as to which
approach is better or can suggest me a new better approach.

Thanks a lot for your help and patience :)
 
D

Daniel Kraft

1st Approach:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-> There will be a class called Tool which will contain information
common to all type of tools. Say e,g it will contain toolbar ID to
which this tool is associated.
-> There will be two more classes say ButtonTool and ListBoxTool which
will inherit from Tool class and contain information specific to their
type.
-> Tool class will have all the methods which can be called on at
least one type of tool and have the default implementation which will
just throw some exception.
-> ButtonTool and ListBoxTool class will override their specific
methods.
-> In this approach if client calls a method which is invalid for this
tool object, he will get an exception.

Main Advantages of this approach:
->Client will always deal with Tool class. So, addition/deletion of
any tool type will not affect exisiting client code.

Main Disadvantages of this approach:
-> Methods which do not make sense to be defined for some classes
will still be inherited from Tool class. Say e.g API to change the
button image does not make sense to be in ListBoxTool class but still
this method will get inherit from Tool class.
-> Addition/Deletion of tool type class will mean to add/remove some
APIs from Tool class also.


2nd Approach:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-> There will be a class say Tool which itself will not be templatized
but will contain member templates similar to the class boost::any.
This class will contain information which will be common for all type
of tools. Also this class will contain the object of ButtonTool class
or ListBoxTool class or anything.
-> Tool class will also contain one method say GetObject() which will
also be templatized and will return the object it contains. Before
returning object the GetObject() method will make sure that it is
returning correct type of object. If it can not return correct type of
object it will throw some exception. So its implementation will be
something like this

template <typename ValueType>
ValueType* Tool::GetObject()
{
If(the ValueType typeid is same as that of type id of the
object Tool class contains)
{
return address of the object
}
else
{
throw some exception
}
}

-> So now if client is having object of the Tool class and if he knows
the exact type of tool; Tool class contains, he will call the
GetObject() method of the Tool class to get the exact type of tool
and then can call methods on that tool directly. But if the client
does not know the exact type of tool; Tool class contains, still he
can call the common methods (methods which are applicable to all type
of tools).

Main Advantages of this approach:
-> Addition/Deletion of tool type class will not affect any class in
the library. We just need to add new class for new tool type or
delete the existing class for that tool type.
-> Methods which are specific to a tool type will belong to its class
only which makes sense.

Main Disadvantages of this approach:
-> Addition/Deletion of tool type class may affect client code bcoz
now client code will deal with concrete classes.
-> I am using Visual Studio6 as my IDE which has lots of bugs with
the templates. So in some cases I have to use some ugly
workarounds.

I think I would use somewhat a combination of those two approaches:

Have a Tool class which only contains the common API and no methods
specific to a tool type; to access specific functionality, the client
could access the tool via Tool* and dynamic_cast it to the expected type.

Or, you could do a method like:

template<typename T>
T* getTool(int id)
{
Tool* tool(getToolById(id));
T* result(dynamic_cast<T*>(tool));
if(!result)
throw some exception;
return result;
}

Which seems to be similiar to approach 2 as I understood; this way, no
client code should be dependent on tool types it does not use but the
generic Tool class does not have APIs that do not make sense.

However, I'm not quite sure about that RTTI stuff--maybe this is
considered poor style/design or is even worse supported than templates are?

Yours,
Daniel
 
D

Daniel T.

Mousam said:
First of all forgive me for the length of this post.

The length is fine when the post is on topic. In this case, however, the
post is better suited to comp.object or one of the other design groups.
I am developing one library for some text editor. In this library
I want to provide a set of C++ classes which will enable client (of
the library) to add tool bars to the text editor.

I don't particularly care for either of the approaches you outline.
Now I am bit confused about the design of Tool class because there
will be several functionalities which will be valid for button type of
tool but does not make sense for list box type of tool and vice
versa. Say e.g button tool can have one API to change the image of
button but this API does not make any sense to have in list box tool.

The problem here is that you are thinking of the member-functions as
commands to order the Button or ListBox to do some specific thing.
Instead think of the member-functions as a way of informing the Button
or ListBox what is going on around it. Instead of "button.highlight()"
think of the reasons *why* the button would be highlighted and use those
for method names. Like "button.mouseDownAt( x, y )" Note, this function
(mouseDownAt) is also useful for ListBoxes.
 
M

Mousam

The length is fine when the post is on topic. In this case, however, the
post is better suited to comp.object or one of the other design groups.


I don't particularly care for either of the approaches you outline.


The problem here is that you are thinking of the member-functions as
commands to order the Button or ListBox to do some specific thing.
Instead think of the member-functions as a way of informing the Button
or ListBox what is going on around it. Instead of "button.highlight()"
think of the reasons *why* the button would be highlighted and use those
for method names. Like "button.mouseDownAt( x, y )" Note, this function
(mouseDownAt) is also useful for ListBoxes.

Thanks a lot Daniel Kraft and Daniel T for your kind suggestions. :)
 
M

Mousam

The length is fine when the post is on topic. In this case, however, the
post is better suited to comp.object or one of the other design groups.


I don't particularly care for either of the approaches you outline.


The problem here is that you are thinking of the member-functions as
commands to order the Button or ListBox to do some specific thing.
Instead think of the member-functions as a way of informing the Button
or ListBox what is going on around it. Instead of "button.highlight()"
think of the reasons *why* the button would be highlighted and use those
for method names. Like "button.mouseDownAt( x, y )" Note, this function
(mouseDownAt) is also useful for ListBoxes.

Hi Daniel T,
The problem here is that you are thinking of the member-functions as
commands to order the Button or ListBox to do some specific thing.
Instead think of the member-functions as a way of informing the Button
or ListBox what is going on around it. Instead of "button.highlight()"
think of the reasons *why* the button would be highlighted and use those
for method names. Like "button.mouseDownAt( x, y )" Note, this function
(mouseDownAt) is also useful for ListBoxes.

Unfortunately I can not think in this way because the set of
toolbar classes I want to design is
a wrapper over existing C APIs. So as a library designer I don't know
how and when the client will use functionality (API). e.g I have to
provide an API to change the image of the button, now its up to client
when he wants to change the button image on left mouse button down
event or on right mouse button down event or at some other time.
 
P

Puppet_Sock

It would be great if some one can please suggest me as to which
approach is better or can suggest me a new better approach.

Not going to do your design work for you. You need to get some
good texts on windows design and handling user input events.

Go here www.amazon.com and search for Petzold. Then go
here www.accu.org and look at some book reviews. (Though they
were not available just now. Hopefully that is short term.)
Socks
 
M

Mousam

Not going to do your design work for you. You need to get some
good texts on windows design and handling user input events.

Go herewww.amazon.comand search for Petzold. Then go
herewww.accu.organd look at some book reviews. (Though they
were not available just now. Hopefully that is short term.)
Socks

Hi,
Its not like I posted one problem and asked you guys to design it
for me. If you have read whole post I described two approaches and
asked for suggestion.

Thanks & Regards,
Mousam Dubey
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top