views:

283

answers:

6

I've got this question about form validation and business validation. I see a lot of frameworks that use some sort of form validation library. You submit some values and the library validates the values from the form. If not ok it will show some errors on you screen. If all goes to plan the values will be set into domain objects. Here the values will be or, better said, should validated (again). Most likely the same validation in the validation library. I know 2 PHP frameworks having this kind of construction Zend/Kohana.

When I look at programming and some principles like Don't Repeat Yourself (DRY) and single responsibility principle (SRP) this isn't a good way. As you can see it validates twice. Why not create domain objects that do the actual validation.

Example: Form with username and email form is submitted. Values of the username field and the email field will be populated in 2 different Domain objects: Username and Email

class Username {}
class Email {}

These objects validate their data and if not valid throw an exception. Do you agree? What do you think about this aproach? Is there a better way to implement validations? I'm confused about a lot of frameworks/developers handling this stuff. Are they all wrong or am I missing a point?

Edit: I know there should also be client side kind of validation. This is a different ballgame in my Opinion. If You have some comments on this and a way to deal with this kind of stuff, please provide.

A: 

On the web you probably want some kind of client-side validation as a "first gate" - check for required values and other simple validation rules, without requiring the user to perform a web request just to see that the data isn't valid. On top of that, you want a server side validation layer (either built into your domain objects, in a service layer or somewhere else) that performs the actual validation of the object properties, and other business rules.
Note, however, that domain dependent validation rules (for example that a Name has the required properties FirstName and LastName) and pure business rules (for example that if a State has been provided, Country must be USA) do not necessarily have to be in the same place.

Tomas Lycken
This is strange I think. Firstname and lastname are required properties. That is some business rule of name right? So this kind of logic should be in the name. If one is not given give some sort of notice (I'm talking server side validation right now). And yes if state is given country should be usa. This is still business logic right? or am I mistaken.
Robert Cabri
I would say that all of it is business logic, but some of it is plain property validation, and some is more complicated. Maybe my example wasn't the clearest one - take another one instead of the state/country case: in an e-commerce system, validation of the price property of a purchase could be that total price is required (domain object validation) and that it matches the temporarily saved shopping cart associated with the current user (pure business logic). Both are business logic, but only one can be performed without more knowledge than the type of object that was submitted.
Tomas Lycken
+5  A: 
  • Form validation (client-side) is actually just for usability
  • Business validation is the real validation

Your application would probably work without what you call form validation, it would only look less nice to the user. Business validation however is needed to prevent corrupted data.

Fortega
+1  A: 

The approach you are describing looks a little bit over-engineered to me. I can see it being theoretically neat and clean but it seems to me that it would be a bit too granular to map to the data in a practical situation, creating unnecessary overheads and a whole lot of classes that do very little in the grand scheme of things. When I run into things like that it tends to start to smell a little of Solution Sprawl. Also if you have a lot of per-field wrappers around primitives you've got some pretty good chances of DRY violations between your "AddressLine1" class and your "AddressLine2" class and so on or an overcomplicated inheritance heirarchy necessary to avoid them.

It's like the sixth normal form- it's theoretically interesting, but if you wrote your code that way it would take a very long time for you to get anything done and maintenance would be a nightmare.

glenatron
It is possible to create basic domain models that could be reused. Like say `class Text {}`. Very generic right? and create some more specific types when needed like `class Email {}`. Normally you refer to this as a validator of some sort. But creating a domain model makes more sens if you ask me. They both have the same validation. Only one (the domain model) is accepted by the other domain models.
Robert Cabri
One certainly could do things that way, and I don't think it would be _wrong_ to do so, but you end up with an inheritance heirarchy like this: Text, Text>>Email, Text>>Name, Text>>AddressLine, AddressLine>>Country, AddressLine>>Zipcode and so on. Looking in any of those objects I would expect to find only a few lines of code to distinguish them from any other class in that heirarchy and just in terms of making it easy to read and work with the source and to be coherent with the data being modelled I would rather have those in a larger object or two that maps more closely to the data.
glenatron
OK you say one big object which does the validation. In what way do you return your errors when not validating? You throw a special Exception have a method validate that returns an array of some sort with errors? You shouldn't return just one error if you ask me. This breaks usability
Robert Cabri
Well, one big object or a bunch of them, so for example a person might have multiple addresses, but I don't see the value in those objects being normalised further than the level of normalisation in the database- in fact the relationship between the fields may be more important than the specific integrity of an individual field in some cases. That does open the door to having a list of validation problems more easily because your parent-level object is already performing all the validation itself. I would certainly want an array rather than one-by-one failures.
glenatron
+1  A: 

If you use business domain objects to validate the form as well, which can be achieved using rather simple tools, this eliminates the cruft of most validator based solutions. In a way you want to extrapolate partial behaviour from the business domain to the form domain; this should reduce code and improve maintenance at the cost of some extra wiring. I agree with Robert. I feel this approach is better than Zend/Cake/Ci etc. It seems to go in the direction of the naked object philosophy; just dump the V and the C, go for models only: http://en.wikipedia.org/wiki/Naked%5Fobjects

Gabor de Mooij
A: 

Validating in both place IS redundant but necessary. You'll want to validate on the client so that your user has a better UI experience. It also reduces the load on your server. You must also validate on the server side as nothing coming over the wire should be trusted by your app.

Walter
Yes I know that. But in a lot of frameworks they introduce server side form validation. As in Validators, not business validation. What do you think of that? How do you deal with validation on the client side? Exporting the same rules somehow? Create the same validation in Javascript?
Robert Cabri
+3  A: 

While it seems the DRY principle is being violated, you are actually validating data in two different layers - presentation and business; validation concerns may differ between these two layers. In your presentation layer you might be concerned with specific elements related to your view, i.e in a web app you might need to return a specific validation message containing a html div so you can properly render an ajax response.

Also forms usually contain persistence related constraints such as not having a certain form field as null or limiting field sizes, while business constraints might be broader, i.e validating if a purchase by an individual in a e-commerce webapp can be allowed by verifying the his past successful purchases.

That said, there are frameworks such as hibernate validator (on java) that allow you to include validation metadata in your business entities that is checked before it is persisted or when you invoke its API to do it so manually. With it you could validate all your constraints in one place.

seibzhen
I don't get it. can you elaborate this difference between presentation and business validation some more? The way I see it, do prove me wrong, is that validation is done because values are going into the domain. so why have different "types" of validation. yes you can define basic/primitive client side validation like required and such, but business validation?
Robert Cabri
I was thinking of situations where your view does not represent your model in a straightforward manner; suppose you have a form with a checkbox and 2 radio buttons, if the checkbox is enabled, you need to validate input from radio buttons - this is a scenario strictly related to your view. But you make a good point. I've given a thought about it again and in most cases form and business validation are the same; rails for example renders forms based on your model and also validates based on it. In this approach you need to translate any constraint violations in your business layer to your view.
seibzhen