Object-orientation is the predominant programming paradigm nowadays: It is mature and well-understood by most developers. Although it had been well-known since the seventies, it reached the mainstream after Bjarne Stroustrup added the concept of “objects” to the C language to get more powerful tools to represent the behavior of entities. It was definitely a revolutionary approach. However, as soon as object-oriented programming (OOP) started gaining momentum and began to be widely used in projects, developers spotted immediately an inherent, almost structural, problem.
OOP works in business enterprises by mapping identified business entities and relationships to classes, adding polymorphism and encapsulation and, overall, promoting code reuse. OOP is then quite good at describing business processes through components and therefore at dealing with the concerns associated with an entity and its software counterpart-the class. Where OOP inherently fails is at dealing with cross-cutting concerns.
Agreed, probably the term “fail” is misplaced here and exaggerated. But for sure OOP is not as good with cross-cutting concerns as it is with modeling. Developers then started the quest for better techniques consistent with the OOP paradigm to deal with this, and prevent the need for code-injection, code-duplication or interdependencies.
The Problem of Cross-cutting Concerns
A cross-cutting concern, by definition, affects not just a given family of classes but many classes in a system. Common examples of cross-cutting concerns are logging, tracing, profiling but also authentication and authorization, error handling and application-wide caching and pooling. In plain OOP practice, nearly every class requires injections of code to address cross-cutting concerns. In real-world-size projects, this amount of extra code may become significant, and the practice of duplicating it across various classes becomes less attractive, although unavoidable.
At the foundation of OOP is the principle that every class should do one and only one thing. At the foundation of real-world software, though, is the fact that cross-cutting concerns should be properly dealt with. Doing so, however, often requires plenty of repetitive, admin-style code for things like logging, tracing, error handling, pooling, threading, and so forth. In the end, implementation of concerns is usually either based on boilerplate code cut-and-pasted from other projects or totally left out.
Already in the mid-1990s, aspects were introduced as a way to wrap cross-cutting concerns into separate code that could be managed, tested and debugged individually before being applied to target methods at run time. Aspect-oriented programming (AOP) never really took off, but flavors of it reformulated as attributes are to be found in a variety of frameworks. You find aspects, for example, in Microsoft Unity and in IoC containers. In ASP.NET MVC, action filters expressed as attributes are just another form of aspects because they add extra behavior and logic to the pre- and post-execution phase of controller methods.
Action Filters as Aspects
Implemented as an attribute, an action filter provides a declarative means to attach some behavior to a controller’s action method. By writing an action filter, you can hook up the execution pipeline of an action method and adapt it to your needs. In this way, you also remove any logic from the controller class that doesn’t strictly belong to the logic of controller methods. In doing so, you also make this particular behavior reusable and, more importantly, optional.
In ASP.NET MVC, action filters are ideal for implementing solutions to cross-cutting concerns that affect the life of your controllers. A canonical example of an action filter is, in fact, the Authorize attribute to attach an authentication filter to any marked method; another good example is the Exception action filter aimed at providing a centralized way to capture and handle exceptions originated by controller methods.
Conceptually speaking, action filters are very similar to aspects. When you create action filters, you can indicate whether the specific action should take place before and/or after the method. An action filter is a class that implements the IActionFilter attribute, as described below.
1 2 3 4 5 |
public interface IActionFilter { void OnActionExecuted(ActionExecutedContext filterContext); void OnActionExecuting(ActionExecutingContext filterContext); } |
The two methods just let you indicate which code runs before and after the controller method. The ASP.NET MVC framework comes with a long list of predefined, built-in filters; others can be found in open-source projects such as latest MvcMate at http://mvcmate.codeplex.com.
Validation by Contract
In ASP.NET MVC, each request ends up being mapped to a controller method. Each controller method has its own signature and a bit of business logic that makes it accept, say, only certain values of a given type. How would you verify that only correct values are being passed?
Let me put the question the other way around. If an invalid value is passed, what should be the behavior of the method? Should it just proceed as far as possible and likely crash at some point? Should it just log the invalid parameter and return or throw?
Preliminary validation of input parameters is a fundamental aspect of coding. It is so essential and vital for code to be really close to common sense; but just as common sense it is sometimes not so common. This observation brought Bertrand Meyer to formalize a software correctness methodology named Design-by-Contract. Design-by-Contract is based on the idea that each software module should have a contract that formally describes what comes in and what comes out of the method.
Today, Design-by-Contract is implemented in C# through a relatively little known feature-Code Contracts. In .NET, Code Contracts use preconditions to assert preliminary conditions to be verified for the method to run. Code Contracts also use postconditions to assert conditions determined by the execution of a piece of the method. In a way, Code Contracts add a light aspect-oriented flavor to .NET code because it makes it easier to define parameter validation using a syntax that, although not attribute-based, is at least conceived as assertions.
Inside Code Contracts
.NET Code Contracts are formed by three main types of contracts: preconditions, postconditions and invariants. Of the three, I reckon that preconditions are the most important contract and the most commonly used one. Postconditions and invariants come more into play as you progress towards the building of a true and full-fledged domain model. Preconditions are instead a more basic type of contract largely equivalent to the If-Then-Throw pattern. For this reason, they tend to be quite common.
The If-Then-Throw pattern suggests you place a barrier of conditional statements at the very beginning of each method, possibly in any class you write. Each conditional statement ensures that a Boolean condition based on input values hold true. If the condition is not verified, then the code throws an exception.
Preconditions have the same functional effect as an implementation of the If-Then-Throw pattern except that preconditions require you express the condition as it is required to be and not its negation. For example, suppose you have a method that gets an integer and the integer is expected to be greater than zero. Here’s how you would write the method using the If-Then-Throw pattern:
1 2 3 4 5 6 |
public ActionResult Increment(Int32 value) { if (value <=0) throw new InvalidArgumentException(); : } |
Here’s instead how to rewrite it using precondition contracts in .NET:
1 2 3 4 5 |
public ActionResult Increment(Int32 value) { Contract.Requires<InvalidArgumentException>(value >0); : } |
Code contracts must be specified in the body of methods and inserted via plain code. The class Contract defined in the System.Diagnostics namespace exposes a bunch of static methods, one for each type of contract. According to the team, the choice of having developers use plain code rather than attributes was made with the precise purpose of keeping contracts to a declarative level but more flexible than with .NET attributes.
At a quick comparison, the code based on If-Then-Throw expresses the condition in its negated form; the precondition format instead tells you explicitly about the required condition: value >0. This means that contracts also work well as documentation for unit testers and other developers. At any time, in fact, the conditions expected on parameters can be consulted in their positive form.
By also adding postconditions, you end up having a clear set of statements at the beginning of each method that show what’s required for the method to operate and what’s going to be produced at the end of the work. It’s the x-ray of the method; you can learn all of it from a single place.
Contracts in ASP.NET MVC Code
As you might imagine, Code Contracts are not specific to ASP.NET MVC, but are rather a fairly generic API that works with any type of .NET application. However, in ASP.NET MVC you certainly need to add a validation layer within controllers; By using contracts, the code stays succinct and clear and keeps the noise of if statements to a bare minimum. Moreover, this guarantees that, if invalid parameters are passed, then the API can capture them and throw appropriately.
Sometimes you might want to distinguish situations in which patently wrong values are passed as parameters and situations in which parameters are omitted. In the latter case, you can use valid default values in the signature to ensure that if the parameter is left empty then valid values are set anyway.
When it comes to precondition contracts, you can choose between two forms ofRequires statements: regular and generic. A generic Requires<TException> contract just throws the specified exception if the contract is not fulfilled. A regular Requirescontract, instead, fires an API specific exception-the ContractException exception. You can catch contract exceptions by registering an event handler for the ContractFailed event. Here’s how to set it:
1 |
Contract.ContractFailed += (YourExceptionHandler); |
The exception handler looks like the one shown below:
1 2 3 4 |
static void Contract_ContractFailed(Object sender, ContractFailedEventArgs e) { ... } |
It is also worth noting that regular Requires statements are omitted when the project is configured in debug mode. This point introduces, however, a subtle point about contracts that needs be explored further.
Implementation of Code Contracts in .NET
To use Code Contracts, you reference System.Diagnostics and start using the Contract class in your code with all of its static methods. Interestingly, if you just compile and run the code-without doing anything else around the project-it brilliantly fails and throws an exception. Using .NET Reflector, you can see the following code in the Requires<T> method (and in all other methods on the Contract class):
1 2 3 4 |
public static void Requires<TException>(bool condition) where TException : Exception { Contract.AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>"); } |
If this is how the Requires<T> method is implemented, how is that it actually works? The key is the rewriter. Code Contracts require the use of an external tool-the rewriter-which runs after the compiler and rehashes bytecode so that any code required by preconditions and postconditions is inserted where it belongs. Without the rewriter, Code Contracts will be an empty box.
At the moment, the rewriter is not part of the .NET Framework-a very debatable decision. You have to download it separately as a Visual Studio extension from http://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-1ce455f66970. The rewriter should also be explicitly enabled from the project property pages, as shown in Figure 1.
Note that, depending on which Requires syntax you opt for, you may also be asked to tweak the default Code Contracts settings. For example, if you opt for Requires<T> then you also need to change the value of the Assembly Mode parameter in Figure 1.
Final Thoughts on Aspects
I started this article with a mention of aspect-oriented programming and its impact on mainstream object-orientation. The problem of the most effective way of adding aspects to OOP is still open. In the .NET space, there are two main routes: attributes and filters injected by IoC frameworks (e.g., Unity). In ASP.NET MVC, you can use attributes in the form of action filters to wrap the execution of a controller method between a pre- and/or post-execute method. What the filter does just adds aspects to the controller method without impacting its structural business logic.
Code Contracts are another form of aspects that targets specifically the realm of parameter validation and code correctness. Child of the Design-by-Contract philosophy, Code Contracts in .NET come as ad hoc code injected at compile time. When you read back the code, though, you find in your source code only a bunch of declarations about what’s required and what’s ensured. It all look like assertions, but the effect is far deeper and preserve significantly readability.
Load comments