Cross-Cutting Concerns in C#

This article is half brain-dump and half thinking out loud to clarify some concepts around cross-cutting concerns. To start with, a common example used to explain OO principals is that of geometric shapes.

interface IShape {
 float GetArea();
}

abstract class Shape : IShape {
 abstract float GetArea();
}

class Square : Shape {
 float length;
 override float GetArea() {
 return length * length;
 }
}

class Circle : Shape {
 float radius;
 override float GetArea() {
 return Math.Pi * radius * radius;
 }
}

These examples are great, but what happens when you run into cross-cutting concerns? We want to obey the single responsibility principal, right? For example, what if I want logging when a user gets the area of a shape? Should I put logging code into every constructor, property, and method? What if I want to write the shapes out to a database or transmit them to a web service as JSON? What if I want security for certain shapes (not everyone can be trusted with trapezoids)? Can business requirements be a cross-cutting concern?

Use Cases

Walking through some common cross cutting concerns can be enlightening. Maybe we can classify them somehow? Logging, security, validation, data/caching, change notifications, ???.

  • Logging – Tracing information, parameter values, etc. The most basic method involves running code before and after method execution but it can get more complicated (catching exceptions during the run, for example).
  • Validation – If a property is validated with certain values, we may want to reuse that validation logic outside of the property setter – in the UI for example. This would involve adding an event to the class, adding an interface to the class, and adding code to run before and after property changes.
  • Security – Methods, properties, or instances of objects may need to be restricted. Flexible as to authentication mechanism, it would also be best to avoid cluttering code with calls out to an ACL service.
  • Data Backing – We want to source our model objects to a data store, but of course we don’t want any of that dirty data code infecting them. I can think of a few ways to accomplish it, but NHibernate uses some form of inheritance, requiring virtual properties. We’d want to execute code when the object is instantiated as well as when any child objects are requested through collections, etc.
  • Property Changes – We may want our objects to raise an event when their properties change, but we don’t want to manually modify every single property and include the same event raising boilerplate code in each class. Doing this properly means adding an event to the class, making the class implement an interface, and adding code to run before and after property changes.

So here are some of the types of changes we want to make to a class in order to handle these cross-cutting concerns:

  • Run code at various times during an object’s life-cycle (instantiation, property get or set, before or after a method call).
  • Force a class to implement an interface, including adding new properties and methods.

The principal of YAGNI is something to be aware of, but I’m thinking particularly about how to structure new code so that it’s open to the most common kinds of extensions. If there is a way to do that without introducing overhead, then I believe it’s worth the effort.

Strategies

So how can we implement some of these cross-cutting concerns without writing a ton of copy/pasted code?

Decorators

With a decorator we can inject new code and implement new interfaces, but only for virtual methods and properties, or those defined by an interface.

public class ShapeDecorator : IShape // or could inherit the abstract Shape if we wanted
{
    public ShapeDecorator(IShape item) {
        this.item = item;
    }
    private readonly IShape item;
    public float GetArea() {
        // we can put our decorator code here - validation, logging, security, etc.
        return this.item.GetArea();
        // or here
    }
}

But this can’t handle all cases – for example we can’t inject code before or after properties defined outside of IShape. We could, through reflection, detect the properties, but we can’t generate them on our ShapeDecorator class. Well, okay, we could maybe generate them, but at that point we’re halfway towards doing our own code weaving, anyway.

Mixins

I read somewhere that extension methods supposedly function as mixins for C#, but I find that lacking as extension methods don’t allow for attaching state to an object. To be clear, when I talk about mixins I mean constructing concrete classes from different components, each with their own methods and properties.

With mixins, theoretically we could do whatever we wanted as far as object composition. In my ideal world this might be baked into the language. We’d need a syntax for specifying a composed type to use in variable declarations and method input and return parameters:

var result = compositionRoot.Generate<IShape>() // var here would be short for some multi-interface syntax (IShape+ILogger+IDataObject+INotifyPropertyChanged)
                .Implement<ILogger>()
                .Implement<IDataObject>()
                .Implement<INotifyPropertyChanged>();
result.PropertyChanged += result_PropertyChangedHandler; // we'd have auto-complete and property inspection here
result.GetArea(); // this could log via ILogger and possibly pull data per IDataObject

This would still leave us a statically, strongly typed environment but with a lot more flexibility for handling cross-cutting concerns without code weaving. Speaking of which…

Code Weaving

Code weaving is a powerful technique that isn’t just applicable to AOP. Code weaving refers to rewriting the IL source code generated by the compiler before completing generation of our final executable or library file. Depending on the exact tool used, we can definitely inject code at any point we want, and we can also force interface implementation. Because we’re re-writing the code during compilation, the sky is theoretically the limit on what we could accomplish (well, the IL is the limit, anyway).

What are the limits? There is definitely added complexity in working with a third party tool. Things like auto-complete won’t work as expected because some properties and methods are applied during compilation instead of statically in a code file.

One aspect I particularly like about code weaving is that it gives insight into what might be lacking in a language. If someone has taken the time and put in the effort to pull apart the code and re-write it to get some particular functionality, it’s worth considering if what they’re accomplishing should be handled by the language or core library. At least, that’s what I get when I look at a list of what can be accomplished with Fody or PostSharp. C#/.Net is great for a lot of things, but there are still many tedious, brittle implementation details and need for tons of boilerplate code (see INotifyPropertyChanged).

Fody

Fody is a great, impressive code weaving project executed mostly by a single developer.

My issues with it are that some of its items are not general purpose enough. It can inject code at method boundaries, but not at property boundaries. It has modules to handle implementing specific interfaces (eg: INotifyPropertyChanged), as well as a module to allow interface mixins, but they’re separate.

Since it’s free and open source, however, it’s the only realistic game in town for a small developer. In performing this brain dump, I think I can meet most of my needs with Fody, it’s modules, along with a newly created property code injection.

PostSharp

Post sharp is great, except that it costs some big bucks for the full version, so as a small developer I can’t use it for personal or open source projects. It definitely allows for code injection, and it includes interface implementation, although I was unable to test this as it’s a paid-only feature.

PostSharp’s version of code weaving uses attributes extensively, which is better than cluttering code with the cross-cutting concern itself, is still cluttering the code. I’d prefer specifications for aspects to take place in a fashion similar to the composition root of DI/IoC.

2 thoughts on “Cross-Cutting Concerns in C#

    1. Matthew – I did try out the free version of PostSHarp, and I was pleased with the capabilities as well as the general polish of the solution. I just kept bumping into the limitations (can’t add interfaces to classes, for example), which was frustrating so I sought out an open source solution. I will check out Castle DynamicProxy, too, thanks!

      Also, really looking forward to reading the full version of your AOP book!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s