CQRS, Implementing the Query Pattern

I have recently started reading about the Command and Query Responsibility Separation (CQRS) pattern, which is a pattern that can be applied to the architecture of a system, with the emphasise on treating requests that query the data differently to requests that perform a command.

To simplify this, if we think about the basic CRUD operations, the query separation would be for all Read operations and the command separation would cover Create, Update and Delete operations.  The overall idea is for the architecture of the system to treat command requests and query requests differently.

The operations performed on a typical application may see about 80% of all requests solely being for read only requests to display some data to the end user.  One of the aims of CQRS is that it looks to simplify the retrieval of such data, implying there is no need to always navigate through all layers / components of a system, just to collect some data from the database and return it to display.  Instead presentation layer itself can be responsible for requesting such data directly from the database.

This post is going to look at how this could be achieved using jQuery and WCF data services, which will be used to expose the entities within an entity framework model directly to the presentation layer.

Will start by looking at the WCF Data Service.  A WCF Data Service allows an Entity Framework (EF) model to be exposed and accessed using a RESTFul interface by simply consuming the Data service in a calling application.  To make things simpler to understand lets jump straight into the code.

public class WcfDataService : DataService<CustomContext>
{
	public static void InitializeService(DataServiceConfiguration config)
	{
		config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
		config.SetEntitySetPageSize("*", 5);
		config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
	}
}

The key part to a WCF data service is setting the type the data service is using, in this case DataService<CustomContext>.  The type that is specified is the EF model context.  Having set the type there is some further configuration, which is specified in the InitializeService method.

Probably the most important configuration setting is the SetEntitySetAccessRule property.  The purpose of this property is to specify the level of access you provide to any application that makes use of this service.  This can be readonly access or provide the ability to manipulate the data within your model by allowing create, update and delete commands to be run against the data service.  You can use this setting to set different access rules for the different entities your model exposes by setting the name input to the name of one of your entities , or you can specify that all use the same rule by setting the name input to *. The following code segment illustrates applying the read only access right to all entities in the model. This nicely allows us to enforce the rule that using this data service as our implementation of the query command pattern, data can only be read using this service.

config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);

There are further configuration settings you can impose on your data service, such as limiting the maximum number of rows returned from one or all entities, which can prevent potentially large data packets being sent over the wire.  The follwing example ensures that a data set only ever returns at a maximum 10 rows.

config.SetEntitySetPageSize("*", 10);

You can also enforce rules on the data being returned by applying QueryInterceptors to an entity.  A QueryInterceptor can be used to restrict what data is returned when querying an entity.  The example below applys a QueryInterceptor to the Car entity to only ever return cars that have a vehicle make of Ford.

[QueryInterceptor("Car")]
public Expression<Func<Car, bool>> CarDefaultFilter()
{
	return (Car c) => c.Vehicle_Make == "Ford";
}

A more practical use for a QueryInterceptor would be to restrict the data returned for the given logged in user. This can prevent sensitive data ever being accessed by anyone.

The examples above have explained a few simple steps you can take to expose an Entity framework model over the web.  Now we will cover consuming the data.

By adding a service reference to the WCF data service through Visual Studio in the client application, the EF model container proxy can be consumed.  By creating a new instance of the EF model container, including the URI of the WCF data service location within the constructor, you can then start using data context as if it was held locally, by executing LINQ queries against the context.  The example illustrates the above.

public JsonResult GetData(),
{
	var uri = new Uri("http://localhost.:44186/WcfDataService.svc/");
	var context = new CarEntities(uri);
	var query = (from car in context.Code44
	select new { VMake = car.Vehicle_Make }).ToList();
	return Json(query, JsonRequestBehavior.AllowGet);
}

When executing LINQ statements against the data context under the hood Visual Studio converts these LINQ statements into RESTFul URI’s which are then submitted against the WCF data service.  Using a tool such as fiddler, you can see what is actually going on when running a LINQ statement.

Converting Acceptance Criteria into Unit Tests

In a previous post I covered the concept of Behaviour Driven development (BDD), with a particular focus on the acceptance criteria that are produced as part of the approach.

In this post I want to show you how you can quickly turn acceptance criteria written using the Given, When, Then notation, into unit tests in .NET within a Visual Studio 2010 project.  The BDD .NET framework we’ll use in this post is called SpecFlow.

First off you need to Download and install SpecFlow .  The download will add three  file templates which are added to Visual Studio, which can be selected when adding a new item to a project.

One of the templates is the feature template.  The feature template is used to copy all the acceptance criteria for a given user story as written by the analysts into Visual Studio.  The only requirement is that the acceptance criteria conforms to the Given, When, Then notation.

SpecFlow - Parking.feature

You can configure SpecFlow to use your favourite unit testing framework.  SpecFlow defaults to using NUnit, but for this example I am going to use MSTest.  To change to MSTest, the following needs to be added the projects config file.

<configSections>
  <section name="specFlow"
    type="TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler, TechTalk.SpecFlow"/>
</configSections>
<specFlow>
  <unitTestProvider name="MsTest" />
</specFlow>

The feature file we just created also includes a designer file. This file breaks down the acceptance criteria and creates a test method for each line within the feature.  The class and methods are decorated with the standard unit test attributes of your chosen unit testing framework.

The next step is to actually run the test.  This will of course fail as there is no implementation, but that is the point of TDD!  This part is kind of key.  Once you have run the test and they have failed, the output of the test will include the stub test methods based on the feature added.  These can be copied from here and pasted into a step definition file.

A step definition file is the actual test file.  Here you will write the code for your tests and include any asserts required.  Use one step definition file for each acceptance criteria.

SpecFlow - Step Definition File

In this simple car parking example, I have used the Given statements to set the context for the test, allowing me to set the current state of the CarPark object.  The When allows me to perform some action, to trigger an outcome, in this case request access to the car park.  The Then’s are actually the outcome, so it is here where I include my asserts to test how the system reacts to the action for the given context.  I now have a well documented unit test case, which anyone can understand, which is not only very useful for the developer to write the code in the first place, but also for maintaining and understanding code in the future.

Behaviour Driven Development

Behaviour Driven Development (BDD) is a software design technique,  with a focus on delivering software with an “outside-in” approach, by identifying the features that provide value to the business.  This can be achieved by looking at the system from the point of what functionality the user interface will provide and by focusing on the process and not the technology or architecture of the system.

The typical artefacts that are produced following the BDD technique, is a set of user stories, which correspond to the user-centric features that bring value to the system.  Each story will contain of a number of acceptance criteria scenarios, that together should cover the functionality, coupled with the testing criteria that is required to be implemented in order that the story can be signed off and considered done.  A good guideline to follow is that a typical user story should contain at a maximum 5-6 acceptance criteria, if any more are identified then it is worth considering breaking the user story down into multiple user stories.  In addition to this, a story should normally aim to include acceptance criteria for about 80% of the stories functionality.

One of the main aims of BDD is to bring collaboration between technical and non-technical personal on a project.  This aim is achieved by bridging the gap between departments within a business by using a small and very specific vocabulary when writing acceptance criteria, that should be written from the perspective of the user, not the programmer.  The acceptance criteria can be read and understood by anyone in the business such as the stakeholders, business analysts, developers, testers, managers and even the end users.  Each story should go through an iterative review process including all teams to ensure the required functionality of each story is captured correctly.

A typical acceptance criteria scenario would be written in the following format.

Given        [Context]

When        [Event / Action]

Then         [Observable Result]

A simple example

Given that I want to park my car in car park A

And the car park is currently full

When I request a ticket to gain entry to the car park

Then I should be notified that the car park is full

And the car park barrier should not open

As a developer I could take an acceptance criteria such as above written in this style and be able to know exactly what I need to implement in order to meet the goal, so that I could provide a relatively accurate estimate fast.  As a tester I could take this and straight away I have my core test case and I can start thinking about producing automated tests to cover the criteria, if all acceptance criteria pass when testing, the user story can be considered done.  As a stakeholder I can ensure that the functionality I expect to be provided by the software, will be delivered

BDD supports Test-Driven Development (TDD).  The acceptance criteria provides the developer with a set testable operations which form the unit tests, which can be used to drive the development using TDD.  There are a number of open source frameworks which aid unit testing the acceptance criteria.  In a future post I will explore one such framework called SpecFlow which can be used with .NET 4.0.