Getting Started with Adobe After Effects - Part 6: Motion Blur


Upload Image Close it
Select File

Weblog of a workaholic
Browse by Tags · View All
.NET General 53
C# 47
LINQ 16
Dependency injection 12
Validation Application Block 10
Enterprise Library 10
ASP.NET 9
LINQ to SQL 8
Entity Framework 8
CuttingEdge.Conditions 8

Archive · View All
August 2009 7
September 2009 6
March 2007 5
October 2006 3
May 2009 3
July 2008 3
November 2007 3
November 2006 2
January 2009 2
August 2008 2

Meanwhile… on the query side of my architecture

Dec 18 2011 12:00AM by Steven   

Command-query separation is a common concept in the software industry. It is fairly common to model the command side as a message passing system with ‘handlers’ that process such a message. This same concept is equally usable at the query side, but is very uncommon. This article tries to change this. Three simple interfaces will change the look of your architecture… forever.

In my previous post I described how I design the command side of my architecture. The greatest part of this design is that it enables a lot of flexibility, and lowers the overall complexity of the system, just by adding a simple interface to the system and grouping business logic in a certain manner. The design is founded on the SOLID principles and brought to life with DI. Please read that post, if you haven’t yet. It will refer to its content often.

It’s funny though, that I encountered the command/handler design a few years ago, but never understood why you would use two classes (a command and a handler) for one single operation. It just didn’t seem very object oriented to me. It was only after I experienced problems with the old design, that the usefulness of the command/handler design became clear to me.

It was this type of discomfort that triggered me to think about the design of a different part of my application architecture. Although the part of the business layer that handles business processes was modeled uniformly and allowed great flexibility, that same didn’t hold for the part of the business layer that was responsible to querying. For the query side I modeled queries as methods with clear names and grouped them together in a class. This lead to interfaces like the following:

public interface IUserQueries
{
User[] FindUsersBySearchText(string searchText,
bool includeInactiveUsers);

User[] GetUsersByRoles(string[] roles);

UserInfo[] GetHighUsageUsers(int reqsPerDayThreshold);

// More methods here
}

Besides this IUserQueries interface, there were interfaces such as IPatientInfoQueries, ISurgeryQueries, and many, many more, each had its own set of methods with own set of parameters  and return types. Every interface was different, which made adding cross-cutting concerns, such as logging and audit trailing, which I often wanted to add to all queries, very hard. Besides that, I was missing the same uniformity in the design, that I had with my command handlers. Those query classes were just a bunch of random methods, often grouped around one concept or one entity, or at least I tried. Still, it looked messy and every time a query method was added, the interface and the implementation of that interface had to be changed.

In my automated test suite it even got worse. A class under test that depended on such a query interface was often only expected to call one or two of the methods of such interface, while other classes were expected to call other methods on it. This lead me to assert that a class didn’t call unexpected methods, which resulted in the creation of an abstract base class in my test project that implemented that interface, that looked like this:

public abstract class FakeFailingUserQueries : IUserQueries
{
public virtual User[] FindUsersBySearchText(
string searchText, bool includeInactive)
{
Assert.Fail("Call to this method was not expected.");
return null;
}

public virtual User[] GetUsersByRoles(string[] roles)
{
Assert.Fail("Call to this method was not expected.");
return null;
}

public virtual UserInfo[] GetHighUsageUsers(
int requestsPerDayThreshold)
{
Assert.Fail("Call to this method was not expected.");
return null;
}

// More methods here
}

For a certain set of tests I would then override this base class and implement one of the methods:

public class FakeUserServicesUserQueries : FakeFailingUserQueries
{
public User[] UsersToReturn { get; set; }

public string[] CalledRoles { get; private set; }

public override User[] GetUsersByRoles(string[] roles)
{
this.CalledRoles = roles;

return this.UsersToReturn;
}
}

This way I could let all other methods fail, since they were not expected to be called, while preventing me from having to write too much code. However, this still lead to an explosion of test classes in my test projects.

Of course al the described problems can be solved with ‘proper’ tooling. For instance, cross-cutting concerns can be added by using Aspect Oriented Programming using attributes and code weaving, or by configuring your DI container using convention based registration, mixed with interception, which uses dynamic proxy generation and lightweight code generation. The testing problems could be fixed by using Mocking frameworks, which also generate proxy classes that act like the original class.

Although all these solutions work, they are patches to fix problems with the initial design. When we validate the design with the SOLID principles, we can see clearly where the problem lies. The design violates two out of five SOLID rules.

The design violates the Open/Closed Principle, because almost every time a query is added to the system, an existing interface -and its implementations- need to be changed. Every interface has at least two implementations (one real implementation and one test implementation).

The Interface Segregation Principle is violated, because the interfaces are wide (have many methods) and consumers of those interfaces are forced to depend on methods that they don’t use.

So let us not treat the symptoms; let’s fix the cause.

A better design

Instead of having a separate interface per group of queries, we can define a single interface for all queries in the system, just as we saw with the ICommandHandler<TCommand> interface in my previous article. We need to define the following two interfaces:

public interface IQuery<TResult>
{
// Marker interface to define query objects.
}

public interface IQueryHandler<TQuery, TResult>
where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}

The IQuery<TResult> specifies an object that can be used to query data, and it defines the data it returns using the TResult generic type. In a sense it’s the counterpart of a command. This interface doesn’t have any members (it’s a marker interface) and doesn’t look very useful, but bear with me, as I will explain this later on why having such interface is very useful.

Although commands are (most often) fire and forget that (usually) don’t return a value, queries are the opposite in that we don’t expect a query to change state, and do expect a return value. Now we can define a query object like this:

public class FindUsersBySearchTextQuery : IQuery<User[]>
{
public string SearchText { get; set; }

public bool IncludeInactiveUsers { get; set; }
}

This class defines a query operation with two parameters, which will result in an array of User objects. Note btw that this query class is a Parameter Object. The class that executes this query can be defined as follows:

public class FindUsersBySearchTextQueryHandler
: IQueryHandler<FindUsersBySearchTextQuery, User[]>
{
private readonly NorthwindUnitOfWork db;

public FindUsersBySearchTextQueryHandler(
NorthwindUnitOfWork db)
{
this.db = db;
}

public User[] Handle(FindUsersBySearchTextQuery query)
{
return (
from user in this.db.Users
where user.Name.Contains(query.SearchText)
select user)
.ToArray();
}
}

Just as we’ve seen with the command handlers, we can now let consumers depend the generic IQueryHandler interface:

public class UserController : Controller
{
IQueryHandler<FindUsersBySearchTextQuery, User[]> handler;

public UserController(
IQueryHandler<FindUsersBySearchTextQuery, User[]> handler)
{
this. handler = handler;
}

public View SearchUsers(string searchString)
{
var query = new FindUsersBySearchTextQuery
{
SearchText = searchString,
IncludeInactiveUsers = false
};

User[] users = this.handler.Handle(query);

return this.View(users);
}
}

Immediately this model gives us a lot of flexibility, because we can now decide what to inject into the UserController. As we’ve seen in the previous article, we can inject a completely different implementation, or one that wraps the real implementation, without having to make changes to the UserController (and all other consumers of that interface).

Injecting the IQueryHandler interface into a consumer however, has a few less obvious problems that need to be addressed. The most important problem is that this solution isn’t as type safe as it seems at first. Say for instance that we change the previously defined FindUsersBySearchTextQueryHandler to return an IQueryable<User> instead of a User[]. Changing a return type is something I tend to do regularly during development. This can simply be achieved by letting the query object implement IQuery<IQueryable<User>>, letting the handler implement IQueryHandler<FindUsersBySearchTextQuery, IQueryable<User>>, and of course we need to change the handler to make it return an IQueryable (by removing the ToArray call). Even though we didn’t change the UserController, the whole application will now compile again, although the UserController now depends on an interface for which there is no implementation. Instead, this will fail at runtime when the DI container tries to create a new UserController for us. I rather see this fail at compile time.

Another problem is the number of dependencies our consumers will get. It is called constructor over-injection when a constructor takes many arguments (the rule of thumb is more than 5). This is an anti-pattern and is often a signal of the violation of the Single Responsibility Principle (SRP). Although it is important to adhere to the SRP, it is very likely that consumers execute many different queries, without really violating the SRP. I experienced the number of queries a class executes to change frequently, which also triggers changes in the number of constructor arguments.

This leads us to the last shortcoming of this approach, which is that the generic structure of the IQueryHandler<TQuery, TResult> leads to a lot of infrastructural code, which makes reading the code harder. Take for instance at the following class:

public class Consumer
{
IQueryHandler<FindUsersBySearchTextQuery, IQueryable<UserInfo>> findUsers;
IQueryHandler<GetUsersByRolesQuery, IEnumerable<User>> getUsers;
IQueryHandler<GetHighUsageUsersQuery, IEnumerable<UserInfo>> getHighUsage;

public Consumer(
IQueryHandler<FindUsersBySearchTextQuery, IQueryable<UserInfo>> findUsers,
IQueryHandler<GetUsersByRolesQuery, IEnumerable<User>> getUsers,
IQueryHandler<GetHighUsageUsersQuery, IEnumerable<UserInfo>> getHighUsage)
{
this.findUsers = findUsers;
this.getUsers = getUsers;
this.getHighUsage = getHighUsage;
}
}

Wow!! That’s a lot of code. And this class only has three different queries it wishes to execute.

So how do we fix these problems? As always, with an extra layer of abstraction. We need a mediator that sits in between the consumers and the query handlers:

public interface IQueryProcessor
{
TResult Execute<TResult>(IQuery<TResult> query);
}

The IQueryProcessor is a non-generic interface with one (generic) method. Remember how our query objects implemented the IQuery<TResult> interface? This is why we need it. By letting the query define its return type, we can have compile time support in our consumers. Let’s rewrite the UserController to use the new IQueryProcessor:

public class UserController : Controller
{
private IQueryProcessor queryProcessor;

public UserController(IQueryProcessor queryProcessor)
{
this.queryProcessor = queryProcessor;
}

public View SearchUsers(string searchString)
{
var query = new FindUsersBySearchTextQuery
{
SearchText = searchString
};

// Note how we omit the generic type argument,
// but still have type safety.
User[] users = this.queryProcessor.Execute(query);

return this.View(users);
}
}

See how the UserController now depends on a IQueryProcessor that can handle all kinds of queries. The UserController’s SearchUsers method now calls the IQueryProcessor.Execute method supplying the query object. Since the FindUsersBySearchTextQuery implement the IQuery<User[]> interface, we can supply it to this generic Execute<TResult>(IQuery<TResult> query) method. Because of C# type inference, the C# compiler is able to determine the used generic type and this prevents us from spelling the generic type out. And because of this, the return type of the Execute method is also known. Thus, when we let the FindUsersBySearchTextQuery implement a different interface, say IQuery<IQueryable<User>>, the UserController will not compile anymore, instead of failing at runtime. Of course it is still possible for the system not to contain a handler for a specific query, but that is much less likely to happen, and it is much easier to write some code that will validate this (either in a unit test, or in the start-up path of the application).

Now it is the responsibility of the implementation of the IQueryProcessor interface to find out which IQueryHandler it should get to execute. It takes a bit of dynamic typing, and the use of a Dependency Injection container, but can be done with just a few lines of code:

sealed class QueryProcessor : IQueryProcessor
{
private readonly Container container;

public QueryProcessor(Container container)
{
this.container = container;
}

[DebuggerStepThrough]
public TResult Execute<TResult>(IQuery<TResult> query)
{
var handlerType = typeof(IQueryHandler<,>)
.MakeGenericType(query.GetType(), typeof(TResult));

dynamic handler = container.GetInstance(handlerType);

return handler.Handle((dynamic)query);
}
}

This QueryProcessor class constructs a specific IQueryHandler<TQuery, TResult> Type based on the supplied query instance. This type is used to ask the supplied container class to get a new instance of that handler. Unfortunately we need to call the Handle method using reflection (by using the C# 4.0 dymamic keyword), because at that point it is impossible to cast the handler instance, since the generic TQuery argument is not available at compile time. However, unless the Handle method is renamed or gets other arguments, this call will never fail, and if you wish, it is very easy to write a unit test for that. There’s only a slight drop in performance when doing this, but nothing much to worry about (especially when you're using the Simple Injector as your DI container, because it is blazingly fast).

I did consider an alternative design of the IQueryProcessor interface by the way, that looked like this:

public interface IQueryProcessor
{
TResult Execute<TQuery, TResult>(TQuery query)
where TQuery : IQuery<TResult>;
}

This interface does solve the problem of having to do dynamic typing in the QueryProcessor implementation completely, but unfortunately the C# compiler isn’t ‘smart’ enough to find out which types are needed (damn you Anders!), which forces us to completely write out the call to Execute, including both the generic arguments, which gets really ugly. I was a bit amazed by this, because I was under the assumption that the C# compiler could get this.

There’s one important thing you should be aware of when using the IQueryProcessor abstraction. By injecting an IQueryProcessor, we make it unclear which queries a consumer is using. This makes unit testing more fragile, since the constructor doesn’t state what the class depends on. I believe we can live with this, but wouldn’t use this sort of abstraction too often. I wouldn’t want to have an ICommandProcessor for executing commands, for instance. The reason for this is that no extra compile time support is needed for commands, and consumers are less likely to take a dependency on many command handlers. And if they do, they are probably violating the SRP.

A consequence of this design however, is that there will be a lot of small classes in the system. I personally like having a lot of small / focused classes (with clear names), but in this scenario, it might give some overhead, since every query handler would have a constructor that takes some dependencies and stores them in local variables.

There are ways to remove that overhead, if it bothers you. You can for instance merge multiple query handlers into a single class, as follows:

public class UserQueryHandlers :
IQueryHandler<FindUsersBySearchTextQuery, User[]>,
IQueryHandler<GetUsersByRolesQuery, User[]>,
IQueryHandler<GetHighUsageUsersQuery, UserInfo[]>
{
private readonly NorthwindUnitOfWork db;

public UserQueryHandlers(NorthwindUnitOfWork db)
{
this.db = db;
}

public User[] Handle(FindUsersBySearchTextQuery query)
{
return (
from user in this.db.Users
where user.Name.Contains(query.SearchText)
select user)
.ToArray();
}

public User[] Handle(GetUsersByRolesQuery query)
{
// Query here
}

public UserInfo[] Handle(GetHighUsageUsersQuery query)
{
// Query here
}

// More methods here.
}

Although this UserQueryHandlers class really looks like the initial design we tried to prevent, there is one crucial difference:  it implements IQueryHandler<TQuery, TResult> multiple times, once per query. This allows us to register this class multiple times, once per implemented interface. This gives us all the previously described advantages.

When using a Dependency Injection framework (which is probably advisable with this model), we can often register all query handlers with a single call (depending on your framework of choice), simply because all handlers implement the IQueryHandler<TQuery, TResult> interface. Your mileage may vary, but with the Simple Injector, the registration looks like this:

container.RegisterManyForOpenGeneric(typeof(IQueryHandler<,>),
AppDomain.CurrentDomain.GetAssemblies());

This line of code saves you from having to change the DI configuration when you add new query handlers to the system. They will be picked up automatically.

With this in place we can now add cross-cutting concerns such as logging, audit trailing, and what have you. Or let’s say you want to decorate properties of the query objects with Data Annotations attributes, to be able to do validation. This might look like this:

public class FindUsersBySearchTextQuery : IQuery<User[]>
{
// Required and StringLength are attributes from the
// System.ComponentModel.DataAnnotations assembly.
[Required]
[StringLength(1)]
public string SearchText { get; set; }

public bool IncludeInactiveUsers { get; set; }
}

Because we modeled our query handlers around a single IQueryHandler<TQuery, TResult> interface, we can define a simple decorator that allows us to do this:

public class ValidationQueryHandlerDecorator<TQuery, TResult>
: IQueryHandler<TQuery, TResult>
where TQuery : IQuery<TResult>
{
private readonly IServiceProvider provider;
private readonly IQueryHandler<TQuery, TResult> decorated;

[DebuggerStepThrough]
public ValidationQueryHandlerDecorator(
Container container,
IQueryHandler<TQuery, TResult> decorated)
{
this.provider = container;
this.decorated = decorated;
}

[DebuggerStepThrough]
public TResult Handle(TQuery query)
{
this.Validate(query);
return this.decorated.Handle(query);
}

[DebuggerStepThrough]
private void Validate(TQuery query)
{
var validationContext =
new ValidationContext(query, this.provider, null);

Validator.ValidateObject(query, validationContext);
}
}

This decorator allows us to validate query objects before they get sent to their handler, without us having to change a single line of code in the application, expect of course the following single line of code in our start-up path:

container.RegisterOpenGenericDecorator(typeof(IQueryHandler<,>),
typeof(ValidationQueryHandlerDecorator<,>));

The RegisterOpenGenericDecorator extension method is part of the SimpleInjector.Extensions.dll, which is part of the download on CodePlex and available as separate NuGet package.

I’ve been using this model for some time now and there is one thing that struck me quickly, which is that in fact everything in the system is a query (or a command). If we want we can model every single operation as a query (or command). Do we really want to do this? No, definitely not, because this doesn’t always result in the most readable code. Take a look at this example:

public IQueryable<Order> Handle(
GetRecentOrdersForLoggedInUserQuery query)
{
int currentUserId =
this.queryProcessor.Execute(new GetCurrentUserIdQuery());

DateTime currentTime =
this.queryProcessor.Execute(new GetCurrentTimeQuery());

return
from order in db.Orders
where order.User.Id == currentUserId
where order.CreateDate >= currentTime.AddDays(-30)
select order;
}

Isn’t that nice? This query method delegates part of its work of to two other queries, which is fine by itself of course. However, using queries for retrieving really simple things does give too much overhead. In this case I rather use IUserContext and ITimeProvider services. This makes the method shorter and easier to read:

public IQueryable<Order> Handle(
GetRecentOrdersForLoggedInUserQuery query)
{
return
from order in db.Orders
where order.User.Id == this.userContext.UserId
where order.CreateDate >= this.time.Now.AddDays(-30)
select order;
}

So where do we draw the line between using an IQuery<TResult> and specifying an explicit separate service interface? I can’t really give any hard guidelines on that. A little bit of intuition and experience will have to guide you here. However, I think when it just returns a (cached) value without really hitting an external resource, such as the file system, web service, or database, and it doesn’t contain any parameters, and when you’re very sure you never want to wrap it with a decorator (no performance measuring, no audit trailing, no asynchronous processing); it’s pretty safe to define it as a specific service interface.

That’s how I roll on the query side of my architecture.


Republished from .NET Junkie [7 clicks].  Read the original version here [0 clicks].

Steven
395 · 0% · 101
0
Liked
 
0
Lifesaver
 
0
Refreshed
 
0
Learned
 
0
Incorrect



Submit

Your Comment


Sign Up or Login to post a comment.

    Copyright © Rivera Informatic Private Ltd Contact us      Privacy Policy      Terms of use      Report Abuse      Advertising      [ZULU1097]