If you’re a developer, you know how important and how much goes into validation – guaranteeing that every data value is correct and accurate. Not considering the impact and the poor implementation of this validation logic in your architecture can be a contributing factor in leading your application to be a Big Ball of Mud.
Just like taking vitamin C to prevent a cold, choosing a good validation framework and integrating properly it into your architecture will not guarantee your application won’t evolve into a big ball of mud. But, it will contribute to the resistance! In this post I will start a series of posts where I will share my thoughts on what I expect from a Validation framework, and how SpecExpress meets these expectations.
Separation of Concern
A lot of validation implementations integrate the validation logic right in the same class that is being validated. Many implementations of validation leverage attributes, such as those defined in the System.ComponentModel.DataAnnotation namespace. Other implementations rely on implementing and calling some method in the class that validates the instance.
Such implementations tightly couple the validation logic with the class being validated. It has been my experience that separating the concern of validation from the class being validated increases maintainability and extensibility. Consolidating rules for a given class consolidates all the business rules that are to be applied to an object in one class. This decreases maintenance costs by not having this business logic scattered across all your application.
SpecExpress does this by defining a separate validation class called a Specification. In SpecExpress, a Specification is simply a class that looks like this specification for a contact:
public class ContactSpecification : Validates<Contact>
Check(c => c.FirstName).Required();
Check(c => c.LastName).Required();
Ideally, when I have a Contact to validate, I do not want to tightly couple the specification to the code that is calling for the validation to be performed. This adheres to the Open – Closed Principle which code is Open for extension, but closed for modification. I can alter, or swap out specifications without having to change any of the code where validation is needed.
In SpecExpress, this is done through the use of a ValidationCatalog which is essentially a container for all the Specifications. When your application starts, you need to configure the ValidationCatalog by calling one of the implementations of ValidationCatalog.Scan(), which will scan for specifications in your application and load them in the container.
When you need to validate a Contact instance, you simply then call ValidationCatlog.Validate against your instance like this:
var contact = new Contact();
// Initialize Contact here.
var results = ValidationCatalog.Validate(myContact);
// Contact is valid
// Contact is not valid - do something to notify user of issues!
As you can see, we simply rely on the ValidationCatalog to know the what’s and where’s of the specifications to use!
By using SpecExpress, we can separate the definition of a class from the business rules that are used to verify the accuracy of the class. By doing so, we are able to decrease maintenance costs and mistakes since all the business rules are consolidated and can be swapped in and out without any impact on the code calling for validation.
Next post, I will dive deeper into what I expect from a framework when an object is invalid.