Cool stuff in FubuMVC No. 1: Behaviors

This is the first post of the FubuMVC series mentioned in the Introduction post.

Perhaps the coolest thing about FubuMVC (and I’m not kidding when I say there’s a lot of cool stuff) is the behavior model. This fundamental concept enables almost all of the other coolness in FubuMVC.  The concept is this: There is no controller. I’m not trying to be cute or clever, I mean it.  When you look at some of the other MVC frameworks out there, they have a fairly strong notion of “Controller class” baked into the framework. So much so that they require a base class for you(*) to derive from. [(*) Django doesn’t require to you subclass a controller (what they call a ‘view’, confusingly) but it enables some scenarios you can’t get unless you subclass].   Main problem #1: The framework is far too invasive into my code. Stated differently: I shouldn’t have to derive from anything or import/”using” any of your code to do simple-to-medium complexity things with your framework.  And if, in an average controller class “.cs” file, I need to have more “using” statements for your framework than I need for my app code, we have major problems.

To be specific, most of these frameworks are of the “Model 2” variety of MVC.  It turns out that these frameworks, by nature of their fundamental design, encourage fat controllers (except, perhaps, Django, but I don’t know it well enough to speak definitively).  Each has a way (some better, some worse) to get some of the logic out of the controller and move it somewhere else.  But in using them, you definitely get the sense that things would be a lot easier to toss into the controller action itself and be done.  The framework doesn’t “encourage” you to spread out responsibilities.  A typical controller might have the following responsibilities:

  • Authenticate the user
  • Authorize the request
  • Bind the request to one or more model or models
  • Validate those models
  • ! Perform the primary logic of the action !
  • Respond to failure if the primary logic failed for some reason (threw an error, returned negatively, etc)
  • Determine what result to send to the client (render a view, JSON, HTTP redirect, etc)
  • Prepare the output model/json/redirect URL in order for the result to proceed
  • Transfer control to the result (with an explicit call in many cases)

Most everyone realizes that this list is far too long for the average controller action to handle. Your method will be very long, have lots of branching, and be nearly impossible to unit test effectively.  You will also be repeating a lot of code (violating the DRY principle). Problem #2: Many MVC frameworks encourage “fat” controllers.

In ASP.NET MVC, you’d move many of the earlier things to ActionFilters that run before and some of the later things into ActionResults.  The other frameworks have similar ways of adding pre- and post-logic to an action which helps with SRP and DRY.  While these help, the level of granularity and control over the web request pipeline generally isn’t enough to allow better separation and composition of responsibilities.  Problem #3: Not enough granularity and/or compose-ability (usually, it’s an after-thought).

Seeing these problems and many others, we realized that we needed to change a few things about how we approached our web framework.  We needed to have a framework that encouraged skinny controllers.   When you get down to it, the only thing the controller should be doing is the “! Perform the primary logic of the action !”.  We found that when we had multiple actions in a controller, that, while each action was skinny, the controller was still pretty fat.   This let us eventually to determine: There should be no controller at all! All that matters is the action. Since, in C#, you can’t have a method without a class around it, we still needed a class to wrap around the action method, but that’s it. This class’s sole purpose is to provide a container for the action method. It can have fields, private methods, etc. that all support that one action method, but it should only have one action method.  You can call this class a “controller” if you like, but it has very little in common with the Model 2 frameworks’ “controller” classes.

“Behaviors”

The solution we came up with involved a pipeline of small, compose-able units of functionality. Each should have its own small responsibility. Each should have the ability be able to wrap the entire pipeline to execute before, after, or around the action.  When we first built FubuMVC, we called these “decorators” because they were originally designed a lot like the decorator pattern, but not exactly. They also behaved somewhat like a chain-of-responsibility pattern, but not exactly. They also behaved somewhat like “commands” in the Front Controller pattern, but not exactly.  We struggled with the nomenclature and a word that captured the unique essence of what these things did. Hat tip to Steven Harman, he coined the term “Behavior,” and it stuck.  More than just ActionFilters and ActionResults, behaviors can hook into and override any part of the pipeline allowing for many interesting  scenarios and maximum flexibility when building complex, compositional applications (which is what we were and are still trying to do at Dovetail Software – we’re hiring, by the way).

The way behaviors work is simple. They have a very simple interface (basically one method: Invoke() and a method InvokePartial in case the behavior needs to behave differently when being invoked in a partial).  Since everything in FubuMVC runs through IoC and is fully compositional in design (versus inheritance-based as in the other frameworks), a behavior takes in the next behavior in the chain and can execute it or not.  By not executing it, the behavior takes on the responsibility for completing the entire request. An example of this would be an authorization behavior that needs to usurp the pipeline because a user doesn’t have the correct permissions to view this page.  The behavior will then send the request down another pipeline that results in an “HTTP 403 Access Denied” view being rendered.  For your convenience (and only for convenience, it’s not required), there is an abstract base class you can derive from which does some of the boring basic behavior stuff.

To learn more technical details and how-to about behaviors, you should probably read the FubuMVC Guide on the subject (yes, these guides look like Rails guides because they are a fork from Spree guides).

Conventions, the real pay-off

Up until now, you may think something along the lines of: “Meh, behaviors are cool, but they’re really just glorified before/after filters/results and don’t really change *that* much of the game.”  Of course you’d be wrong, but not unreasonable – until you consider the conventional application of those behaviors to actions.

As the sub-title suggests, conventionally applying behaviors to actions is where things get really interesting and when most people have the big “Ah-hah!” moment.  Again, I encourage you to read the “Advanced Behaviors” guide as it goes into a lot of the specifics.  This post will just be an overview and conceptual treatment of the subject.

Every app has its own conventions whether you call them that or not. When I say “conventions” I mean anything that, when a new developer joins your team, you explain to him/her that “this is the way we do things.”  For example, any method in any class in this namespace is “secure” or any method with the “[Secure]” attribute, and any method whose name ends in “Secure” are examples of conventions.  FubuMVC allows you to define those conventions in code, make them first-class citizens in your app, and use them to apply behavior(s) to your actions.  The best part is, you don’t have to use any of the framework’s attributes or interfaces or base classes. You can do it by names of types or methods, or by your own custom attributes or interfaces.  This helps lessen the number of “using” statements required to use the framework. Our goal is to have zero-to-a-few “using” statements in your app code.  When we talk about more or less “intrusive” or “unobstrusive” (look Ma, no using statements! Pure POCO!), this is what we mean.

In fact, almost everything in FubuMVC is based on your conventions. The idea is FubuMVC brings the bag of tools and you tell it where and how you want things wired up.

Summary

I realize this post was light on code and some specifics. This was intentional. I wanted this to be more a philosophical post about our approach. It is important for you to understand this as the rest of the posts in this series will make increasingly more sense as you begin to understand this and think like we do when it comes to approaching framework building (especially web framework building).  If you really want specifics and haven’t checked out the “Advanced Behaviors” guide, I invite you one last time.   As this series progresses, I’ll get into more specifics of just how deep the configurability and conventional approach runs in FubuMVC and a lot of this post will begin to make more sense.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Chad Myers

Chad Myers is the Director of Development for Dovetail Software, in Austin, TX, where he leads a premiere software team building complex enterprise software products. Chad is a .NET software developer specializing in enterprise software designs and architectures. He has over 12 years of software development experience and a proven track record of Agile, test-driven project leadership using both Microsoft and open source tools. He is a community leader who speaks at the Austin .NET User's Group, the ADNUG Code Camp, and participates in various development communities and open source projects.
This entry was posted in .NET, cool-stuff-in-fubu, FubuMVC. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://murrayon.net/ Mike Murray

    I like to think of Behaviors as single-handedly revolutionizing my usage of the MVC pattern: http://murrayon.net/2011/06/fubumvc-behavior-chains-bmvc-pattern.html

  • http://twitter.com/jmarnold Josh Arnold

    Great post, Chad. I’ve been looking forward to your FubuMVC series. Keep them coming!

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #880

  • Carlos Ribas

    This stuff sounds pretty nice, Chad.  I, too, have noticed that for some reason MVC controllers are exempt from SRP in too many developer’s minds.

  • John Simons

    Chad, your FubuCore series were awesome, and now these ones, very exciting stuff.
    If possible can you cover how you guys deal with views that change based on user role, eg:
    UserA can see some data on /products/view/1234 but UserB is not allowed to see it(and this may have implications on how the HTML is structured). I’m interested to find out if you guys create a View per role or do the logic on the View itself.

    Can’t wait for the next one!

    • http://chadmyers.lostechies.com Chad Myers

      John, that will be covered in part #10 (the number may be subject to change).  But to answer your question about view logic:  We do not have separate views (although you could do it that way but it may end up being too much extra work depending on the circumstances).  We try to avoid direct logic (if statements) in views, though we cheat in a few places.  We’ll try to deal with it by optionally rendering/not rendering partials, by dealing with it in our HtmlTags for InputFor() (determining whether it’s editable, read-only, or invisible for this user), etc.

      We may also have something like:

      x.FirstName).OnlyForPrivilege(“foo”) %>

      We try to make our privileges (the things that are securable in the app) conventionally names and flowing from our domain, our controllers, our models, etc, but we do have a few one-off privileges for special functionality in our app.

      Then we have roles that you map users to and map privileges to the roles and the users get those privileges.

  • Pingback: FubuMVC: Authentication | Rex Flex

  • http://twitter.com/ntcoding Nick

    Good explanation. I don’t think any of the articles I’ve read about behaviours show a nice hierarchical diagram – I think it would clarify the concept a lot.

    • http://chadmyers.lostechies.com Chad Myers

      That’s because they’re not hierarchical.  Jeremy calls them Matryoshka dolls, which is closer to the reality, but behaviors can fork and call out to other behaviors, so “graph” is probably more realistic.  This is a gross simplification (and very old): http://www.infoq.com/news/2009/04/fubu-mvc

      This one is pretty good: http://www.joshua-arnold.com/2011/02/fubumvc-primer-configuration-vs-runtime/

  • StarTrekRedneck

    Great series. I’ve seen my love for OO programming take a hit recently when realizing what I’m programming are just tasks or “jobs that need doing.” In agreement with your controller-less concept, I’m finding that better  flexibility is achieved by wrapping every Task in its own interface. In these implementations, the very notion of an “object” becomes really just the infrastructure needed to perform the Task– a layer that declares and manages dependencies of the task. I’m left with only datastructures and functions. Feels a bit remedial, honestly and indicative of what’s denounced as anemic domain models. What about DDD? DSLs?

  • Tomas

    Chad! Can you please continue your Cool stuff in FubuMVC posts, it’s the best that happend since free coffe!