Java Forum / General / June 2007
Design Question for Model and View
Jason Cavett - 30 May 2007 20:40 GMT I have a question about a design for a model/view and communication between the two.
I have a model (MainModel) that holds a Collection of project objects. It keeps track of which projects are open, what the current project is, it initializes projects and saves projects. I have a view to this model which provides me access to these various tasks. (The MainModel can have multiple projects open at a time. These projects are shown in the view.) The view is an Observer of the MainModel. This all works great.
The problem I run into (sort of a problem - I can easily hack around it, but I'm wondering if there's a better way) is that it can be tough getting information from the user when I need to accomplish a goal. For example, if I'm closing an open project, the user selects "close" in the MainView. Here is how I think it should happen - if there's a better way, please let me know.
1. The user selects "Close Project" 2. The view (which knows about the model) calls "model.close()" 3. The model checks to see if the project is saved. If it's not saved, the model notifies that view that it needs to ask the user if they want to save before they close. 4. [TRICKY PART] - The view pops up a JOptionPane and asks the user if they want to save. The user selects "Yes" The view sets a flag in the main model notifying that it should save. 5. The model continues, sees the flag has been set to "true" and saves, then proceeds to close the project.
Is this a good way to go about it? It just seems to me that there could be a lot of flags floating about if I start doing more within the MainModel.
Thanks
Kai Schwebke - 30 May 2007 21:08 GMT > For example, if I'm closing an open project, the user selects "close" > in the MainView. Here is how I think it should happen - if there's a > better way, please let me know. here's my suggestion:
1. The user selects "Close Project"
2. The view (which knows about the model) checks the isSaved-property of the model. If the model is not saved, the view asks the user if they want to save before they close. If the users selects "Yes" the view calls the models save method.
3. The view calls "model.close()",
> Is this a good way to go about it? It just seems to me that there > could be a lot of flags floating about if I start doing more within > the MainModel. By shifting the control to the view the flags and callbacks can be avoided in this case.
Kai
Lew - 30 May 2007 23:08 GMT > By shifting the control to the view[,] the flags and callbacks > can be avoided in this case. This is a very good principle to enforce between two components - distinguish the initiator ("client") from the responder ("server"), in your case the view and the model, respectively.
The responder should not initiate, thus the initiator need never respond.
The initiator asks the responder if it's "saved". Based on the answer, the initiator might solicit information from the user. Based on that answer, the initiator might ask the responder to save the data. After all that, the initiator asks the responder to close (something).
This pattern avoids a lot of deadlock and complexity, and has surprisingly wide applicability.
 Signature Lew
Jason Cavett - 31 May 2007 15:30 GMT > > By shifting the control to the view[,] the flags and callbacks > > can be avoided in this case. [quoted text clipped - 15 lines] > -- > Lew Okay - this is primarily what I was wondering. The client/server (or initiator/responder) model seems a lot less complex as opposed to pure MVC.
Thanks
Lew - 31 May 2007 18:51 GMT > The client/server (or > initiator/responder) model seems a lot less complex as opposed to pure > MVC. The statement makes no sense. There is no correlation or conflict - one would implement MVC using components that follow an initiator-responder pattern. Or not. One could also implement a non-MVC solution using an initiator-responder pattern. Or not.
And what do you mean by "pure" MVC? How does it relate to this discussion?
I would recommend the architectural model of MVC, or one of its close relatives. It makes for a maintainable, stable product.
What complexity do you fear? Is avoiding it worth compromising the maintainability and stability of the product?
 Signature Lew
Jason Cavett - 01 Jun 2007 13:44 GMT > > The client/server (or > > initiator/responder) model seems a lot less complex as opposed to pure [quoted text clipped - 15 lines] > -- > Lew See Stefan's post. The strikes me more as a pure MVC solution due to the fact that the model is doing everything and the view is *only* being a view for the model. (AKA - The view will have no logic whatsoever.)
For example, in "non-pure" MVC...
The view asks the user, "This project is not saved. Do you want to save?" The user selects an answer. The view checks the answer and based on the answer tells the model what to do.
In "pure" MVC.
The view asks the user, "This project is not saved. Do you want to save?" The user selects and answer. The view sends the answer to the model. The model checks the answer and, based on the answer, performs the action.
I'm guessing a separate controller may be applicable here, but I don't see a *huge* need for a separate controller. As I stated in my post below - I'm always confused how the controller fits into everything. I've researched a bit online, but other people seem to have different thoughts on how it fits in as well.
Lew - 01 Jun 2007 15:13 GMT > The strikes me more as a pure MVC solution due to > the fact that the model is doing everything and the view is *only* [quoted text clipped - 5 lines] > The view asks the user, "This project is not saved. Do you want to > save?" No - that is not MVC. How would the view know the project is not saved? It has to ask the model if the project is saved.
> The user selects an answer. > The view checks the answer and based on the answer tells the model [quoted text clipped - 4 lines] > The view asks the user, "This project is not saved. Do you want to > save?" No - that is not MVC. How would the view know the project is not saved? It has to ask the model if the project is saved.
> The user selects and answer. > The view sends the answer to the model. > The model checks the answer and, based on the answer, performs the > action. What you call "pure" MVC is less conformant to the MVC pattern. In what you call "pure" the model interprets the answer, but the answer is a view artifact. Having the view interpret the answer and direct the model is more "pure".
> I'm guessing a separate controller may be applicable here, but I don't > see a *huge* need for a separate controller. As I stated in my post > below - I'm always confused how the controller fits into everything. > I've researched a bit online, but other people seem to have different > thoughts on how it fits in as well. The controller receives the request directly, parses it enough to determine which logic applies, sends the request data (possibly parsed first) to the appropriate model logic. Based on a result condition from the model, it selects the next view.
Another term for the controller is the "dispatcher". Think of a taxi service - the dispatcher doesn't drive the cars, they select the next, nearest available service component (taxi) to handle the request. To have the view (telephone) interact directly with individual taxis would be horridly inefficient - you could have dozens of calls go to one taxi and none to any of the others.
The dispatcher needs some knowledge of the model (available vehicles) to determine that you are asking for a limousine that seats eight, not a Mini that seats barely two.
If you send directly to a "logic" component you lose flexibility in the face of view evolution. (Taxi service via internet - now every cab needs a 'net connection, unless you have a dispatcher.)
There is no "pure" version of any of these implementations. There will always be boundary layers between model and controller and between view and controller. The controller will do some things that arguably belong in the view, and it will do some things that arguably belong in the model. It's part of what makes programming more an art than a science.
 Signature Lew
Jason Cavett - 01 Jun 2007 17:39 GMT > > The strikes me more as a pure MVC solution due to > > the fact that the model is doing everything and the view is *only* [quoted text clipped - 65 lines] > -- > Lew Thank you for your explanations. It cleared up a lot.
One last question - a controller doesn't necessarily have to be a separate class, does it? Can it be part of (from a class perspective - not a logical one) the model or view - especially if it doesn't do a whole lot?
Thanks again, Lew. Lots of great information.
Lew - 01 Jun 2007 18:09 GMT > One last question - a controller doesn't necessarily have to be a > separate class, does it? Can it be part of (from a class perspective > - not a logical one) the model or view - especially if it doesn't do a > whole lot? You should be more precise in terminology. Let me rephrase your question; you tell me if I did it wrong: "Does one need to implement the controller in a separate component from the view or model?"
The "controller" is a concept. As such, it is distinct from the "model" and "view" irrespective of implementation.
<http://en.wikipedia.org/wiki/Model-view-controller> many of the links at the bottom of that page address your specific questions.
Google on "model-view-controller". There are many variants on the theme. One, whose name escapes me and I just plain don't feel like doing all the googling here, represents fractally more detailed controllers each with its own mini- (micro-, pico-, femto-, ...) MVC loop.
Marty Hall [1] suggests implementing the controller as a distinct method in a backing bean, if you're programming for JSF [2]. Other parts of the bean implement the model, or part of it. I've done that; I've also implemented controller functionality in a separate class, or even several separate classes, using JSF.
Struts [3] uses a separate controller servlet that the application programmer treats as a black box. Each Action class in Struts implements a method such as execute() to handle the action for a screen. That method is the controller for that screen. Or is it the logic? It's a floor wax /and/ a delicious dessert topping!
Notes: [1] <http://www.coreservlets.com/JSF-Tutorial/> [2] <http://java.sun.com/javaee/5/docs/tutorial/doc/JSFIntro.html#wp114889> <http://myfaces.apache.org/> [3] <http://struts.apache.org/>
 Signature Lew
Jason Cavett - 01 Jun 2007 18:36 GMT > > One last question - a controller doesn't necessarily have to be a > > separate class, does it? Can it be part of (from a class perspective [quoted text clipped - 36 lines] > -- > Lew Haha, thanks for all the links. Don't worry - I've been Googling a lot to make sure I understand it. Unfortunately, there's so much information out there, and not everybody understands MVC the same way, that it can get confusing.
I've been reading in the wikipedia site. Thanks for the other information.
Stefan Ram - 30 May 2007 21:24 GMT >The problem I run into (sort of a problem - I can easily hack around >it, but I'm wondering if there's a better way) is that it can be tough >getting information from the user when I need to accomplish a goal. For example, a model operation might need a yes/no-information.
According to MVC, the model then would change a variable »information_required« to be »true«. The View would be subscribed to this as an observer and, thus, become notified of the need. The view will create a yes/no-requester visible to the user.
When the user decides to supply the information, the controller will tell the model, which then will set »information_required« to »false«, which will make the view to close the requester.
>the model notifies that view The model must not know that there is a view, otherwise it would be coupled to the view in a way that is not intended in MVC.
It only knows that there are observers, so it ... (see above)
>The view sets a flag in the main model notifying that it should >save. In MVC, this would be the part of the »controller«.
But then, maybe you did not want to use MVC at all.
>Is this a good way to go about it? I can not determine, whether a strict and pure application of MVC is advantageous in your case. I just wrote /how/ to do it /if/ one wanted to do this.
Things might be simplified by a kind of »hierarchical MVC«, where the confirmation-logic is contained entirely in the View of the outer MVC, while it consists of an internal MVC structure itself.
Jason Cavett - 31 May 2007 15:32 GMT > >The problem I run into (sort of a problem - I can easily hack around > >it, but I'm wondering if there's a better way) is that it can be tough [quoted text clipped - 38 lines] > of the outer MVC, while it consists of an internal MVC > structure itself.
>From a theoretical standpoint, this seems to be the best way to do this. At the same time, it seems overly complicated. I could easily implement something like this as the foundation for MVC is already there. I'm just wondernig if this would be the best idea.
Also - the controller - that doesn't necessarily have to be a separate class, does it? (I didn't think so, but I always get a bit confused on the actual layout of the model, view and controller. It seems other people do as well.)
Thanks
Eric Sosman - 30 May 2007 22:42 GMT Jason Cavett wrote On 05/30/07 15:40,:
> I have a question about a design for a model/view and communication > between the two. [quoted text clipped - 28 lines] > could be a lot of flags floating about if I start doing more within > the MainModel. There are a lot of ways to approach this. Since your model apparently knows that it has been changed since last being saved, it could publish that knowledge. The view could call model.hasUnsavedChanges() to decide whether it should get the user's permission before calling model.close().
A variant of the above is for the model to maintain a counter that increments each time a change is made, and to publish that counter via model.getVersion(). This lets a single model be seen by multiple views, each (perhaps) with its own backing store and its own notion of when things were last current.
Yet another scheme is to use model.closeIfUnchanged() and model.closeUnconditionally(). (model.close(boolean) seems less mnemonic.)
 Signature Eric.Sosman@sun.com
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|