Input Validation vs.Business Rules Validation
I am probably going against conventional wisdom here, but I wanted to talk about the difference between input validation and business rules validation.
Input Validation for me is about validating the user input. Some people call "Name must not be empty" a business rule, I think about it as input validation. Business Rules validation is more complex, because a business rule for me is not "Name must not be empty", it is a definition of a state in the system that requires an action. Here is a definition of a business rule:
In this case, invalid business rule is something that exists in the system by definition, and require some sort of an action. Flagging the user, sending a PayUp(tm) letter, etc. It is also usually something that involves more than a single object and its properties. "Paid order" means that there is an accepted transaction for this order within the specified range, and extending the duration of acceptable payment is another object entirely.
Input validation can be as simple as validating required fields or as complex as: "You need to input phone number OR email, if you enter ungency you must put reason description OR reason code". Business rules validation is beyond that, it is validating that the total sum of the order is less than the allowed credit for this acount.
I tend to use different UI for the different validation schems as well. Input validation is something that needs to be presented near or at the input itself. Business rules validation is something that is generally a different screen all together, and is distinctly different that the input itself.
Comments
Where does the input validation live? In the presentation layer or in the domain layer together with the business rules (or both)? Interesting perspective BTW.
Input validation is specified on the domain model itself, usually using attributes.
Input validation itself is done on the controller, when accepting input
I disagree that 'Name shouldn't be empty' isn't a business rule. It CAN be a business rule, because it tells you something about the validity of an entity, e.g customer, which name shouldn't be empty.
To use a customer C in a process P which applies other business rules onto the consumed entities, C must obey to a set of rules. One of them can be 'Name shouldn't be empty'. If C has an empty name, it violates that rule and C is invalid. This has nothing to do with imput, but with validation of C itself.
I think your question is more about where you place validation.
I also am against validation using attributes: it depends on the context if a given entity E is valid or not. If you then look at attributes, it is too rigid, they don't change. Better is to inject via DI a validator object into the entity which performs the validation for the entity. This frees the entity of the validation code and you have more flexibility implementing it as well, also when using it.
I'm currenctly implementing (sort of) input validation in the domain as argument validation, but only validations that can cause conflicts like null inputs and such.
Business validation (name length and real business rules) go into a validationg method per class, so all the validations can be rerun again at a later time. Parent can be defined to be valid only if some child types are also valid (Order -> OrderLines). Rules will change, and you have to be able to revalidate you data I think.
I'm still looking for a good match between UI and domain validation re-use. I do believe that domain validation comes first and is most important since it's about the (business) data integrity. UI validation is about userfriendlyness and is to be added on top of a solid domain.
But I'm still very new in this topic and trying to find my way...
I agree that required fields should be treated with an input validation block but I disagree with examples such as "if you enter urgency you must put reason description OR reason code" being taken as input validation.
Ideally the input from these three fields: "Reason description, reason code, and urgency" would be passed to a business object called something like "Incident".
The incident class would take all the fields as parameters to its constructor and self validate to decide whether description or reason code were both passed as non-empty strings. That way if this business rule ever changes (i.e. both are now required), the only that needs to be updated is the Incident object.
First off I submit that "business rule" is a somewhat overly specific term in the first place. I prefer to think of them as "domain rules" since they may be promulgated for a business, or some other entity, including even a software service.
Secondly, you are trying to make a distinction between rule types when in fact you are simply discussing the matter of location and timing of where and when a rule is applied. All rules that attempt to keep invalid data out of a system are still domain rules. It's just a question of location and timing. And the timing may or may not be dictated purely by the needs of the system. For example, rules enforced in the UI are often done as much because of the immediacy of feedback needed by the user's workflow, as by anything else.
Sometimes ... often .. perhaps even most of the time ... a particular rule enforced in the UI maps exactly to a rule that needs to be enforced at the DB integrity level. The problem is that, particularly in web apps, the rule may need to live as as, say, client-side JavaScript in the UI, and as a relational constraint in a proprietary DB on the other end. And of course, UI rules may need to be either finer or broader-grained than any one domain rule.
In an ideal (DRY) world, business rules would be expressed in one central repository which would be capable of generating whatever code artifacts are needed to apply it in the UI, business layer, or data store safety net (e.g., stored procedures or constraints that guard basic relational integrity from rogue application logic wherever it may reside). I have yet to see such a system that does not impose more system design constraints and/or complexity than it solves, unfortunately.
I see it a little like Bob does, in that input validation the use of business rules in a given context (time and place). More specifically, the context happens to be a UI interaction that involves collecting input from the user.
A system embodies the many many business decisions and facts that domain experts have expressed. Because of this, to me it seems that business rules are present at every level, in every tier, and can take many implementations. I see business decisions/rules all over the place - in database constraints, choice of data types, ActiveRecord validation attributes, workflows, policy objects, specification objects, state transitions, finder methods etc.
I suppose the trick is to find a neat way of implementing the right rules in the right place to make them as understandable, manageable and maintainable as possible. Simplicity and consistancy are desirable, and this is why I like the validation attributes in ActiveRecord - they're explicit and easily applied throughout the domain model. I think they're great for invariants that are applicable for the entire lifecycle of an entity, if you're system is simple enough to have those!
Tobin
@Frans,
Name is not empty is an invariant of the entity. Not a business rule because it is not something that can happen (yes, I know about bad data and no constraints).
About validation using attributes, they are good for simple things, because they clearly express the intent of declaratively. They are not good for the more complex issues.
About different things for different stages, I may have a customer valid for a shopping cart, but not valid to place an order (has no credit card).
This is usually handled by grouping attributes.
@BtV,
You may be new, but you are on the right track.
I would usually try to stretch what I can do with attributes a bit more than just required fields, though.
@Karthik,
Ctor validation is good, but is has issues.
It has issues because the only way for a ctor to report an invalid state is to throw an exception.
This means that suddenly I lose a lot of friendliness in the validation approach.
I use the term business rule and business logic to mean something about the domain in the application. Is sounds like you have a more precise definition in mind for it.
I usually express input validation as attributes on the object, which the UI layer knows how to use. This means that there is one place where I use it.
The UI still may have separate mechanism to deal with validation, though. Mainly because of the limitations that you mention.
I've put up the solution I use for modeling validation rules as well as how to get access to them in a generic way here:
http://udidahan.weblogs.us/2007/04/30/generic-validation/
Comment preview