On the TestFirstUserInterfaces, MikeStallings? asks...
Let's say you have a nice separation between your business objects and the GUI, say perhaps TheHumbleDialogBox approach. Now you wish to implement form validation. You need immediate validation after each control is left, and want to set an error provider on the form beside the control. Sometimes you need to validate groups of controls, and you may need to set multiple error providers, or enable/disable buttons. How can the BusinessObjects [LogicLayer] know enough about the GUI and what the user is doing, and then give feedback to the view as to exactly which error providers to set?
It is clear that the GraphicalUserInterface must keep the BO informed after each and every control is left so that validation can occur, and that the BO must be able to associate a list of DotNetErrorProviders with a list of controls, so it can tell the GUI which ones to set. An Enum for each control?
Note sometimes you must validate each keystroke - if this is truly UserFriendly. A numbers-only field should simply ignore letters, for example.
JohnRoth then defines a RepresentationLayer:
Let's add one requirement to the mix: you need to be able to test the BusinessObject "as if" it was the actual GUI object, using a package such as FIT ( http://fit.c2.com ).
This means that each control in the GUI must have a one to one representation in the BusinessObject. I normally use the "CallDownNotifyUp?" layering pattern. That is, each widget in the GUI will call its own method in the BO, and each widget in the GUI will request that it be notified of events that interest it.
This way, the form is a relatively passive container for a cluster of relatively independent wigets. The only obvious place they cooperate is in sharing the status bar at the bottom of the window. That, of course, is boilerplate GUI logic.
Mikey likes it:
The answer which JohnRoth gave solves the whole problem, I think. When a property on the BO is set, the BO can perform as much validation as it wants, and can then send an event for each control, if necessary, telling it to set its error provider. Or to enable the Save button because all requirements have been met. Etc.
If you wanted to cheat, and you knew you would only be developing one view for the BO (YouArentGonnaNeedIt), then the BO could simply call methods back on the GUI, e.g.,
InvalidateStreetName(String msg)Interestingly, this is the opposite of the Humble Dialog, which asks the gui for data, instead of the gui directly setting properties in the BO.
We submit it's the opposite of Humble Dialog's example, not its theory. Mike then gets it:
Yes, upon reflection it could be done just as easily using the Humble Dialog approach. Every time a control is left, notify the BO. The BO does a validation and then sends out the appropriate validation events, or calls the view interface back directly.
However - try not to be shocked - RonJeffries dislikes it all:
I'm a bit troubled by all these solutions, and hope that when you do one or more, you'll post them for our amusement.
Why is Ron troubled, all are not asking themselves ... well, it's because it seems likely to me that the GUI is more complex than the BO (!) wants to be, and that adding a bunch of stuff to it to fire a bunch of events on the off chance that someone is interested in them, seems like a lot of extra messing about.
I don't have a better answer. It just seems that the notion of having all this little microwidgets on our widgets, each of which can tell us something different about what we did wrong in the GUI, and then having the model know all about those ... it just seems like we have somehow purchased trouble for ourselves.
JohnRoth gets more concrete:
I'm not sure I agree that it's more trouble than it's worth. My thinking is that the model needs some way of saying there is something wrong with the data entered, and it's up to the GUI class to display that to the user. This particular toolset seems to want to use a composite widget to do that, which seems like a bit of overkill but I don't have an objection as long as, and I'll repeat that, as long as the model doesn't have to deal with the fact that there are two widgets there.
The way I think of it is that the model needs to send back a message whose semantic level is something like: "you can't distim the frozzle while the xnax is green." The actual implementation could be something like "error code = 17." Then the UI gets to display that in a meaningful manner.
Remember that there is also form-level validation that cannot be applies on a per-field basis, such as "Either a phone number or email address is required".
Typical and basic validation that I wish was part of the HTML standard:
It's rare for database constraints to be used for security reasons. They're usually used to ensure the database is correct and consistent, independent of whatever rubbish the application developers might write or what nonsense the users might enter.
I generally meant server-side application code, not the database itself. I was mostly thinking of typical web-based applications where there is often a significant server-side application presence rather than the "traditional" LAN-based client/server type of application. In other words, you don't want browser-side code to be the final validation because it can be relatively easily hacked around without breaking into the server. The browser can give "friendly" messages, highlight problem fields, etc., but the server side should still verify to guarantee bad data doesn't get through even if the browser has been fudged with. The database can perhaps do some of that "final" validation, but that's up to the app designer. In the name of OnceAndOnlyOnce, you don't want to do the same validation in too many places if possible.
Note that if the client handles most of the UI issues of validation, then the server side may not have to have "friendly" validation handling. The session or transaction can simply "crash". This is because under normal (non-hacked) circumstances, the browser-side code will catch the problem in a user-friendly way. There is no need to be user-friendly to hackers. And the distinction between "security" reasons and "data integrity reasons" is often fuzzy. For example, a hacker can use bad data to crash our foul up a key system to slow a business. -t
See also: FormValidation, CrudScreen, DataDictionary