var blog = new ThoughtStream(me); RSS 2.0
 Monday, June 23, 2008

Over the weekend, I spent some time refactoring some business rules in my current project, to use the ISpecification<t> framework that I previously created.

One of my coworkers had asked about logical groupings - making sure that we can handle complex logic such as, "(this and this) or this". Since my project actually made use of logical groupings I wanted to share with the world and show how easy it is.

In this example, I have a Date Range that is being selected – a From date and a To date. The rules are as follows for validating the range:

  • If a From date and a To date are provided, the From date must be equal to, or before, the To date
  • Or, you can specify a From date without To date
  • Or, you can specify a To date without From date

The following is the actual code that I’m using to define these business rules, via the ISpecification<t> framework. 

PredicateSpec<ExtractSearchCriteria> fromDateProvided = new PredicateSpec<ExtractSearchCriteria>(crit => crit.FromDate > DateTime.MinValue);
PredicateSpec<ExtractSearchCriteria> toDateProvided = new PredicateSpec<ExtractSearchCriteria>(crit => crit.ToDate > DateTime.MinValue);
PredicateSpec<ExtractSearchCriteria> fromDateBeforeToDate = new PredicateSpec<ExtractSearchCriteria>(crit => crit.FromDate <= crit.ToDate);  
 
ISpecification<ExtractSearchCriteria> validDateRangeSpec =
    (
        (fromDateProvided.And(toDateProvided))
        .And(fromDateBeforeToDate)
    )
    .Or(
        fromDateProvided.Not(toDateProvided)
    )
    .Or(
        toDateProvided.Not(fromDateProvided)
    );

Here, I am defining the core of the business rules – to check if the From date was provided, to check if the To date was provided, and to check if the From date is before or equal to the To date. From these core specifications, I can build the aggregate spec that handles all of the stated rules for validating the date range.

There are three logical groupings using parenthesis to represent each of the business rules that can comprise a valid date range. The first logical grouping checks to see if both a From and To date are provided, and checks if the From date is before or equal to the To date, if both are provided.

(
    (fromDateProvided.And(toDateProvided))
    .And(fromDateBeforeToDate)
) 
 

The second group is specified with an Or, and checks to see if we provided a From date but not a To date.

.Or(
    fromDateProvided.Not(toDateProvided)
)

And the third group also uses an Or, and checks to see if we provided a To date but not a From date.

.Or(
    toDateProvided.Not(fromDateProvided)
)

The end result is that we have one of three possible ways for this date range to be valid – all logically grouped and relatively easy to read (compared to a bunch of if-then statements, at least). Even better – we re-used two out of three simple ISpecification<t> objects to create all of the rules for this validation check. This helps to create a validation that is not only easier to read, but easier to maintain and enhance in the future.

Monday, June 23, 2008 9:43:24 AM (Central Standard Time, UTC-06:00)  #    Comments [0]. Trackback 
Tags: .NET | Analysis and Design | Design Patterns | Lambda Expressions | Principles and Patterns | Refactoring

Navigation
About Me
View Derick Bailey's profile on LinkedIn

Send mail to the author(s) Contact Me
Archive
<June 2008>
SunMonTueWedThuFriSat
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2008
Derick Bailey
Sign In
Statistics
Total Posts: 91
This Year: 91
This Month: 0
This Week: 0
Comments: 40
Themes
Pick a theme:
All Content © 2008, Derick Bailey
DasBlog theme 'Business' created by Christoph De Baene (delarou)