Thinking about GUIs in terms of a 'Model-View-Controller' architecture is a flawed model for many problems. It all comes down to validation.
Consider this problem: I want to ask the user for four numbers, A,B,C and D such that A+B = C±2. D can be any number.
This has got to be as simple as GUI problems get, surely?
Firstly, I'm going to tell you that the GUI has to look like this:
You might suggest that I rework the GUI to ask for independent things, so ask for values for A, B and 'C-A-B', and report the value of C back to the user. In this case that would be possible, but that isn't a nice user interface, and I could give more complex examples where it isn't possible to do that at all. They might walk in a say 'I'd like to buy £1's worth of apples, please,' or maybe 'I'd like 1lb of apples, please'.
Ok, so lets consider all the possible things the user can put in those boxes:
They may enter a correct set of values
They may have entered numbers into all the boxes, but A+B isn't nearly equal to C
They may have entered '45foo' into box C, so we can't even start our validation.
They may have entered 'foo' into box D, but A=1; B=2; C=27, so our A+B=C validation rule fails.
Now consider some things we want to support:
Loading and saving
Undo
Display a pretty graphical representation of the setup, which is only possible when the form validates.
In the general case getting all the validation to pass may be tricky for a user. They surely want the support of undo while this is taking place. It would be nice if they could save where they were and show a friend it they got stuck.
Assuming we have a single underlying datamodel, the critical issue here is about what states we let the underlying data model get into. Most sane people wouldn't store the values as strings (unless they believe in XML...), which means that you can't click 'Save' when a box contains '45foo'. You might want undo to work for this series of operations though:
Set D to 'foo123'
Set C to '34'
Set A to '12'
Undo
If the undo history is in terms of the application Model, then undo will reverse all three operations in this case and only 1 operation in this case:
Set D to '123'
Set C to '34'
Set A to '12'
Undo
Hardly the expected result.
“Ah”, you say “The solution is to stop the user typing in invalid characters in the first place!” This, alas doesn't get us very far (imagine if I said that the numbers had to have 4 digits: how would delete work?). It doesn't even work in this case, since “-” isn't a number but “-1” is. Or consider entering a decimal number:
“1000.0” Oops meant to enter 10.000
“10.00.0” Insert
the new decimal point
“10.000” Remove the old one
Forcing the last two operations to be the other way round is not what the user would expect. How are they meant to find out why doesn't the dot key doesn't work?
Fundamentally, the idea of the GUI view being a true function of the underlying state (Model) is flawed, since it assumes that there is always a simple route to get from one valid state to another. In many cases this might involve changing two things at once (in the A+B=C case) or just put funny constraints on the way things are done, such as we saw in the decimal number editing case above.
My feeling is the answer is to consider the validation problem as constructing a series of successively more constrained representations of the state. Think about editing a program in your favourite language:
You start with a source file that is a list of Unicode code points. This gets converted to a sequence of tokens by the lexer, which then gets parsed, type checked, and linked. Every stage tries to build a higher level representation of the input, which can optionally fail.
But this model is totally different to MVC. In MVC the master representation is at the highest level of abstraction, and the views are derived from that. In a compiler the master representation is the lowest possible level of abstraction (a list of characters), and the high level representations needed for execution and compilation are created as necessary.
