views:

90

answers:

3

Hello,

I am working on an application with a GUI using wxWidgets. I got an object used as a "model": its data has to be used to draw the ui and the ui should modify it. Let's call this class Model.

The structure of the applications looks like this:

A wxApp-derived object, that possesses:

  • a wxFrame-derived object, that possesses a wxGLCanvas-derived object.
  • another wxFrame-derived object.

For the Model class,

  1. I could use a singleton that would make things very simple: I could just use model.getThatData() or model.setThatData() anywhere.

    However, I can't disagree when people say that it's a global variable with a fancy dress.

  2. I could also use dependency injection (or is it something else): I instanciate Model in the wxApp object, and then I pass a reference to the instance model in the constructors of both wxFrame-derived classes, same thing with wxGLCanvas constructor, and I store the reference as an attribute of the needed classes.

    However, this doesn't seem either a very good solution. Suppose the first wxFrame object doesn't need to use model. We will nontheless have to pass a reference to model in its constructor to be able to pass it to the wxGLCanvas-derived object. So that design could lead to many (?) unnecessary passings.

  3. ?

What do you think ? I have been asking myself this question for a long time...

+1  A: 

However, this doesn't seem either a very good solution. Suppose the first wxFrame object doesn't need to use model. We will nontheless have to pass a reference to model in its constructor to be able to pass it to the wxGLCanvas-derived object. So that design could lead to many (?) unnecessary passings.

Passing pointers around is peanuts compared to the nightmares of untangling the dependencies between classes/objects, hidden in the implementation (== singletons).

The #2 is the way I do it. The goal is to be able just by looking at the class declaration to have an idea about the class prerequisites. Ideally, if in the context I have everything what c'tor/init method needs, I should be able to instantiate and use the object. That way the life-cycle also becomes clear: the prerequisites may not be released until the object is released.

Dummy00001
+1  A: 

Does the frame dependent on a specific canvas class? Or the canvas object interchangeable?

If the latter is the case, then the constructor for the frame should be parameterized by a reference to a canvas object. This way, the application will take care of instantiating the model, creating the canvas using said model, and passing the canvas to the frame. The frame will no more be dependent on the model directly.

If the frame is dependent on a specific canvas class (that is, the frame instantiates its own canvas, and knows what type of canvas it wants). Then if the canvas' constructor is dependent on the Model object, by proxy your frame is also dependent on the model. So #2 is correct.

Santa
The canvas inherits from the frame, so I can't invert things.I just found this interesting link: http://googletesting.blogspot.com/2008/10/dependency-injection-myth-reference.html
Klaus
That link more or less what I tried to said in my first suggestion, albeit with a more concrete example.I don't know what inheritance has to do with your problem. As stated, it seems to me that an application holds a reference to a frame, which holds a reference to a canvas. My first suggestion still stands.
Santa
Oh yeah, sorry :) I posted the link precisely because it was exactly what you said. Thank you !
Klaus
+1  A: 

Put it into a simple MVC model. (Recall that C interacts with M and V, and M and V do not interact with each other.)

Your model is (obviously) the "M" in MVC. Your widgets are the "V" in MVC.

See the problem here? You're trying to give the "M" to the "V"; you're missing the "C" to delegate everything. Your "C" may be your wxApp (it depends on how you want to design things).

In other words, the controller should give the data the view needs from the model to the view; the view shouldn't grab its own data directly from the model.

(Therefore, both of your proposals are, in my opinion, poor options in an MVC application.)

strager
Yes! The `wxApp`-derived class object (`c`) seem a good idead for the controller. wxApWxWidgets gives a `wxGetApp()` function that returns a reference to c everywhere, so that's perfect. Sorry if the following is silly, but I'm not familiar to the MVC model. So, I put my model m in C as an private attribute. Now, to get `f`, an attribute of the model, from the view, should I do a wrapper method like `c.getF()`, that would call `m.getF()` (=> much boring if I have to access many attributes) or could I have a `c.getM()` function (almost public, hmmm) ?
Klaus
@Klaus, Neither the "M" nor the "V" should know about the "C". The controller simply passes the V and M information and gets information back. The controller controls information flow; that's its job. If you're making the wxApp the controller, your view probably shouldn't be looking at wxApp (especially not to access model data).
strager
So I should give a `f` attribute to the view and make the controller update it according to its own `f` ? And when I want information from the view, use a `getViewVariable()` from the controller ?
Klaus
@Klaus, The view should have public fields/setters for all the information it needs to operate well. The controller passes the information into this field/setter. The view should also have public fields/getters for all the information it provides. The controller reads this information. For example, a text box may have a getText getter and setText setter, which allow a controller to manipulate the widget and get information it needs from the widget.
strager
Ok, thank you ! :)
Klaus