catarsa.com
English čeština Deutsch English (United Kingdom)
Story

User: NotSigned (NotSigned)

Logon: Logon

Language: en-US

Validator HOW TO use it

Business Facades are responsible for 'Business Rules' validation. These rules must be evaluated before the all basic CRUD operations, and/or some other special methods are executed.
Validator - as the design pattern - provides the easy to use, read and maintain approach for business rules evaluation. The real added value comes with declarative syntax of the Rules.

Validator - HOW TO use it

index

What are the business rules?

top

Multi-tier architecture contains usually (at least) the Data Access layer, Business layer and UI layer. To allow communication among these parts there must be some 'goods' to be exchanged. The Catharsis framework calls it as an Entity.

Data Access Objects (DAO) converts the persisted data into the properties of an Entity and pass them through the Business Facades to the User Interface. Users can change this information in interaction with the application and finally save them. UI layer bounds changed values into the Entity's properties and asks the Business layer for persisting them. If Business layer requirements are met, Facade calls the DAO which converts values from passed Entity's properties into the structure dependent on the underlying persistence type (DB, XML).

This life cycle requires many checks, e.g. the security aspects, string property length... But which of these checks are Business Rules? Well, the answer, in the Catharsis framework, is:

Every property of any Entity should be checked if it meets the Business Rule(s). The Business Rule targets the Entity's property and check its value.

The checks which assure that the Entity's property meets the 'application customer' needs (length, value, not null...) are called the Business Rules. Any other checks (Security, Work-flow states etc.) are out of the scope of the the Business Rules. And that's really good to know, because now we can work with clearly defined and precisely described application aspect - the Business Rule.

Where to validate business rules?

top

The above description, about the Entity journey from persistence to the User and back, brought many candidates for the Business Rules holders (executors). (Of course the Business layer does not have its name in vain, but do not anticipate, please!)

UI layer

There could be some Validators on UI. If we are talking about the Web-application, we can easily remember the ASP.NET validator controls (or any other patterns). These features are able to assure that INPUT box is filled, has correct length and even the right value (from, to, regular expression). And if there is enough time and resolution, developers can extend the HTML embedded rules with the many other powerful checks e.g. using the JavaScript.

But, what are (if any) the down sides of this approach?

HTML Form validation is simply not enough. There must be at least some 'doubled' check, based on the declared validator, executed on the server (code behind the page). In some cases, Validator is so simple, that it could be easily reused twice (Once for JS checks on the HTML Form, secondly on the server side). These cases are 'required', max/min length and max/min value, regular expressions.  

But what about the more sophisticated checks? For instance:

  • Code property must be unique.
  • Entity cannot be deleted until is used
  • Email can be null or match the regular expression

In these scenarios (and they are real if not even almost common) the UI Validation is not enough. It could help, but it cannot solve the complete Business Rules validation.

Much more significant weak point is the dependency on the UI. The validation checks could be applied only when the input comes from the HTML Form. When there will be at least one other way how to insert data: rules must be re-written. For instance import Excel sheet or text file.

UI as the Business Rule holder is unacceptable.
Data layer

The Catharsis framework uses the NHibernate ORM functionality for accessing the DB storage. NHibernate and the Open Source community arround it brings many powerful tools for data validation. The essence of these validators is the reuse, if you are mapping Entity's properties in detail (min/max length, type...) why not to re-use these information more then once.

NHibernate based validators are ready to be used out of the box. Their advantage is the declarative syntax for the rules. Min/Max length can be set in the mapping file or in the attribute decorating the Entity's property and so on. All these rules could be triggered automatically let's say before write operations on the Data layer. The real advantage comes with the ability to call these checks even outside the DataLayer, on Business tier or even on the UI if needed.

Are there any down sides?

The significant disadvantage of the Data layer as the Business Rules holder is the mixing stuff.

Sudden NHibernate dependency infiltration is obvious. Even in cases, that you cannot or don't want to use NHibernate for Data layer you would be forced to use NHibernate Validators. Such approach is simply wrong, and not sustainable for any Architecture or framework in the long run.

The more requirements and features should our application have, the higher probability is that there will be data persisted in xml or text files, Web Services data sources ...

Yes, you can still use the NHibernate Validators even for these scenarios, but to be honest, you can also use .NET 1.1 today. Will you? Is it really appropriate? Introducing the Dependency on one DAO feature (ORM) to upper layers is simply potential risk, which you will face sooner or later.

Sophisticated checks (as mentioned above in the UI) are also impossible with these NHibernate Validators. The declarative syntax has in this case its boundaries which can be stepped over only with a large effort (and coding). The result is not granted and future maintaining will be difficult.

And finally, the Data layer has its name to emphasize the fact, that it handles data access. Data Access Objects should be straightforward, directly set or get the data from persistence. Any other functionality is out of the scope this tier, until we are still discussing the multi-tier Architecture with separation of concern.

Business layer

In comparison with the previous places as the candidates for executing the Business Rules, the Business layer has mostly advantages. This layer name, of course, comes from the fact, that there should be the Business Rules declared and applied.

The Catharsis framework introduced the Business Facade design pattern for every Entity, as the middle-tier for Data Access and UI layers. Facades mimics the basic interface of the DAOs. Every CRUD operation is therefore defined on both layers:

    // DAO - Data access object
    public interface IMyEntityDao()
    {
        MyEntity Add    (MyEntity entity);
        MyEntity Update (MyEntity entity);
        void     Delete (MyEntity entity);
        ...
    }
    // FACADE
    public interface IMyEntityFacade()
    {
        MyEntity Add    (MyEntity entity);
        MyEntity Update (MyEntity entity);
        void     Delete (MyEntity entity);
        ...
    }

What's the benefit of the separated objects Facade and DAO if they are providing the 'same' interface?

    ==> The separation of concern.

Too easy? But incredibly effective!

DAO concern

The DAO only concern is the persistence. Its implementation can be very complicated (ADO.NET, XML, WebService) or maybe very easy (ORM), but only this is the real aim of the DAO.

The consumer of this DAO functionality, in our case Entity's Facade, is not dependent on implementation and therefore could easily work with any type of the underlying persistence type.

Catharsis for instance has built in two types of DAO for entities: Language and Translator. DB and XML files. If you cannot change DB schema, you can still use all the power of the Catharsis localization with the .XML files placed in \APP_DATA folder.

Till the DAO concentrates only on getting and setting data, your application is easily movable from one persistence type to another. Without any impacts to the Business Rules validation!

Facade concern

Facade (in comparison with DAO) is the designed, intended place for the one-and-only separated task: Business Rules validation. Facade calls the DAO's CRUD operations only when all Business requirements (Rules) are met. That also means, that some checks can even improve performance, because when validation fails, the DAO instance does not have to be created at all.

Separation of concern can be expressed as: Facade == Businss Rules holder and executor. Every piece of the application is accessing the Facade when needs data (get or set). UI, WebServices, Importers, Exporters, Batch applications... whatever, for all these is Facade the only gateway to persistence. This is the designed target for the Business Rules to be placed and evaluated.

Business layer == Business Rules holder and executor. RE-use as the design. No dependency as the implementation consequence. Validator design pattern for the declarative syntax.

How to validate business rules?

top

The previous Catharsis framework release (2.0 and previous) was built on the Check() operations on each Entity Facade. Next snippet shows the Add operation handling. Before the Dao.Add() was called, Check() was evaluated.

    // simplified example of the Facade
    // to show the ADD operation and CHECK evaluation
    
    public class MyEntityFacade: IMyEntityFacade
    {
        //...
        public virtual MyEntity Add(MyEntity entity)
        {
            if(Check(entity))
            {
                return Dao.Add(entity);
            }
            return entity;    
        }
        
        //...
        public virtual bool Check(MyEntity entity)
        {
            // Check properties one by one
            if(entity.Code.Length < 10)
            {

                AddErrorMessage(...
                return false;
            }    
            return true;
        }
    }

This approach was working. All rules where placed in one place: Facade.Check()

But yes, there was a big big down side:

...a lot of spaghetti code ...

Indeed. Every validation needed to be placed inside the if(check) { /* add error message, return false */ } . This was not only hard to write, but also hard to read. Imagine Entity with 10 or 20 properties.

To be honest, some stupid checks like the MaxLength was implemented only on the UI using the HTML maxlength attribute. Bad, very bad, but for lazy developers ...

Expression kills the Spaghetti star

This was simply dangerous. And there was a strong call for change. Spaghetti code, lot of if and {} was not possible to keep. The demand was:

Easy to write (implement), easy to read, easy to maintain

Solution should be on one side as easy as declarative syntax for Validators (UI or NHibernate style). On the other hand, we needed solution which will be ready to provide even the more complicated checks, for instance as already mentioned:

  • Code property must be unique.
  • Entity cannot be deleted until is used
  • Email can be null or match the regular expression

Expression and Validator design pattern was the answer.

Surprisingly the result, Validator implemented in the Catharsis framework, is really forcing developers to write the validation rules. Really! Surprisingly! It is easy and almost funny... How it works, will be in detail described in the next article. But even the quick observation of the code in the newly created solution will give you the answer.

Validator, design pattern

top

Every Entity Facade has its own Validator object. Validator is holding the Rule set (list), Facade is evaluating them when needed. Special rules for Add(), specific for Delete() etc.

...Validator is in fact the holder of the Business Rules; Facade is theirs executor...

So, the Validator contains the list of Rules. Those are objects which contain the Expression to be evaluated (returning true/false) and some settings, where or when should be the Rule applied. Simplified Rule class definiton:

    public class Rule<T, TFacade>
        where T : IPersistentObject
    {
        public virtual ValidateOn ValidateOn      { get; set; }
        public virtual string     ValidationGroup { get; set; }
        public virtual bool       BreakOnError    { get; set; }
        public virtual int        Order           { get; set; }
        public virtual Expression<Func<TFacade, T, bool>> Expression { get; set; }
    }

As already said, the Rules are referenced in the Validator's list. The interesting thing is that the Validator's list of Rules is static.

The best place to fill the static list with Rules is the Validator's static constructor.

And also it means, that rules are instantiated only once - for all MyEntityFacade instances there is the same static list of Rules in  MyEntityValidator, which is reused for evaluation many many times during the Web-Application lifetime.

Well, to much spaghetti description!

Validator in action

There is an entity used in Catharsis Language

    public class Language : Persistent<short>
    {
        public virtual string LanguageName { get; set; }
        // ... other not persisted stuff
    }

Yes, Language has only one property: the language name. This is in fact the code of the Culture. But even this entity (property) needs to be checked. When new Language is introduced to the application we need to be sure, that it is existing culture code. Firstly we should check the length, then assure that the culture exists, and finally because only one instance of the culture is enough, we also have to check, if the same Language is not already in the system.

Let's have a look on Catharsis built-in Validator for the Entity Language. This is the complete snippet of the LanguageValidator. Only the static constructor and the list of Rule declarations.

    public class LanguageValidator : BaseValidator<Language, LanguageFacade>
    {
        static LanguageValidator()
        {
            AppendAddUpdate((f, entity) => f.CheckLength(() => entity.LanguageName, 2, 10), true);
            AppendAddUpdate((f, entity) => f.IsLanguageNameValid(entity.LanguageName), true);
            AppendAddUpdate((f, entity) => f.IsUnique(entity.ID, new LanguageSearch
                                                                 {
                                                                     LanguageNameSearch = entity.LanguageName
                                                                 }
                                                       ));
        }
    }

The first rule is checking the length of the property entity.LanguageName. The string must be at least 2 and at max 10 letters long. The true switch at the end will break executing of the other rules when this fails.

Next rule is the call to the LanguageFacade operation IsLanguageNameValid(), which assures that provided string (e.g. 'en-GB') represents the existing culture.

And finally there is a check for uniqueness - LanguageFacade provides the operation IsUnique() (implemented in base facade, and available for every Facade in the framework) which takes the search parameters and evaluates them: is there any result coming from persistence? then the Language is already existing... return false, Entity is not unique.

Method AppendAddUpdate() is an abbreviation for creating the rule and appending it into the list. It provides the same result as the similar code:

    Rules.Add(
        new Rule<Language, LanguageFacade>
            {
                BreakOnError = true,
                Expression = (f, entity) => f.CheckLength(() => entity.LanguageName, 2, 10),
                ValidateOn = ValidateOn.Add | ValidateOn.Update,
                Order = 100,
            });

As we can see, AppendAddUpdate() creates new Rule instance with Order set to 100, and the switch ValidateOn is allowed for Add and Update. Expression and BreakOnError was provided as the operation AppendAddUpdate() parameters.

Validator declarative syntax in examples

top

Validator syntax in the Catharsis framework is as shown above very simple. We only need to append the rules to the Validator Rules list. These Rules have some switches (Order, BreakOnError, ValidateOn) which decide when or where to execute the Expression => which is the essence of the Validation.

Expression is defined:

public virtual  Expression<Func<TFacade, T, bool>> Expression { get; set; }
  • TFacade parameter is the instance of the currently validating Facade and
  • T is the Entity instance which is just evaluated, checked.
  • bool as the result of this expression can(must) be only true or false.

Any such a Rule can be appended to the Validator list (the best is the static constructor). Another words this snippet is perfectly valid:

    Rules.Add(
        new Rule<Language, LanguageFacade>
            {
                Expression = (f, entity) => entity != null,
                BreakOnError = false,
                ValidateOn = ValidateOn.Add | ValidateOn.Update,
                Order = 100,
            });

and because some of the Rule properties has also the default values, the previous snippet is the same as the next

    Rules.Add(new Rule<Language,LanguageFacade> { Expression = (f, entity) => entity.Is(), })

and thanks to the AppendAddUpdate() ValidatorBase method the same as

    AppendAddUpdate((f, entity) => entity.Is());

So in the previous example we were checking if the entity exists (is not null). That is good, because the result was the true/false statement. If wee need to check string for the value we can do it similar way:

    AppendAddUpdate((f, entity) => entity.LanguageName.Length >=  2);
    AppendAddUpdate((f, entity) => entity.LanguageName.Length <= 10);

This is absolutely perfect (but...). If the LanguageName does not fit the required length, the Facade operation Add() or Update() wouldn't persist changes, because the Rule will correctly return false (the Rule was not met).  

BUT the user won't have any information what was wrong, why changes was not persisted.

Catharsis validation extension methods

To effectively use the Validator and also keep the user informed about the incorrectness, there are few easy to use extension methods (And any other can be added). For instance we can use this expression:

    // the CheckLength() is an extension method available for Facade derived classes
    AppendAddUpdate((f, entity) => f.CheckLength(() => entity.LanguageName, 2, 10));

The CheckLength() extension has this declaration

    public static bool CheckLength(this Facade facade, Expression<Func<string>> expr, int? lowerBound, int upperBound)

The first parameter is the (this) Facade, abstract class which contains the collection of Messages (Catharsis essential feature). That means, that inside this extension method, we DO have access to the Facade's Messages collection. If anything will go wrong (Rules won't be met) we can directly append the Error Message and keep the user informed.

To finish the overview CheckLength() extension method, next parameter is the string Expression,  which will be checked for its length. Why do we expect the Expression instead of the direct string value? To use the power of the .NET Expressions. When passing the:

    entity.LanguageName

as the parameter, we can access not only the value of the LanguageName property, but also the entity as it is. We can parse the Expression to get the name of the property, name of the entity ... and assemble the meaningful Message for user, when something is wrong.

The final two parameters are the lower and upper boundaries. The lower bound can be even null and therefore allow to pass the null value as valid.

Summary

The Validator is the large step forward for the Business Rules evaluation. They are now easy to declare, easy to read and in the near future will be easy to maintain. The Validator design pattern applied in the Catharsis framework is not forcing developers to use any external tool. But any tool is easy to incorporate! And that's cool...

Comments
Add Comment
Comment
* (required field)
Detail view Printable view