Solved

OOP design. Tree of classes containing classes containing classes...

Posted on 2014-03-29
7
266 Views
Last Modified: 2014-04-07
I'm tinkering with developing a Model-View-Controller design of classes. I've ended up with something like this:
        +--------Machine-------+
        v                      v
      Model                Controller
        |                      |
   +----+-----+           +----+--------+
   |          |           |             |
   v          v           v             v
 ModelA    ModelB    ControllerX   ControllerY
 data1      data2

Open in new window

Now suppose ControllerY wants to fetch data1 and data2. I could pass Machine down to ControllerY, then ControllerY could call
Machine->Model->ModelA->data1

Open in new window

to fetch the data. However, now I have a fragile design, where I can't make any changes to the overall structure of the Model, because Controller relies on that structure being there.

So I thought, "Maybe Controller should just pass data1 to ControllerY, since that's what it really needs. ControllerY doesn't really need the entire Machine class, it just needs data1. That should make it easier to test, as I don't have to instantiate an entire Machine class (which ironically contains ControllerY) and pass it to ControllerY in order to test it."

However, I came up with a problem in how to do this.

When I instantiate my Machine class, a whole cascade of class creation happens, because Machine has a Model class and a Controller class, which it instantiates; the Model class has a ModelA class and a ModelB class, which it instantiates; then the Controller class has a ControllerX and ControllerY class, which it instantiates.

And I'm supposed to initialize all this in the constructors, using constructor initialization lists. I don't see how in the Controller constructor initialization list, to extract and pass data1 to ControllerY constructor.

I could probably figure out how to move the extraction of data1 from Machine up to Controller, maybe something like this:
private:
Machine& machine;
Data1 data1;
Controller::Controller(Machine& m) : machine(m), data1(machine.Controller.data1)
{
}

Open in new window

(The syntax probably isn't quite correct, but the general idea is to extract it in the initialization list. Then I can pass it on to ControllerX when it gets instantiated.)

I've discovered constructor initialization lists are difficult to debug. There's nowhere to set a breakpoint. It all happens at once. And a whole cascade of classes being constructed all at once using initialization lists quickly becomes a big problem to debug. Especially if I anticipate making any changes in the future, I foresee endless frustration debugging the creation of these classes.

I'm trying to avoid using new to create classes, because this isn't managed code.


So how do I avoid this problem at the design stage? What trick or design pattern am I missing?
0
Comment
Question by:deleyd
  • 4
  • 3
7 Comments
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 500 total points
ID: 39966417
probably you should reconsider the hierarchy tree.

I would do

machine is parent of controllers. controller is parent of models. model is parent of views.

each level may have a baseclass  (for example model baseclass) where you could have data and functions common to all derived classes of that level.

each parent class holds a container with baseclass pointers of its child level. so you easily can get all models to a container and can go further by means of virtual calls.


I'm trying to avoid using new to create classes, because this isn't managed code.
the 'new' in managed code and 'new' in (unmanaged) c++ have little in common. while in c++ you would create a pointer pointing to allocated heap space (and have to care for freeing the dynamic space after use and not use the pointer after freeing)  the managed c++ would do all this management for you. storing baseclass pointers in a container is the only way to have a dynamic list of child objects which may be different derived classes.

to encapsulate the 'new' on these objects you may think of using the factory pattern to create child objects by name rather than by class.

Sara
0
 

Author Comment

by:deleyd
ID: 39967944
Is that the same as Model-View-Presenter?
0
 

Author Comment

by:deleyd
ID: 39968000
As I play with my class diagram, moving to Machine -> Controller -> Model -> View,

well now I have Model controlling the View with no Controller in between.


It also hearkens back to an older question I had, which was, if I'm displaying a Menu, does the data for the Menu go in the Model?

The Menu is dependent on the screen size, and Model isn't supposed to know about the View, so Menu text doesn't go in the Model.

Likewise, Menu text doesn't go in the View, because then I have a thick View.

It was suggested to me that Menu text actually should go in the Controller.


(Are there any examples of an actual C++ OOP MVC design? (Or MVP, or anything good?))
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 500 total points
ID: 39969020
Is that the same as Model-View-Presenter?

no, as far as I know, the presenter is responsible to show data in a suitable way for a specific output device, for example for monitor, notebook, smartphone.

well now I have Model controlling the View with no Controller in between.
it depends on the tasks for the controller if that is right. you also could make the controller manage both models and views. I also know architectures where the controller(s) only manage(s) all views and has no relation to the model. if you have a controller that was responsible to synchronize models, it would be parent of models.

displaying a Menu, does the data for the Menu go in the Model?
normally menu texts are coming from resources which were loaded in the presentation layer, what is the view. resources give a means to support difference languages. if your controller is an ui controller it could have an own frame and menus which are independent on the views. then, the controller would provide the texts (or load from resources). the model would not care for menus beside of menus which contain data, for example the recent files list.

Sara
0
 

Author Comment

by:deleyd
ID: 39972418
I just read some articles on the "DCI" Data Context Interaction design pattern. Didn't fully understand the proposed solution of "injecting" code into classes.

I do see the problem is somewhere needs to go the code that handles interaction between two classes. I thought that's what the Controller was for.

Have you heard of this DCI idea?
0
 
LVL 32

Accepted Solution

by:
sarabande earned 500 total points
ID: 39973116
Have you heard of this DCI idea?
no, not as a design pattern. I read an article about it, though.

but the idea of designing roles and interactions as classes, is a often used design. the problem with such "abstract" objects often is that differently to real objects (for example model, view) it is difficult to have a common agreement on them.

I thought that's what the Controller was for. 

Open in new window

no, for your task an ui controller would be responsible for displaying both the caller view and the target view at one screen. it also might be responsible to pass user input to the current active view.

an interaction object would be if you move data from model1 to model2 using the view1 and show the results both in view1 and view2. you could implement this as a function of the controller, using functions of the views and models. in the dci you would have a interaction object which lives only for the one transaction and would do the job. I know the design for server-client interactions, where it is a valid design pattern.

Sara
0
 

Author Closing Comment

by:deleyd
ID: 39984284
I guess there's no "correct" way of doing it. I like the idea of reorganizing the hierarchy of classes.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now