Guidelines aren’t rules


I’m a huge fan of the Framework Design Guidelines book.  It provides great instruction on creating reusable libraries, based on Microsoft’s design on the .NET Framework.

But it’s important to remember that guidelines aren’t rules.  Guidelines are recommendations based on a set of perceived best practices.  Even a “DO” or “MUST” guideline can be broken in rare cases where following the guideline creates a negative user experience.  In these cases, you need a pretty overwhelming case against the guideline to not follow it.

ASP.NET MVC Example

Looking at Action Filters in ASP.NET MVC (Preview 2), I found an…interesting naming convention for creating action filters:

public class AdminRoleAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(FilterExecutingContext filterContext)
    {
        if (!filterContext.HttpContext.User.IsInRole("Administrator"))
            throw new ApplicationException("For cool dudes only.");
    }
}

In the ASP.NET MVC framework, we’re required to create a custom attribute to create action filters.  Taking a look at the method I override, when exactly does this method get executed?  Is it before, after or during?  The present tense of the verb implies that it’s during, but that’s not possible.  I have to deduce that it gets executed before the action.

The naming convention here is a little strange, with “OnActionExecuting” the method for “before” and “OnActionExecuted” for “after”.  This naming style is normally used for event raising, where you’d create protected “On” methods that would in turn raise the event.

In the ActionFilterAttribute, there are no events being raised, so this guideline shouldn’t apply. That’s where more clear names like say, “BeforeAction” and “AfterAction” would be far more explicit about when these methods get called.

Other frameworks

Action filters are fairly common in MVC frameworks.  I wouldn’t want to call out this design choice without looking at a few others, so let’s check out what the other cool kids are doing.

MonoRail

To create a custom filter in MonoRail, you don’t need to create a new attribute type.  In the ASP.NET MVC example, I’d decorate my controllers with the specific “AdminRole” attribute.  The filters in MonoRail are somewhat decoupled from when they’re executed:

public class AdminRoleFilter : IFilter
{
    public bool Perform(ExecuteEnum exec, IRailsEngineContext context, Controller controller)
    {
        if (!context.CurrentUser.IsInRole("Administrator"))
        {
            controller.Flash.Add("For cool dudes only.");
            controller.Redirect("", "login", "login");
            return false;
        }

        return true;
    }
}

You then decorate your controller with the FilterAttribute, specifying when the filter gets executed:

[Filter(ExecuteEnum.BeforeAction, typeof(AdminRoleFilter))]
    public class AdminController : SmartDispatcherController

Note the nice pretty name, “BeforeAction”.  Other values for the ExecuteEnum include “AfterAction”, “Around”, “AfterRendering”, etc.  These names are very expressive for exactly when this action should get executed.  I don’t get names like “OnViewRendered” or “OnActionExecutingOhAndByTheWayOnActionExecutedAlso”.

Non-.NET frameworks

Rails has equally expressive manner of doing actions.  This makes sense as MonoRail was heavily influenced by Rails.  In Rails, you can specify then name of the methods to be executed:

class BankController < ActionController::Base
    before_filter :audit

    private
      def audit
        # record the action and parameters in an audit log
      end
  end

  class VaultController < BankController
    before_filter :verify_credentials

    private
      def verify_credentials
        # make sure the user is allowed into the vault
      end
  end

Rails provides many descriptive methods (which can be chained) to modify the filters for a particular controller: “before_filter”, “after_filter”, “around_filter” and others.  Note again the obviously named methods, where the time the filter executes is explicitly named “before” or “after”.

Finally, in Django, filter-like features are created through the Decorator pattern, where you explicitly wrap a controller action in another method that adds functionality:

from django.contrib.auth.decorators import login_required

def my_view(request):
    # ...
my_view = login_required(my_view)

Instead of specifying when the filter is executed, it’s up to the implementer of the decorator to determine when to call the underlying action.  This gives quite a bit of flexibility to the designers of the decorator, but takes it away from the developer, as they can no longer specify when the filter should execute.

Intention-revealing interfaces

In the end, the difference between a good and not-so-good framework can be found in its success in creating Intention-revealing interfaces.  If you can’t look at a component or class and infer its responsibility and purpose without exercising the component, chances are good that you have an intention-revealing interface.

In the ASP.NET MVC filters, I had to guess which one executed before the action, as the word “before” was nowhere to be seen.  When guidelines directly contradict a clear, intention-revealing interface, it’s safe to choose to not follow the guideline.  If we had an ActionFilterAttribute that had only “BeforeFilter” and “AfterFilter”, I don’t think the FDG police will come knocking at anyone’s door.

Dear software tool vendors, RE: I’m breaking up with you