The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Where to put validation in the MVC pattern

Hi all,

I'm having a conceptual problem in the intersection of OO, the MVC pattern and validation. In short. I have no idea where to put validation and how to apply it.

In principle we should only allow objects to be in a valid state any time. If I contruct an object is should be valid at contruction time i.e. I should not pass malformed data to the contructor. If a constructor gets invalid information is should throw an exception.

Since my program interfaces with the real world I can expect malformed data from the user, so I have to add validation somewhere. It shouldn't be in the contructor as malformed data isn't exceptional, so it has to be somewhere before it.

In the MVC pattern, the view shouldn't ever know about validation and as just explained I can't argue for putting the validation in the model. I don't like putting validation code in the controller, but I don't see how it could be moved away.

Maybe I could make some MVCV pattern and get the validation put in some other place where the coupling to the controller is smaller. How would you go about doing this? Would you create some static validation classes with helper functions invoked by the controller, or how do you go about it?

I'm really perplexed. Thanks in advance.
Peter Monsson Send private email
Saturday, June 17, 2006
The MVC pattern attempts to impose some structure, but the "barriers" b/w the various roles in an application are not always so rigidly enforced.  It all depends on how you slice your application up - physically, by objects, role in a pattern, by aspects, etc.  In the real world, strict layering rules are often violated in order to optimize for performance or for other practical reasons.  Also, correct me if I'm wrong but MVC doesn't say anything specific about input validation.

It seems to me that each layer is responsible for some validation.  Your model objects should not accept bogus arguments.  That's why there is an IllegalArgumentException in Java.  Some IOC containers also define callback methods that your model object can use to raise an exception if an object has null properties.

Why can't the View have validation code?  It's very common to find JavaScript routines in web pages that check for date ranges, correct format of email addresses, etc.

One could argue that these routines are really part of the Controller.  OK, so the Controller is distributed across physical tiers and multiple program components.

What if I put all my data validation rules in XML files that are indexed by "action"?  Are they part of the Model, View or Controller?  The Controller invokes this validation logic in response to a request, but is it considered part of the Controller?

In the past, I have hard-coded validation routines in a web "Controller" class.  Many of these are static routines and could just as easiy be placed in separate libraries.
NPR Send private email
Saturday, June 17, 2006
Once and only once. If you test a value for "rightness" in Javascript you are going to have to do it again before actually committing anything. Hence, the same code should always be validating. If you want to validate with Javascript, it should make a server call to do so, and make no assumptions itself.
Saturday, June 17, 2006
It's not always necessary to make a call to the server to validate input.  Some things can be encoded as static rules and need no state information whatsoever from the server.  I can think of numerous examples:

- empty fields
- malformed email addresses
- field must be a certain number of char's long

To call a routine on the server in these cases is an unnecessary use of network/server resources.  Further, to add checks for all these special cases in your server when they already are performed on the client is unnecessarily redundant.

A good framework might include a way to generate the JavaScript to perform these checks from information in a configuration file that is coupled with the model, or even from Java code in the model. 

HTTP/XML-based remoting (AJAX) or traditional request-response could be used to talk to a routine on the server in order to validate against a database.  Things like:

- Invalid address (wrong zip code)
- A user with that email address already exists
- Wrong password

The principle here is that each layer only talks to the next layer if it needs the information.

But, I think the confusion arises by considering the M, V, and C to be distinct physically distributed layers/tiers, when in fact M, V, and C functionality can be distributed and overlap multiple tiers.  Validation can be performed in multiple places.
NPR Send private email
Saturday, June 17, 2006
"If you test a value for "rightness" in Javascript you are going to have to do it again before actually committing anything."

OK - I'll admit, this is true in many cases.  If the user has disabled JavaScript, if you want to make JavaScript optional, you have to validate on the server, too.  JavaScript should be viewed as the first line of defense.
NPR Send private email
Saturday, June 17, 2006
Well unless you want a security hole the size of Texas you _always_ have to do validation on the server side of anything that is submitted by the client, without which it is a trivial matter for a hostile client to submit invalid and potentially dangerous data.

Whether this server side validation is user friendly or solely to prevent dangerous data from fake or buggy clients, with additional friendly validation clientside, is another matter.

The issue with relying on 100% server side validation is one of performance. Doing client side validation can give the user much quicker feedback about errors they may have made in input, the problem here is the the client needs to know what is and isnt valid input, and much of this is a function of the business rules that form part of the model, and often requires the validator to be able to retrieve information from the database.

The way I generally work it is to leave complex BL dependent validation to the model, and in the controller (ie: servlet/struts action/portlet etc...) and view (ie: clientside Javascript) to perform simpler semantic (is that the right word?) validation such as checking that data was entered in the correct format for the data type it is to be comverted to before it is passed to the model.

This can be aided by having the model provide the controller & view with additional metainfo about fields beyond just the data types (where such info is static in nature and not dependent on the result of runtime business logic) such as minimum and maximum values, regexps for valid formats, and so forth.
Java GUI Programmer
Sunday, June 18, 2006
I have built a framework based on MVC and IMHO the best place to put validation is in the model, never the view or controller. Validation is, after all, the implementation of business rules, and all busness rules should be contained within the model.

In my framework all views are supplied from reusable XSL stylesheets which do not contain any hard-coded references to any database table or column names. All my controllers are reusable which again do not contain any hard-coded references to any database table or column names. Hence these two components do not know what data they are dealing with and are therefore incapable of validating it. All this knowledge resides in the model, so it's the model's responsibility to validate the data before sending it to the database.
Tony Marston Send private email
Sunday, June 18, 2006

What you can do is. Create Validator object within your Model, and let Model to provide Validator for the UI. Then your UI can ask Model for Validator, talk with validator using user input, and display appropriate messages to the user.

This way, you will keep your UI away from knowledge on validation process. I described how I did it here:

Denis Krukovsky
Denis Krukovsky Send private email
Sunday, June 18, 2006
> Once and only once.

A better form of OAOO is to define the validation in one place and use code generation to implement validation at every relevant layer.

You want as much validation as possible closest to the user so they have a good experience, yet as each of the layers are independent they need to validate too. But implementing them independently leads to a nightmare of inconsistencies.

That's why I like the generation approach. You define once but implement everywhere from one definition.
son of parnas
Sunday, June 18, 2006
Validate in the model.  There's a few different styles: object constructor can throw illegal argment, factory class can do validation and create an object if all is ok, have a 'raw widget' class if you need hold the user's input for awhile before final validation...
Mike S Send private email
Monday, June 19, 2006
Smart objects or dumb objects? In MVC the model is like a combined business and data object, so it needs to be smart enough not to persist invalid data.

When client-side validation is thrown into the mix, you have to deal with two code bases, but you can't eliminate server-side validation just because you've already implemented it in JavaScript.

So there's going to be "pain," and as one post suggested code generation can be used to ease the suffering. ;)

If the body of business rules is large and/or complex, it may be helpful to encapsulate validation in another layer which must be called from the model layer before saving.
Beanbrain Send private email
Tuesday, June 20, 2006
Thank you all for your replies.

You're all right that the validation just can't be anywhere but in the model. One thing I might have erred on is when an object is valid as opposed to internally consistent.
Peter Monsson Send private email
Tuesday, June 20, 2006
I'm not a big fan of having the M throwing exceptions on bad data, IMO exceptions should only be thrown on exception circumstances and sadly bad data isn't.

The approach we have is to allow the business object (M) to keep the bad data but to all contain the list of currently broken business rules. As properties are changed this list has items added and removed. This solves the problem of two properties dependent on each other for validation.

The business objects are built on top of an OR Mapping system that will throw an exception if an invalid object is committed to the database.

As for feedback we have a control similar to the ValidationSummary webcontrol that lists broken business rules for the user. Also some of the early javascript valdiation is fed from the those same business rules in the M.

This allows our M to define all the rules as well as provide some good feedback.
Nige Send private email
Tuesday, June 20, 2006
Who says the Model has to throw exceptions when it encounters bad data? That's not what exceptions are for.

In my framework the Model generates an array of errors, and if this array is not empty it does not waste time trying to write anything to the database. When the Controller receives the result of the Model's efforts it notices that the error array is not empty so it instructs the View to rebuild the page with the error messages (yes, there can be ore than one!) inserted in the right places. If the error array is empty then the Controller moves on to the mext action.
Tony Marston Send private email
Wednesday, June 21, 2006
I agree Tony, exceptions shouldn't be used for bad data, it was mentioned in the first post so I thought I'd comment on it.

IMO exceptions are should only happen in "exceptional circumstances".
Nige Send private email
Wednesday, June 21, 2006
hehe, something like this? ;-)

 * Thrown when the user enters a value that is actually
 * correct and meaningful. This situation is so unlikely
 * that we dont even make this a checked exception as its
 * doubtful anyone could implement code to handle it.
public class ValidInputException extends RuntimeException
Java GUI Programmer
Monday, June 26, 2006
+1 Tony
Michael B
Friday, July 14, 2006

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz