Tuesday, January 10, 2012

Inline Specifications


A powerful feature of SpecExpress is it's ability to automatically generate user readable error messages for broken rules, and gather all of them up to display. In order to use this functionality, you need to create a Specification with the rules defined, add that specification to the ValidationCatalog, call Validate, and handle the ValidationNotification that is returned. But, sometimes specifications can be overkill for your needs. You might not need the reuse of a specification, or you might have rules that only need to be applied in a specific context.

We've recently add a new feature called Inline Specifications to SpecExpress that allows you to use SpecExpress to create your validation rules and messages, and not need the ValidationCatalog or just let you throw an exception. Here's what they look like in action.

Assert Inline Specification
public void DoWork(Request request)
{


//Before we do our work, validate the request, and throw an exception if invalid
Specification.Assert(sp => 
{
sp.Check(s => request.Field1).Required().EqualTo("Yellow"));
sp.Check(s => request.Field2).Required().EqualTo("Blue"));
})
}




Will create a ValidationNotificationException with all the broken rules.

Validate Inline Specification
public void DoWork(Request request)
{

//Before we do our work, validate the request
var validationNotification = Specification.Validate(sp => 
{
sp.Check(s => request.Field1).Required().EqualTo("Premium"));
sp.Check(s => request.Field2).Required().EqualTo("Blue"));
})

if (!validationNotification.IsValid)
{
//Log error and state then precede
}
}




Sunday, September 18, 2011

IDataErrorInfo and SpecExpress

We recently received a post from Karl:

I didn't see an example or documentation for using SpecExpress along with IDataErrorInfo.  Is it possible?
Thank you, SpecExpress looks great,
Karl

Well Thanks Karl!  We think SpecExpress looks great to!  Using IDataErrorInfo with SpecExpress is VERY possible.  A matter of fact it makes implementing IDataErrorInfo in your model classes extremely simple.

For those that are unfamiliar with IDataErrorInfo, IDataErrorInfo is an interface that a UI framework such as WPF, Silverlight, and MVC can bind to when data validation errors occur.  The interface exposes two member properties:

  • Error – gets an error message indicating what is wrong with the object
  • Item – an index based property that gets an error message for a given property given the property name provided as the index

Implementing these two interfaces is as simple as this:

using System.ComponentModel;
using SpecExpress;

namespace MvcApplication5.Models
{
public class Contact : IDataErrorInfo
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

#region IDataErrorInfo
public string this[string columnName]
{
get
{
return ValidationCatalog.ValidateProperty(this, columnName).ToString();
}
}

public string Error
{
get { return ValidationCatalog.Validate(this).ToString(); }
}

#endregion
}
}



You may even want to consider implementing the interface in an abstract base class that all your model classes inherit from!  The beauty of this code is the simplification you get in defining the model class.  The aspect of business rules delegated to SpecExpress’ ValidationCatalog through a single line of code for each property!


Of course, using MVC, the IDataErrorInfo interface is called on the server side each time the data is posted to the controller through a post back.  Sometimes, especially for lengthy forms, this may not be the optimum user experience.  With SpecExpress, we have written an MVC Integration library that leverages the JQuery Validation library for client side validation.  Through the MVC Integration, the appropriate client side validation is automatically called based upon the validation rules expressed and registered in the ValidationCatalog.  See the documentation and sample code in the source code for more specifics on this integration.

Sunday, August 7, 2011

What to Expect from a Validation Framework: Functionality

You can only discuss functionality from the aspect of the impact the functionality has on a given consumer.  Given the fact that we are discussing a “framework”, the consumer that is going to be most impacted is the developer consuming the framework.  After all, a developer can deliver the same user experience with or without the use of the framework.  A good framework should allow the developer to deliver this user experience with the least amount of effort while increasing the maintainability.  So with that in mind lets discuss some functionality I would expect a Validation Framework to deliver.

Fluent Interface

Dictionary.com defines fluent as “ able to speak or write smoothly, easily, or readily”.  Eric Evans and Martin Fowler first coined the term “fluent interface” as it applies to an API, allowing the developer to easily and readily interact with it.  This is usually done through the use of method chaining.  By implementing a fluent interface, a Validation Framework will all a developer to easily express validation rules, leveraging intellisense along the way.

Check(c => c.FirstName).Required().MaxLength(50).IsAlpha();



Use of Expressions


Many frameworks rely on strings being passed in as parameters that indicate a property that is to be referenced or a method that is to be invoked.  The problem with doing so is that these strings often get missed when renaming a property or method.  By using expressions, represented as lambdas, we not only facilitate all the renaming, but also give the developer more flexibility to express what they wish in the lambda, and allow them to take advantage of intellisense – something lacking when defining a string.


Of course, a Validation Framework should allow me to utilize expressions when declaring the target of a rule such as when I want to declare a rule for the StartDate property of a class defining a Meeting:

Check(m => m.StartDate).Required();

However, in a lot of situations, a rule needs to reference other properties, or call other methods, or rely on some other piece of data that is declared elsewhere in application.  This is where I see a lot of Validation Frameworks fall short.  Consider a class defining a Meeting where a rule may be “StartDate must be before EndDate”.  Many frameworks require you to implement your own delegate and call it as part of a “custom” rule.  SpecExpress allows you to declare this rule as part of the standard GreaterThan or LessThan rules:

Check(m => m.StartDate).Required().LessThan(m => m.EndDate);

A matter of fact all argument based rules that are implemented by SpecExpress have an overload that takes a constant, as well as an overload taking in an expression.


Implementation of Most Common Rules


A Validation Framework is only as useful as the rules it implements out of the box.  In my opinion, this is another area where a lot of frameworks lack.  Many frameworks give you a subset and leave the rest to be implemented by you – the consuming developer. 


At last count, SpecExpress has implemented 30 rules that cover:



  • Required

  • Boolean (IsTrue, IsFalse)

  • Collections (Contains, IsEmpty, etc.)

  • DateTime (IsInFuture, IsInPast)

  • IComparable (Between, IsGreaterThan, IsLessThan, etc.)

  • String (MaxLength, MinLength, Alpha, Numeric, Matches, etc.)

  • Custom (for the rare occasion where you need it)

Combining Rules


Often times, there are relations between rules.  For instance, I may have rules for a serial number that states “The serial number must start with a ‘y’ or a ‘z’ and be 10 characters long”.  Many frameworks consider this to be a “complex rule” that must be implemented in a custom delegate, but in SpecExpress, by using the Matches and LengthEquals rules, this can be expressed through the fluent interface and not relegated to be implemented in a delegate:

Check(i => i.SerialNumber).Required()
.Group(s => s.Matches("^y.*")
.Or
.s.Matches(“^z.*”)
.And.LengthEqualTo(10));

In the above example, a Group is defined to control the precedence of the “And” and the “Or” operations.  Just like in normal C#, an “And” takes precedence over the an “Or”.


Summary


By focusing on the developer experience, SpecExpress has provided a Validation Framework not only assists the developer express the rules through Intellisense, but also reduces the amount of code that code they would need to write for what other frameworks would consider “complex” validation.  However, SpecExpress has not ignored the fact that there may be situations that were either simply overlooked, or would be better expressed through extending SpecExpress. In my next post, I will show two ways to extend and customize SpecExpress.

Monday, August 1, 2011

What to Expect from a Validation Framework: It’s About Results!

This post is the second of a series where I share my thoughts on what I expect from a Validation framework, and how SpecExpress meets these expectations.  In my last post I discussed how SpecExpress separates the validation logic from the instance being validated – creating a loosely coupled validation solution.  In this post, I will discuss what should be returned when an instance is validated and is found to be in an invalid state.

More than a List of Strings

At first inclination, one might think that when we validate an object, we simply need a list of string describing what was invalid about the object.  But what if I simply want to know if the object is valid?  And what if the object I am validating references other objects that are invalid?  Perhaps the object I am validating is a Contact, and a Contact references an Address.  If the address is invalid, how do I want that represented in the list of strings?  How do I represent the details about what is invalid about the address?  Also, what if I want to somehow bind each message to a control on the user interface?  Wouldn’t I need more meta data about each error message in order to discern the bindings?

When an object is validated in SpecExpress by calling ValidationCatalog.Validate, a ValidationNotification object is returned.  Here is an example of the structure of the ValidationNotification:

The ValidationNotification has an IsValid flag indicating whether or not the instance is valid or not.  It also contains a list of ValidationResult objects accessible through the Errors property.  Each ValidationResult contains the following:

  • “Message” property which is intended for display to user
  • “Property” property which is a MemberInfo which encapsulates all the metadata about the property being validated
  • “Target” property holding reference to the instance being validated
  • “NestedValidationResults” which - if the property being validated is a reference to another object (such as Address) – will contain another collection of ValidationResults that define the items that are invalid with it.  Thus the Results are hierarchical.

The ToString method of the ValidationNotification will result in a user readable summary of all the messages where the hierarchy is represented by indentation.  However, this may not suit all cases, and in cases where it has not been suitable, I have simple created my own extension method to the ValidationNotifiation type to render it as I wish!

Message store and globalization

As a consumer of a Validation Framework, I want complete control over the messages rendered to the user.  Of course, I want the ability to specify an error message when defining a rule, but doing so may paint me into a corner when it comes to globalization.  Such hard coded error messages are often frowned upon.  The preferred method would be to store such messages in a resource file which can be easily globalized.

SpecExpress, out of the box, stores its error messages in resource files.  However, SpecExpress does not limit you to using resource files.  The validation engine interacts with the resource files through an interface called IMessageStore.  One can create their own implementation of IMessageStore that, perhaps gets the error messages from another source such as an XML file, WCF Service, database, or even any combination – the options are limitless.

The IMessageStore interface requires you only implement two methods: GetMessageTemplate and IsMessageInStore.  GetMessageTemplate simply returns the message given the key, and IsMessageInStore simply returns a boolean indicating if a message for a given key exists in the store.

After implementing your IMessageStore, one simply add your implementation to the ValidationCatalog by doing the following:

ValidationCatalog.Configure(x => x.AddMessageStore(new MyCustomerMessageStore, "MyCustomMessageStore"));



Messages are accessed through message keys.  These keys are simply the name of the rule or, if the rule is negated, the name of the rule is prefixed with “not_”.  So, for instance, when the “Contains” rule fails it will look for the message keyed by “Contains”.  If the rule is defines as “Not.Contains”, then the validation engine will call for the “Not_Contains” message.



You may add override the default messages by implementing your own repository, or adding another instance of the ResourceMessageStore pointing to your own resource file, and simply placing new message keyed by the same name in there.  The validation engine will search all the added message stores for the file and if not found will use the default messages.



Summary



When an object is invalid, SpecExpress will return a ValidationNotification object which provides a rich set of information regarding what is invalid.  The ValidationNotification is hierarchical in nature, reflecting the hierarchical nature of the object being validated and can be used to bind error results to the user controls bound to the model being validated.



SpecExpress also gets the error messages from a message store which is loosely coupled to the validation engine through the IMessageStore interface. By implementing your own instance of the IMessageStore, one can store the error messages anywhere they want and even override the default messages.  SpecExpress provides a ResourceMessageStore that implements the IMessageStore interface and returning messages stored in resource files.



In my next post, I will discuss a few general features I would expect a Validation Framework to provide the developer.

Tuesday, July 26, 2011

What To Expect from a Validation Framework: Separation of Concern

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>
{
public ContactSpecification()
{
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);
if (results.IsValid)
{
// Contact is valid
}
else
{
// 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!



Summary



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.


Friday, September 18, 2009

What is SpecExpress?

SpecExpress is a Fluent Interface to a validation focused Domain Specific Language for .Net.

Benefits

  • SpecExpress handles all the infrastructure code allowing the Developer to focus on writing concise validation rules in the Validation DSL.
  • The Fluent Interface, teamed up with a DSL, allows the developer to quickly write the rules with the help of Visual Studio Intellisense which guides the Developer into writing consistent code.

Examples

Let’s look at some requirements for validating a person’s Last Name. Some typical validation rules are:

  1. Make sure it’s required by looking for nulls or empty strings
  2. Make sure it’s not too big to fit into the database
  3. Doesn’t have any funny characters

If any or all of these are broken, you have to display nice user-friendly feedback. It would be some combination of:

  • Last Name is required.
  • Last Name length must be less than 50 characters
  • Last Name can only contain letters

Now let’s look how we would implement this requirement with and without SpecExpress.

With SpecExpress

Check(p => p.LastName).Required()
.And.IsAlpha()
.And.MaxLength(50);

Pretty easy, huh? And now…

Without SpecExpress

var errors = new List<string>();
//Required
if (string.IsNullOrEmpty(input.LastName))
{
errors.Add("Last Name is required.");
}
else
{
//MaxLength
if (input.LastName.Trim().Length > 50)
{
errors.Add("Last Name length must be less than 50 characters");
}

//Only characters A-Z
var onlyValidChars = new Regex(@"^[a-zA-Z\s]+$")
.Match(input.LastName.Trim()).Success;

if (!onlyValidChars)
{
errors.Add("Last Name can only contain letters");
}
}

return errors;

Not too difficult, but a lot of code, most of it having to deal with “Infrastructure” code storing the error messages But there’s also Regular Expressions (yuck!), and some logic for only validating the rules if nothing is required.

Validation Catalog

In addition to a Fluent DSL, another feature that streamlines the validation process is the Validation Catalog. If you’re a fan of Dependency Injection, then you’ll love the Validation Catalog. Register your Specifications with the Catalog on startup, and when it comes time to validate your objects, just call

ValidationCatalog.Validate(object);

Add let the Validation Catalog resolve which specification is right for you.

You’ve piqued my interest. What now?

Take a look at the Quickstart if you want to see a full example of how to create a validation specification using SpecExpress, and validate an object.

Read the full Developers Guide, which has lot’s of examples, even if it still is a work in progress.

Or, if you want to jump right into slinging some code, Download the latest release.

Feedback

Even though a lot of love, thought, work, and testing has gone into this, we’re still interested in your feedback. Drop me a line to TechnoAg @ Twitter, post it to the Discussion Groups, or just drop a note in the comments.