- Edsger W. Dijkstra (paraphrased)
- Total adherence to principles: The framework should itself abide by the fundamental principles of good software design and it should require you to do so as well. It should make it as difficult as possible to flout them and, preferably, punish you for doing so by making everything harder.
- Completely compositional: It should itself be based entirely off of composition and either not use inheritance at all, or only in very minor circumstances and certainly should not require you to derive from any framework base classes if you don’t want to. Convenience base classes are fine, but should not be imposed upon the framework consumer. The framework should encourage and reward compositional design and frustrate and punish inheritance mis-design.
- Model based: It should encourage and reward you for having a centrally defined model (or models) and be based around one itself. The framework should itself use one or more models to represent its own internal structures (configuration, routing, etc) and expose these for manipulation by the consumer. It should facilitate you using your own models in your actions and views.
- Not have any notion of controllers: The framework itself has one controller that processes the routes and this satisfies the “C” in MVC. The words “controller” should not appear anywhere else in the framework or outside. It should completely break you of the notion that you need a class called “controller” because this is just wrong and leads you to do all sorts of bad, nasty, and dumb things.
- Statically typed: In line with the “Model based” requirement, it should facilitate inspection, reflection, and convention-based development where everything (and I mean everything) flows OUT from the model (not into the model, like ActiveRecord foolishly does). All your validation rules, authorization rules, binding rules, display rules, input rules, etc. should all flow from decorations and conventions attached to your model. Which leads to the next requirement….
- Conventional top-to-bottom: The framework itself should expose all of its own conventions and allow them to be replaced. It should encourage and reward conventional development and frustrate and punish you for doing one-off stuff except as a last resort. And I don’t mean Rails’ conventions where it’s my-(lame)-way-or-the-highway, I mean real conventions – YOUR conventions where you can define them and reuse them. This is only possible with static typing because you can’t get the level of introspection and reflection necessary to pull this off with dynamic typing and string-only reflection.
- Based on IoC: No more IoC as an afterthought. I’m not going to have this debate. If you disagree with this you are wrong. If you disagree then you simply haven’t seen the power of IoC done right in a framework and in an app. Try playing with FubuMVC for a few weeks and look at some of our samples or come hang out at Dovetail for a day or two and I guarantee you will no longer disagree with me. The power this provides is so overwhelming and fundamental that is perhaps the requirement of requirements.
- Mostly model-based conventional routing: Your routes should flow out, conventionally, from the model as much as possible allowing proper REST scenarios. This is extremely important in a CRUD app. Specific actions (for service actions like “send email” that aren’t based on your main domain model) should be easily created, defined, and conventionally routed.
- Action-based: In line with the whole “no controllers” and “completely compositional” requirements, it should encourage each action to be tiny (a few lines at most). All things like model binding, validation, object/persistence retrieval, should be moved into composable “behaviors” that are outside of the action since they are not the concern of the action. Each action should be a single class with a single public method that does that one thing. No more multiple-50-plus-line methods in your dripping-with-inheritance “Controller” class. NO!
- Minimized code-in-view: This one fits with the “conventional” and “compositional” requirements. The framework should provide ways of micro-HTML generation that flows from the model and through conventions. I’m not talking about lame loosely-typed “HTML helpers”, I mean real meaty, conventional, model-based micro-HTML generators. The framework should also make using partials a natural, normal, and preferred way of compositing screens. It should support the ability to render simple HTML no-code partials, or to execute a partial action through the framework to render a chunk of HTML, JSON, etc.
- One Model In, One Model Out: Every action method should take in one model (not primitives) in and return one model out (no ActionResult nonsense or framework-dependent inheritance silly classes). The action should not tell the framework which view to render or where to go next unless the action’s purpose is specifically for that (such as a post-successful-login routing action). The framework shall conventionally determine how to bind the models going in and render views from the outgoing model
- Zero touch: My actions should have ZERO knowledge of the web framework. I shouldn’t have to “import” or “using” or “require” any of your framework stuff. My actions should be simple POO’s like this (note no “using FubuMVC”)
- Independent of other frameworks: I shouldn’t have to use your stupid “ORM” or your favorite JavaScript framework which is 2 weeks old and already outdated. This is made easier, if not entirely possible, by the “IoC” requirement, by the way.
- Testing as a first class citizen: I debated whether or not I should even put this in here because, for me, this is like putting “Step 1: Breathe” at the top of any list of instructions. Generally, if you care about any of the other requirements, this one is essentially a “Step 0” requirement kinda like “Use a computer” or “Run on x86 processors”.
- 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)
- First, set up the Stringifier
- Second, new up a DisplayConversionRegistry to help you register your conventions with Stringifier (you don’t have to do this, but it makes it easier unless you want to write your own API for doing convention registration).
- Then we explain our conventions to the registry. In this case, I’m using a silly example of grabbing the text of the “Description” attribute hanging off the property. I chose to do it this way to show you your conventions can do more than just grab the value of the property. They can work with the type metadata and not just the value itself. A quick aside: When you here us Fubu guys going on and on about making the most of static typing while we’re using a statically typed language, this is the kind of stuff we’re talking about.
- Next we have the registry dump all its conventions into Stringifier. This would normally be done during app start-up/config time.
- New up a DisplayFormatter and satisfy its dependencies. Also use ReflectionHelper to get a static reflection reference to the property. Normally HtmlTags does this for you in a web app situation. I would recommend if you’re using a web app to use HtmlTags, otherwise, make sure to bake IDisplayFormatter into whatever framework you’re using.
- Perform the actual conversion. You’ll notice what I did her. I print out the simple ToString() value, and then I print out what DisplayFormatter did.</ol> Here are the console output results:
Converted: This is an example date time valueIn practice, huge pay-off
If you bake Stringifier and IDisplayFormatter into your app, and use DisplayConversionRegistry to registry all your conventions in your app configuration/bootstrapping, you can achieve a consistent, conventional approach to displaying values throughout your app. You can stop worrying about which method to call to convert this date/time into whichever format you need it in in a given context.
One really cool effect this has is that now your display formatting is also *PLUGGABLE*. For us, this is huge since our customers like to customize our app significantly. Some want to display Cases this way and Date/Time’s that way and so on and so forth. We can very easily register different conventions into StructureMap for each individual customer to achieve different formatting strategies according to their whims. Try to do *that* in *your* app without using conventions and IoC container pluggability 🙂
Some other ideas
Before I leave you, I wanted to mention a few other conventions that we use that I thought were cool and might help you to grok the power of stringification.
On our domain entities, we have some properties of type DateTime that we only really use the Date portion. For example, contract expiration date. We generally don’t care about the time, just the day. We established a convention in our domain that if a property is of type DateTime and the property ends in the word “Date” (for example “ExpirationDate”), then it’s a date-only property. When we display these, we use a custom DateTime format that only displays the Date portion. Likewise, if the property ends in the word “DateTime”, then it’s a date and a time (for example, “CreatedDateTime”).
We also had another problem in that we wanted dates on this one portion of a page to be displayed in a certain format (long date/time, “Friday June 10, 2011 5:09 PM”). The portion of the page happened to be a FubuMVC partial with an input model (because partials in FubuMVC are also “one model in, one model out”). So what we did is to bind a convention to type DateTime but only if the property was on a specific view model. Here’s the code:
IfPropertyMatches<DateTime>(p => p.DeclaringType == typeof(LogSeparatorDateViewModel)) .ConvertWith<IDateTimeFormatter>( (formatter, date) => formatter.Format(date, "{0:D}"));
- New up a DisplayFormatter and satisfy its dependencies. Also use ReflectionHelper to get a static reflection reference to the property. Normally HtmlTags does this for you in a web app situation. I would recommend if you’re using a web app to use HtmlTags, otherwise, make sure to bake IDisplayFormatter into whatever framework you’re using.
- Next we have the registry dump all its conventions into Stringifier. This would normally be done during app start-up/config time.
- Then we explain our conventions to the registry. In this case, I’m using a silly example of grabbing the text of the “Description” attribute hanging off the property. I chose to do it this way to show you your conventions can do more than just grab the value of the property. They can work with the type metadata and not just the value itself. A quick aside: When you here us Fubu guys going on and on about making the most of static typing while we’re using a statically typed language, this is the kind of stuff we’re talking about.
- Second, new up a DisplayConversionRegistry to help you register your conventions with Stringifier (you don’t have to do this, but it makes it easier unless you want to write your own API for doing convention registration).
- Convention Over Configuration (MSDN Magazine article)
- Convention Over Configuration (Hanselminutes Podcast)
- Convention Over Configuration (Video, NDC talk 2009)
- Building a simple FubuMVC Convention (blog post)
- FubuMVC’s Configuration Strategy (blog post)
- FubuMVC – Define your actions your way (blog post)
- Coding with Conventions (blog post about a local NUG talk, with code)
- Model-based Apps and Frameworks (blog post)
- Convention Scanners in StructureMap (blog post)
- Houston Alt.NET ‘09 talk on FubuMVC with Jeremy Miller (video)
Dovetail Hiring again
Dovetail Software is hiring developers to work on our HR Case Management SaaS app. We’re looking for smart people to help us work on some cool stuff on cutting edge technology hosted in AWS. Help us write some code, automate some servers and push updates to happy customers!
While we still have some .NET code, we’re also doing quite a lot of other stuff now. We’ve got a little bit for everyone (from Javascript stuff like node, require, knockout to systems management and automation using AWS, Ruby, Python, Puppet, etc).
We’re currently looking for:
Domains available
In my effort to make myself an ex-GoDaddy customer, I have 3 domains left to transfer or let expire.
Two of them I’m making available to transfer to anyone who wants them (rather than letting them expire so that you would have to pay the recovery fee).
Anyone want these domain names before I let them expire?
whackcoder.net
startingwith.net
Both are currently parked and have no viewership to speak of.
Sweet, sweet vindication
It’s been awhile since I have written an eye-poker post. I’ve been trying be more reserved, professional, and politically correct. But that basically had a cooling effect on my writing. So it’s time we turn up the heat and let the rage flow.
The State of Web Frameworks Sucks
The state of big web frameworks sucks. Not the least sucky among these is Rails. There, I said it. “Bah, he’s just a bitter .NET developer stuck in the stone ages”. I’m tired of getting made fun of and beat up by former PHP scripters telling me how lame and “enterprisey” .NET is and how wonderful and magical Rails is and how it solves every problem. Tell it all to this guy:
ActiveRecord (and Rails) Considered Harmful
Especially with this wonderful quote:
It is practically impossible to teach OO design to students that have had a prior exposure to Rails: as potential programmers they are mentally mutilated beyond hope of regeneration.
My thoughts exactly, on all counts. The whole “Controller” mindset in most MVC frameworks is “pants-on-head retarded”. Worse yet, most frameworks use inheritance. I can’t say this loud enough, so I’m going to BOLDFACE it, ALLCAPS, BLOCKQUOTE it so maybe you’ll see it:
INHERITANCE IS FAIL FOR MOST DESIGNS, BUT NEVER MORE SO THAN IN WEB/MVC FRAMEWORKS!
Rails is one of the biggest violators of this. I don’t care about your stupid dynamic typing and all your excuses about how it “just doesn’t matter” — it matters. The laws of good design don’t just fly out the window when you’re using Ruby or any other language.
More Pants On Head: ActiveRecord
To call ActiveRecord an ORM is to insult the already sullied and notorious name of ORM. I won’t even say that AR is the Linq2SQL of Rails dev because it’s worse than that. AR is the equivalent of dragging and dropping your database to your design surface in Northwind/Designer-driven developing in Visual Studio.
I don’t care what you’re doing with your data store, the model should be the core. This principle is so fundamental that not even silly dynamic typing can overcome it. The model flows out into everything, not your database driving your model. AR represents everything that’s wrong with data-driven development as much as designer-driven EF does in .NET. It’s just wrong, always has been wrong, and always will be wrong. The model is the key, not the persistence mechanisms. AR flagrantly and flamboyantly violates this principle and anyone with a clue who has used AR seriously on any project of length will tell you how it grows into a big mess.
And then you have the whole “Unit test against your database” phenomenon. I’ve had Rails guys chide me for this unmentionable and detestable practice and say that I’m too stuck in my .NET ways, but I’m sorry. You’re an idiot. Unit testing against the database is always, and in every case, wrong. Attempts to explain otherwise sound awfully like arguments I once heard from someone explaining why cannibalism isn’t as bad as people make it out to be. It’s just wrong (unit testing against your database and eating people). Just because you wear thick rimmed glasses and drink lattes with your scarf flipped casually around your neck doesn’t mean you get to throw fundamental principles out of the window. So stop it. Just because it may be quick or easy (which I don’t believe) doesn’t make it right.
Just when I thought I couldn’t say anything worse about AR, I’ve got one more — the coup de grace –it uses inheritance! ARGH! Add “maliciously” to the adverb list (“flagrantly, flamboyantly”).
ActionController – Crack Den of Inheritance
It seems almost every web framework has this wrong: Rails, ASP.NET MVC, Struts, Django, Spring, and MonoRail from my limited research.
Let me put it another way in case I haven’t been clear enough: Inheritance is antithetical to web app design.
One class — that derives from some gawdawful ginormous base class — that has many “action” methods on it is a pile of fail. Why? Because each of those methods has, by definition, a different responsibility and you’re breaking the Single Responsibility Principle. Principles matter! No matter what language (dynamic, static, etc), principles matter! Just because you’re a Rails hipster doesn’t mean you don’t have to obey the laws of physics. With sufficient thrust, pigs can fly for a short while. Likewise, with sufficient ignoring of principles, a rails dev can be successful for awhile but the legacy maintenance cluestick will eventually come crashing down on him/her.
The Perfect Web Framework
Rails is the whipping boy of this post, but most of the other frameworks deserve all the same vitriol because they have all the same fatal flaws (primarily inheritance). So what would the perfect web framework look like? Let me show you:
It should come as no surprise that we, at Dovetail, came to these conclusions (many of them solely by Jeremy Miller) after evaluating all the other major frameworks, suffering much ridicule and derision for noting the inherent and fundamental flaws in them and then building our own that follows all the principles: FubuMVC.
In many ways, FubuMVC is better than Rails and I’ll put my framework up against yours any day of the week. In some ways, it has a long distance to go yet. These are, namely, approach-ability for newbies and community. Currently you have to be disgusted with your current web framework and have tried to replace large portions of it before you can truly appreciate FubuMVC. As far as community, it’s still pretty small at this point, and community contributions are growing, but still not anywhere near Rails level, for sure.
Cool stuff in FubuMVC No. 2: Action Conventions
This is the second post of the FubuMVC series mentioned in the Introduction post.
UPDATE: Josh Arnold (FubuMVC contributor) pointed out an error in a code sample (at the bottom about custom conventions) and that I missed another extension point for defining custom conventions. If you’ve already read this post, you may want to re-read the last section again.
In the previous post, I hopefully sold you on the fact that behaviors combined with conventions are extremely powerful and enable the kinds of things that were originally intended by the Front Controller pattern (Fowler’s PoEAA one, not this one).
In the next few posts, I’m going to detail some of the various types of conventions you can use when configuring your app with FubuMVC. Actually, by the time I’m finished with this FubuMVC series, you’ll see that just about everything you can do with this framework can be conventionally applied exactly how YOU want it applied according to the rules of YOUR app. Have I mentioned before that FubuMVC is very conventional?
In the “Getting Started” guide, near the end, you can see how to get a basic FubuRegistry going. Your FubuRegistry is the class where you tell FubuMVC how you want your app to behave and how things are to be wired up. In this post, I’m going to focus on two parts of the FubuRegistry: Action conventions and Behavior conventions.
Action Conventions
One of the first tasks FubuRegistry has is to figure out what assemblies to scan and which types in those assemblies to scan. By default, it’ll use the “current” assembly (i.e. your web application assembly). You can tweak this if you want, but I digress. The end result of type scanning is that FubuMVC builds up a “type pool” of all the possible types that could contain “action” methods. If you insist on using this language, you could say it tries to locate potential “controllers” and “controller action methods”, but as I mentioned in the previous post, the word “controller” doesn’t really make sense in the FubuMVC world.
As an aside, I’ll be referring to the thing you might normally call “controller” in other MVC frameworks as a “handler.” That is, a type that contains one or more action methods. You might say I’m splitting hairs, but there is an important distinction in the philosophy of FubuMVC and Front Controller MVC architecture in that the “Controller” is the guts of FubuMVC, and not your class. Your class is really a command or action that gets called by the controller. Thus your action methods and the types that contain them should necessarily be small, singularly-focused, and delegate quickly to other classes to perform work. This helps preserve SOLID principles such as the Single Responsibility Principle.
Scanning for Types
As I said above, the first task is to locate which types may be handlers or exclude types that are explicitly not handlers.
A few examples of things you can do with type conventions are:
Consider action methods in all types that end with the word “Controller” (if you insist on using the word “controller” still), or in all types that implement a specific interface (ISomeInterface), or a specific type. Note that these are chainable, so you can define multiple conventions according to the various pieces of your application and how they are architected.
Actions.IncludeClassesSuffixedWithController() .IncludeTypesImplementing<ISomeInterface>() .IncludeType<SomeClassWithActionMethods>();
You can also define one-off, ad-hoc conventions. Though I don’t recommend doing this for large projects, it can be useful for smaller projects. You can even exclude certain types, so you can say “Include all types whose names end in the word ‘Action’, but not ones that end with the letters ‘NotAnAction’”. For example:
Actions /*... other conventions ...*/ .IncludeTypes(t => t.Name.EndsWith("Action")) .ExcludeTypes(t => t.Name.StartsWith("NotAnAction"));
Scanning for Action Methods
Once you’ve defined the conventions by which FubuMVC will locate your candidate handlers, it’s time to tell FubuMVC how to find which methods to consider actions. While it is possible for your handlers to have more methods that are not actions, it is generally ill-advised. Having public methods on handlers that are not action methods could be a smell that your handler is doing too much and is not as focused on its responsibility as it should be. The FubuMVC team also considers it best practice to have one or two methods (one for Get, one for Post) per handler. There are valid cases where more methods are necessary, but they should be the exception.
Consider a few examples of how to identify action methods and filter out methods that may seem like action methods, but you don’t want them to be:
Actions /*... other conventions ...*/ .IncludeMethods(c => c.HasAttribute<IsAnActionAttribute>()) .ExcludeMethods(c => c.Returns<SomeBadType>()) .IgnoreMethodsDeclaredBy<MyUglyBaseClass>() .ForTypesOf<SomeComplexActionType>(p =>
p.IncludeMethods(m => m.Name.StartsWith("Foo")));
Creating custom conventions
As you may have noticed, many of these conventions I’ve demonstrated are one-off conventions that are per-application and not very reusable. As with anything in FubuMVC’s configuration, you can hook into the model underneath the FubuRegistry DSL (domain-specific language) and manipulate it significantly to bend it to your will. You can author these conventions in separate classes which you can then reuse across projects.
As an example of how this process works, there is actually an encapsulated convention built into FubuMVC itself called the “Handler” convention. This convention looks for all types in the namespaces you specify that end in the word “Handler” and that have a method named “Execute” which appears to be an action method (i.e. follows the zero-or-one-model-in and zero-or-one-model-out rule).
To use the out-of-box Handler convention, you can call one of the overloads for ApplyHandlerConvention method, for example (somewhere in your FubuRegistry class):
ApplyHandlerConventions<MyMarkerType>();
In this example, “MyMarkerType” represents a type in the namespace (or parent namespace) of the location where all your handler classes are. Typically you’d have all your handler classes under a single folder, and then in sub-folders by functional area of your app. In that case, you’d have a marker type (just an empty class in C#) which will serve as the indicator to Fubu where to look for your handler classes.
Really Custom Conventions
If that’s still not enough power for you, check out the IActionSource interface which gives you full access to define action conventions your way. Once you’ve created your action source, you can attach it to your FubuRegistry using the FindWidth method hanging off of the “Acitons” DSL in FubuRegistry. For example, _Actions.FindWidth
Summary
In this post, we learned about how FubuMVC is conventional and we started to see what, exactly, that means. We learned about how you can put your “controllers” (handlers) anywhere you want (even in multiple assemblies) and you can “teach” FubuMVC how to find them and discover which methods are meant to be action methods on those handlers. We also learned about how handlers should be small, preferably with one or two public methods — each of which is an action. Finally, we learned that FubuMVC has this “Handler” convention built in so as to make following this best practice easier.
I hope you found this post useful and I hope it gets your noodle cooking about all the ways you can organize and structure your application architecture and how FubuMVC allows you that freedom!
New Blogger: Ryan Rauh
I’m pleased to announce there’s a new blogger on the Los Techies blog roll: Ryan Rauh.
Ryan is a high-energy guy and has his hands in a lot of new tech out there, so expect some exciting blog posts from him.
He’s into JavaScript, FubuMVC, HTML5/CSS3, UI/UX, and general .NET and programming related things. If you went to the last Pablo’s Fiesta, you may have attended his impromptu session on JavaScript functions which received high praise from a number of attendees. Look for cool stuff coming from Ryan soon!
Code Review Quiz
I’ve been following Ayende’s series of reviews on the Microsoft N Layer App Sample V2. His most recent post in the series explored a little bit of the data access layer in the app. Specifically, this interface (which has since been removed):
public interface IMainModuleUnitOfWork : IQueryableUnitOfWork { #region ObjectSet Properties IObjectSet<BankAccount> BankAccounts { get; } IObjectSet<BankTransfer> BankTransfers { get; } IObjectSet<Country> Countries { get; } IObjectSet<Customer> Customers { get; } IObjectSet<Order> Orders { get; } IObjectSet<OrderDetail> OrderDetails { get; } IObjectSet<Product> Products { get; } IObjectSet<CustomerPicture> CustomerPictures { get; } #endregion }
I couldn’t find the source for the IQueryableUnitOfWork base interface, but I assume it exposes a significant amount of methods and properties.
Ayende alluded to the fact that this interface has several significant problems with it, but didn’t go into detail. So I thought that this would be a good opportunity for a quiz. How many wrong things can you spot with this interface?
I counted at least 6 major problems, though I’m sure there are a few others.
Pablo’s Fiesta 2011
In case you haven’t seen John’s posts about Pablo’s Fiesta, I suggest you check them out.
That’s right, Los Techies is having the 2nd annual “Pablo’s Fiesta” open spaces conference in Austin, TX over the weekend September 30, October 1 & 2. Most of the Austin peeps will be there and a host of folks from out of town.
It’s an open spaces conference which means *you* get to choose the topics! There’ll be lots of folks ready to present on topics, plus there will be lots of open discussion topics (for example, John hosted a session on NoSQL so that he could learn and it turned out to be a really great session). Is there something you’ve been wanting to learn about and want to hear the unvarnished truth from folks in the trenches? Propose a session and, most likely, people will show up.
I’m looking to “facilitate” (that is, start a conversation, not necessarily present anything) a session on documentation topics. We’re thinking about changing how we do docs at Dovetail. Dru Sellers brought this up to me and I’ve been eyeing, covetously, the work that the django folks are doing. I like their style and philosophy of documentation. In fact, we’re even considering it for FubuMVC’s docs.
I’d also like to get a bunch of the FubuMVC contributors and various other interested folks to talk about the future of FubuMVC and try to ramp up development, documentation, guides, etc. FubuMVC seems to be reaching a critical mass and I want the community to be well prepared for a boom so that it will be successful.
But that’s just what I want. The real question is, what do YOU want?
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:
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.
Cool stuff in FubuCore No. 9: Stringification
This is the ninth post of the FubuCore series mentioned in the Introduction post.
It’s a funny title, but it captures the point perfectly. What do you do when you have something (a domain entity or model object of some kind, or maybe a value type, etc) that you need to convert to a string? “Duh, ToString()!” you might say, and that’s how we started. But in our app we quickly ran into situations where one “ToString()” method wasn’t enough. We needed context. In this context, it should look like this and in that context, it should look like that. So then we had ToString() methods that took arguments. Soon we needed to have services that could do things like figure out the correct time zone for the current user when display date/time values. It got out of hand. We needed to be able to string-ify anything in any way we needed to in the current context, possibly using services from the container. Stringifier and IDisplayFormatter were born.
Why?
I started writing a whole mini-post on the circuitous route we took to finally arrive at centralizing and conventionalizing our display formatting, but it got too long. So I moved it to it’s own post: Convention over lots of code. You might want to read that before continuing, but if you already understand the “Why”, please proceed.
How
Stringifier does all the real work, IDisplayFormatter is a nice veneer around Stringifier to make it easier. We’ve baked IDisplayFormatter deep into FubuMVC and HtmlTags so that, generally, your code won’t have to mess with it too much. That’s been beautiful for us. We have a few places where we need to use IDisplayFormatter such as formatting grid columns with our AJAX-y jqGrid supporting code. FubuMVC’s FubuRegistry has the stringification convention registration built-in. Once you set it up there, you generally don’t have to worry about it. It just works.
But this post is about FubuCore. So let’s assume you’re not using FubuMVC but you still want to use Stringification in your app (say, an ASP.NET MVC app in which you’re already using the HtmlTag library). Fine, here’s how you go about it. I’m going to post a big chunk of code and then break it down:
public class StringifierExample { [Description("This is an example date time value")] public DateTime? ExampleDateTime { get; set; } public void FullExample() { ExampleDateTime = DateTime.Now; // [1, 2] Setup stringifier and DisplayConversionRegistry var stringifier = new Stringifier(); var registry = new DisplayConversionRegistry(); // [3] Setup convention to grab description from property registry.IfPropertyMatches(p => p.PropertyType.IsTypeOrNullableOf<DateTime>() && p.HasAttribute<DescriptionAttribute>() ).ConvertBy(r => r.Property .GetAttribute<DescriptionAttribute>() .Description);
// [4] Dump the conventions to Stringifier registry.Configure(stringifier); // [5] Setup display formatter var locator = new StructureMapServiceLocator(ObjectFactory.Container); var formatter = new DisplayFormatter(locator, stringifier); var accessor = ReflectionHelper.GetAccessor<StringifierExample>( s => s.ExampleDateTime); // [6] Perform the conversion Console.WriteLine("Unconverted: {0}", ExampleDateTime); Console.WriteLine("Converted: {0}", formatter.GetDisplay(accessor, ExampleDateTime)); } }
Now, normally you wouldn’t be doing this all in one class. Parts of it would be scattered in your app (mostly in your StructureMap config/bootstrapping). It’s only the last part about the DisplayFormatter would you really be touching once everything is wired up.
Let’s break that code sample down:
</pre>
(IDateTimeFormatter is a class we have that encapsulates all the DateTime / TimeZone handling logic)
This gave us tons of flexibility to keep our views and controllers nice and trim and not having to call a bunch of crazy extension methods to do one-off formatting all the time. All our conventions (even one-offs) are in ONE PLACE – easy to look at and, more importantly, easy to test!
Convention over lots of code
I’m in the middle of writing my last FubuCore series post before I proceed to the FubuMVC series of posts. The post is called “Stringification” (String-eh-feh-k-shun) and it’s about using conventions to remove a lot of code that deals with properly displaying values/models/entities in different contexts. We have a localized, multi-time zone application and displaying data gets tricky when you realize it has to be localized and all dates and times must be in the correct time zone and local format. There’s a lot of stuff built into .NET to do this, of course, and it’s great, but you still have a lot of code to write to call it and wire it up and yadda yadda.
Anyhow, as I was writing that “Stringification” post, I started by writing the “Why” part (i.e. how we came to the conclusion that we needed conventional-based “ToString”-like support throughout our app). As I was writing it, it became a blog post all by itself. So I’m breaking it out here and making this post about why conventions are important and how they can save you tons of time and effort and speed up your development.
Lots of people throw around the words “convention over configuration” and it’s important. But a lot of people who aren’t “thinking conventionally” don’t really get the power or value of it. What I’m about to share was part of my “ah-hah!” moment of appreciation.
The Date/Time/TimeZone Problem
Let me start by explaining a specific problem we had, how we solved it originally, the problems we ran into, and how IDisplayFormatter/Stringifier made things much easier and better. Our app, like most, tracks a lot of dates and times with our entities. We display these dates, times, and date/times often in our app. The trick is that we could have users in different time zones using the system. We need to display the dates and times in the user’s current time-zone.
Both Josh and I have written about this particular problem before: Josh wrote “Helpful DateTime extension methods for dealing with Time Zones” and I wrote “How we do Internationalization” (scroll down to the Date/Time part).
When we started, we had created a bunch of extension methods for dealing with the problem. Most of the time, we were displaying date/times in our views, so this worked somewhat well. Eventually we started needing to display them in non-view code (for example, when we were setting DateTime values on a JSON response to an AJAX call). Then the extension methods got a little more complicated. Eventually the time zone problem became so complicated, we needed some services to be pulled out of StructureMap and the extension method thing kinda fell flat on its face.
And remember, these are *just* the DateTime properties. We had a host of other issues such as our localized list values (where the value of a drop-down list is not displayable or localized, and we need to display a different, localized value to the user), currency and other floating point numbers, the link text when linking to an entity, etc. We soon had a bunch of extension methods and one-off solutions for each type of problem we faced. Ultimately, though, all the problems were around taking a value/model/entity of some type and displaying it properly to the user (where “properly” is whatever is appropriate for that type of data and context).
This became a maintenance nightmare replete with duplication/DRY-violations, one-off static location from the container, and all sorts of other general nastiness. We needed a single solution through which to pump all our data-that-needs-to-be-displayed and have it rendered to the client in a consistent, easy to maintain way. Naturally, the first thing that came to our mind was: “Conventions!”
We ended up building Stringifier and IDisplayFormatter which allows us to have a central, conventional way of consistently displaying things. It’s pluggable and allows us to customize it. You can read about Stringifier/DisplayFormatter in my other post.
What conventions mean to us…
Early on in our development cycle (that would be in June of 2008), we kept hitting problems where we would find ourselves saying, out loud in meetings/stand-ups, etc, “That stupid [X] bug bit me again. Be advised, team, that any time you need to do [X], it should be done this way [Y].” And we trained ourselves to recognize that phrase formula and immediately knee-jerk by adding something conventional into our architecture to lock it down. We found that these efforts always resulted in a huge boost in productivity so much so that I can’t imagine how we would’ve been able to do half of what we’ve accomplished the past 3 years at Dovetail without all our conventional stuff.
Naturally, you can imagine why I now think that building conventions into your infrastructure is critical to maintaining velocity over a long period of time and why I consider this mindset a critical factor in the success we’ve had over these past 3 years without a single re-write and not a ton of legacy code baggage.
We’ve all written a lot of conventional programming, convention over configuration, and the like. You should check out some of these posts, videos, and podcasts:
Jeremy Miller
Joshua Flanagan
Chad Myers
subscribe via RSS