views:

56

answers:

3

If from one view a user enters some invalid data, e.g.:

    E-mail: [email protected]    

then i want the controller to:

  • not place the data into the model
  • color the text box reddish
  • not allow the user to save

But it's possible that if the user enters the same invalid data in a different view i want the controller to:

  • place the data into the model
  • color the text box reddish
  • allow the user to save

But it's possible that if the user enters the same invalid data in a different view i want the controller to:

  • place the data into the model
  • color the text box bluish
  • allow the user to save

And it's possible that another view will:

  • place the data into the model
  • leave the text box uncolored
  • allow the user to save

And it's possible that another view will:

  • auto-correct the data, placing it into the model
  • color the text-box reddish
  • allow the user to have

And it's possible for another view to:

  • auto-correct the data, placing it into the model
  • update the view with the new data
  • color the text-box bluish
  • allow the user to save

[ad infinitum]

Without using n-controllers for n-views, how do i do this?


Update

i was about to ask a new question on stackoverflow, 'How do i have the controller change its behavior depending on the view." But then i realized that i have the exact same question title in use already.

Today's example:

  • If the entered data is too long for some parts of some of the database tables it will be going into, then perform validation and reject a save.

  • unless the data is coming from another view. In which case automatically trim certain fields to fit the database rules

  • unless the data is coming from another view. In which case, require the database to throw it's truncated exception

So many practical problems with MVC that i never see addressed in the books/articles/blogs i've read - it's no wonder i don't use it.

+1  A: 

The logic of what has to be done with each view must reside somewhere. I would recommend you empower the view with that information, instead of using multiple controllers, or creating some sort of mapping between view => configuration within a single controller.

I don't know what these views represent in terms of your domain, but it looks like the view seems to be commanding if invalid data can be saved into the model, if auto-correction is permitted, the visual indication for invalid data, etc. Why not empower the view with all that information?

Each of these views would have certain properties.

acceptsInvalidData => boolean, place invalid data to model
requiresAutoCorrection => boolean, auto-correct the data
synchronizeWithModel => boolean, always keep the view in sync with the model
allowsSavingInvalidData => boolean, allow saving of invalid data
invalidDataIndicator => string:color, how to color view for invalid data

Given these 5 properties (maybe missing one or two), the controller can initiate a sequence of actions that will uniquely handle each type of view. The view will have to expose himself or the properties to the controller.

Anurag
+1  A: 

Your examples can be somewhat generalized in the view as suggested, however, some use cases really ask for different controller imho. Also you might try add some logic in models. Colors are straight view thing, controllers should decide if it is reasonable to save the data in the models, if that data doesn't have some property deciding if it should be saved or not, let it on controllers, possible different ones. Auto-corrections should be in views and helpers. That is only my opinion.

Gabriel Ščerbák
A: 

To summarize the problem:

  1. It seems you want N different behaviors without having N controllers.

  2. You don't want to tightly couple the views and the controllers (no 1<->1 relationship), but the you want the controller to have strong and varied control over the behavior of each view.

Let me state this differently:

  1. It seems you want N different behaviors without having N objects.

  2. You don't want to tightly couple the A objects and B objects (no 1<->1 relationship), but the you want B object to have varied tight control over the behavior of each A object.

Here's how I see these 2 issues:

  1. This isn't a problem of MVC, its a classic software problem: you either need N objects to have N different behaviors, or you need to parameterize the behaviors so that you can distill out commonality (e.g. the approach Anurag suggested) to have less than N separate objects and/or resort to a giant case statement. :-)

  2. This one isn't a problem of MVC, but rather its one of the trade-offs. MVC has us decouple the M, V, and C code to ease future changes (e.g. changing or adding views). But the trade-off isn't free, the components necessarily have to have less knowledge and control of each other. Either you give up on the controller having tight control over the views (no N different kinds of behaviors) or you give on the segregation between the C and V (e.g. allow 1<->1 tightly coupled views-controllers).

Certainly, there has been great success with MVC in decoupling the Ms from the Vs and Cs, but less success in decoupling the Vs and Cs from each other. I think today's responsive interfaces call for coupling views and controllers, or started differently, its not worth the effort and complexity to strongly isolate views and controllers. This modified M(VC) approach has worked much better for me in the real world.

Bert F