UPDATEThis post is now obsolete. Single project areas are a core part of ASP.NET MVC 2.
Preview 1 of ASP.NET MVC 2 introduces the concept of Areas. Areas provide a means of dividing a large web application into multiple projects, each of which can be developed in relative isolation. The goal of this feature is to help manage complexity when developing a large site by factoring the site into multiple projects, which get combined back into the main site before deployment. Despite the multiple projects, it’s all logically one web application.
One piece of feedback I’ve already heard from several people is that they don’t want to manage multiple projects and simply want areas within single project as a means of organizing controllers and views much like I had it in my prototype for ASP.NET MVC 1.0.
Well the bad news is that the areas layout I had in that prototype doesn’t work right out of the box. The good news is that it is very easy to enable that scenario. All of the components necessary are in the box, we just need to tweak the installation slightly.
We’ve added a few area specific properties to VirtualPathProviderViewEngine, the base class for our WebFormViewEngine and others. Properties such as AreaViewLocationFormats allow specifying an array of format strings used by the view engines to locate a view. The default format strings for areas doesn’t match the structure that I used before, but it’s not hard for us to tweak things a bit so it does.
The approach I took was to simply create a new view engine that had the area view location formats that I cared about and inserted it first into the view engines collection.
public class SingleProjectAreasViewEngine : WebFormViewEngine {
public SingleProjectAreasViewEngine() : this(
new[] {
"~/Areas/{2}/Views/{1}/{0}.aspx",
"~/Areas/{2}/Views/{1}/{0}.ascx",
"~/Areas/{2}/Shared/{0}.aspx",
"~/Areas/{2}/Shared/{0}.ascx"
},
null,
new[] {
"~/Areas/{2}/Views/{1}/{0}.master",
"~/Areas/{2}/Views/Shared/{0}.master",
}
) {
}
public SingleProjectAreasViewEngine(
IEnumerable<string> areaViewLocationFormats,
IEnumerable<string> areaPartialViewLocationFormats,
IEnumerable<string> areaMasterLocationFormats) : base() {
this.AreaViewLocationFormats = areaViewLocationFormats.ToArray();
this.AreaPartialViewLocationFormats = (areaPartialViewLocationFormats ??
areaViewLocationFormats).ToArray();
this.AreaMasterLocationFormats = areaMasterLocationFormats.ToArray();
}
}
The constructor of this view engine simply specifies different format strings. Here’s a case where I wish the Framework had a String.Format method that efficiently worked with named formats.
This sample is made slightly more complicated by the fact that I have another constructor that accepts all these formats. That makes it possible to change the formats when registering the view engine if you so choose.
In my web.config file, I then registered this view engine like so:
protected void Application_Start() {
RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Insert(0, new SingleProjectAreasViewEngine());
}
Note that I’m inserting it first so it takes precedence. I could have cleared the collection and added this as the only one, but I wanted the existing areas format for multi-project solutions to continue to work just in case. It’s really your call.
Now I can register my area routes using a new MapAreaRoute extension method.
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapAreaRoute("Blogs", "blogs_area",
"blog/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" },
new string[] { "SingleProjectAreas.Areas.Blogs.Controllers" });
routes.MapAreaRoute("Forums",
"forums_area",
"forum/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" },
new string[] { "SingleProjectAreas.Areas.Forums.Controllers" });
routes.MapAreaRoute("Main", "default_route",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" },
new string[] { "SingleProjectAreas.Controllers" });
}
And I’m good to go. Notice that I no longer have a default route. Instead, I mapped an area named “Main” to serve as the “main” project. The Route URL pattern there is what you’d typically see in the default template.
If you prefer this approach or would like to see both approaches supported, let me know. We are looking at having the single project approach supported out of the box as a possibility for Preview 2.
If you want to see this in action, download the following sample.
UPDATE: This post is outdated. ASP.NET MVC 2 RTM was released in March.
Four and a half months after my team released ASP.NET MVC 1.0, I am very happy to announce that the release of our first Preview of version 2 of ASP.NET MVC is now available for download. Go download it immediately and enjoy its coolness. :) Don’t be afraid to install it as it will sit nicely side-by-side with ASP.NET 1.0.
The release notes provide more details on what’s in this release and I’ve also updated the Roadmap on CodePlex, which describes the work we want to do in Preview 2 and beyond.
After shipping ASP.NET MVC 1.0, the team and I spent time pitching in on ASP.NET 4 which was a nice diversion for me personally as I got a chance to work on something different for a while and it let ideas for ASP.NET MVC 2 percolate.
But now I’m very happy to be back in the saddle going full bore working on ASP.NET MVC again. As mentioned in the roadmap and elsewhere, ASP.NET MVC 2 will run on both ASP.NET 3.5 SP1 and ASP.NET 4. We will be shipping ASP.NET MVC 2 in the box with Visual Studio 2010 and be making a separate installer for Visual Studio 2008 SP 1 available via download.
Templated Helpers
One of my favorite new additions in Preview 1 is what we call the Templated Helpers. You can watch a short Channel 9 Video that Scott Hanselman filmed of me giving a last minute impromptu demo of Templated Helpers.
Templated Helpers allow you to automatically associate templates for editing and displaying values base on the data type. For example, a date picker UI element can be automatically rendered every time data of type System.DateTime is used.
If you’re familiar with Field Templates in ASP.NET Dynamic Data, then this is very similar to that, but specific to ASP.NET MVC.
To find out more about the helpers, check out the pre-release documentation for a walkthrough of using Templated Helpers.
We also include support for Areas and Data Annotations, along with various bug fixes and minor API improvements. Everything is detailed in the Release Notes.
The Team
I have to say, I really like being a part of a team that I feel is working very well together and am proud of the work they’ve done. Some of them already have blogs such as Eilon (rarely updated) and Brad Wilson. The QA guys recently started a podcast. But others (Levi, looking at you) really need to start a blog. ;) Great work fellas!
Be sure to let us know what you think and provide feedback in our forums!
Related Links
Note: the official name of this version of the product is ASP.NET MVC 2 and not ASP.NET MVC 2.0 as some might expect. Maybe it’s part of a new marketing initiative to get rid of dots in product names. I guess they didn’t read my Law of Demeter post to understand it’s not about reducing dots ;).
A member of the Subtext team discovered a security vulnerability due to our integration with the FCKEditor control as well as the FreeTextBox control. This vulnerability would potentially allow unauthenticated users to upload files using the file upload tools included with these editors.
The Fix
If you’re running the latest version of Subtext (Subtext 2.1.1), the quickest way to patch your installation is to copy the following web.config file…
<configuration>
<system.web>
<authorization>
<allow roles="Admins" />
<deny roles="HostAdmins"/>
<deny users="*" />
</authorization>
</system.web>
</configuration>
…to the following directories within the Providers\BlogEntryEditor\ directory.
- FCKeditor\editor\filemanager\browser\default\connectors\aspx\
- FCKeditor\editor\filemanager\upload\aspx\
- FTB\
If you’re running an older version or would rather not have to hunt through your installation, upgrade to Subtext 2.1.2. The only difference between this version and 2.1.1 is the change mentioned above.
Notes
This is the second time we’ve been bitten by integration issues with these rich text editors. The Subtext team takes security very seriously and regret that this vulnerability was released. We’ll take a hard look at these integration points and may consider turning them off by default or some other mitigations. I have a feeling that most of our users use Windows Live Writer or some other such application to post to their blog anyways.
You might wonder why we don’t simply include that web.config file within the Providers directory. I tested that out and unfortunately it breaks FCKEditor for no good reason that I could deduce.
Again, I feel terrible that this happened and we’ll work hard to ensure it doesn’t again. My thanks goes to Si Philp who found the issue and discreetly reported it.
Download
The URL to the new version of Subtext is here.
Recently I read a discussion on an internal mailing list on whether or not it would be worthwhile to add a null dereferencing operator to C#.
For example, one proposed idea would allow the following expression.
object a = foo.?bar.?baz.?qux;
This would assign the variable a the value null if any one of foo, bar, or baz is null instead of throwing a NullReferenceException. It’s a small, but potentially helpful, mitigation for the billion dollar mistake.
Sure enough, it did not take long for someone to claim that this syntax would be unnecessary if the code here was not violating the sacred Law of Demeter (or LoD for short). I think this phenomena is an analog to Godwin’s Law and deserves its own name. Let’s call it the “LoD Dot Counting Law”:
As a discussion of a code expression with more than one dot grows longer, the probability that someone claims a Law of Demeter violation approaches 1.
Count the dots and win a prize!
What is wrong with the claim that the above expression violates LoD? To answer that let’s briefly cover the Law of Demeter. I’m not going to cover it in detail but rather point to posts that describe it in much better detail than I would.
The Many Forms of Demeter
The formal object form of the law can be summarized as:
A method of an object may only call methods of:
- The object itself.
- An argument of the method.
- Any object created within the method.
- Any direct properties/fields of the object.
A general formulation of the law is:
Each unit should have only limited knowledge about other units: only units "closely" related to the current unit. Or: Each unit should only talk to its friends; Don’t talk to strangers.
This of course leads to the succinct form of the law:
Don’t talk to strangers
In other words, try to avoid calling methods of an object that was returned by calling another method. Often, people shorten the law to simply state “use only one dot”.
One of the key benefits of applying LoD is low coupling via encapsulation. In his paper, The Paperboy, The Wallet, and The Law of Demeter (PDF) (it’s a relatively quick read so go ahead, I’ll be here), David Bock provides a great illustration of this law with an analogy of a paperboy and a customer. Rather than having a customer hand over his wallet to pay the paperboy, he instead has the paperboy request payment from the customer.
In answer to “Why is this better?” David Bock gives these three reasons.
The first reason that this is better is because it better models the real world scenario... The Paperboy code is now 'asking' the customer for a payment. The paperboy does not have direct access to the wallet.
The second reason that this is better is because the Wallet class can now change, and the paperboy is completely isolated from that change…
The third, and probably most 'object-oriented' answer is that we are now free to change the implementation of 'getPayment()'.
Note that the first benefit is an improvement not only in encapsulation but the abstraction is also improved.
Dot Counting Is Not The Point
You’ll note that David doesn’t list “50% less dots in your code!” as a benefit of applying LoD. The focus is on reduced coupling and improved encapsulation.
So going back to the initial expression, does foo.bar.baz.qux violate LoD? Like most things, it depends.
For example, suppose that foo is of type Something and it contains properties named Bar, Baz, and Qux which each simply return this.
In this semi-contrived example, the expression is not an LoD violation because each property returns the object itself and according to the first rule of LoD, “you do not talk about LoD” … wait … sorry… “a method is free to call any properties of the object itself” (in a future post, I will cover the class form of LoD which seems to indicate that if Bar, Baz, and Qux return the same type, whether it’s the same object or not, LoD is preserved).
This pattern is actually quite common with fluent interfaces where each method in a calling chain might return the object itself, but transformed in some way.
So we see that counting dots is not enough to indicate an LoD violation. But lets dig deeper. Are there other cases where counting dots leads do not indicate an LoD violation? More importantly, is it always a bad thing to violate LoD? Are there cases where an LoD violation might even be the right thing to do?
Go Directly to Jail, Do Not Pass Go
Despite its name, violating the Law of Demeter will not get you on an episode of Cops nor is it some inviolable law of nature.
As the original paper points out, it was developed during design and implementation of the Demeter system (hence the name) and was held to be a law for the developers of that system.
The designers of the system felt that this practice ensured good Object-Oriented design:
The motivation behind the Law of Demeter is to ensure that the software is as modular as possible. The law effectively reduces the occurrences of nested message sendings (function calls) and simplifies the methods.
However, while it was a law in the context of the Demeter system, whether it should hold the weight that calling it a Law implies is open to debate.
David Bock refers to it as an idiom:
This paper is going to talk about a particluar (sic) 'trick' I like, one that is probably better classified as an 'idiom' than a design pattern (although it is a component in many different design patterns).
Martin Fowler suggests (emphasis mine)
I'd prefer it to be called the Occasionally Useful Suggestion of Demeter.
Personally, I think most developers are guilty of bad encapsulation and tight coupling. I’m a bit more worried about that than applying this law inappropriately (though I worry about that too). Those who have deep understanding of this guideline are the ones who are likely to know when it shouldn’t be applied.
For the rest of us mere mortals, I think it’s important to at least think about this guideline and be intentional about applying or not applying it.
I Fought The Law and The Law Won
So what are the occasions when the Law of Demeter doesn’t necessarily apply? There’s some debate out there on the issue.
In his post, Misunderstanding the Law of Demeter, Daniel Manges argues that web page views aren’t domain objects and thus shouldn’t be subject to the Law of Demeter. His argument hinges on a Rails example where you send an Order object to the view, but the view needs to display the customer’s name.
<%= @order.customer.name %>
Counting two dots, he considers the change that would make it fit LoD:
<%= @order.customer_name %>
He then asks:
Why should an order have a customer_name? We're working with objects, an order should have a customer who has a name.
…when rendering a view, it's natural and expected that the view needs to branch out into the domain model.
Alex Blabs of Pivotal Labs takes issue with Daniel’s post and argues that views are domain objects and an order ought to have a customer_name property.
It’s an interesting argument, but the following snippet of a comment by Zak Tamsen summarizes where I currently am on this subject (though my mind is open).
because they don't. the primary job of the views (under discussion) is to expose the internal state of objects for display purposes. that is, they are expressly for data showing, not data hiding. and there's the rub: these kind of views flagrantly violate encapsulation, LoD is all about encapsulation, and no amount of attribute delegation can reconcile this.
The problem as I see it with Alex’s approach is where do you stop? Does the Order object encapsulate every property of Customer? What about sub-properties of the Customer’s properties? It seems the decision to encapsulate the Customer’s name is driven by the view’s need to display it. I wouldn’t want my domain object’s interface to be driven by the needs of the view as that would violate separation of concerns.
There’s another option which might be more common in the ASP.NET MVC world than in the Rails world, I’m not sure. Why not have a view specific model object. This would effectively be the bridge between the domain objects and the view and could encapsulate many of the these properties that the view needs to display.
Another case where an LoD violation might not be such a bad idea is in cases where the object structure is public and unlikely to change. While in Norway, I had the opportunity to briefly chat with Michael Feathers about LoD and he pointed out the example of Excel’s object model for tables and cells. If LoD is about encapsulation (aka information hiding) then why would you hide the structure of an object where the structure is exactly what people are interested in and unlikely to change?
Use It or Lose It
When I learn a new guideline or principle, I really like to dig into where the guideline breaks down. Knowing where a guideline works, and what its advantages are is only half the story in really understanding it. When I can explain where it doesn’t work and what its disadvantages are, only then do I feel I’m starting to gain understanding.
However, in writing about my attempts at understanding, it may come across that I’m being critical of the guideline. I want to be clear that I think the Law of Demeter is a very useful guideline and it applies in more cases than not. It’s one of the few principles that can point to an empirical study that may point to its efficacy.
In a Validation of Object-Oriented Design Metrics as Quality Indicators, the authors of the study provide evidence that suggests The Law of Demeter reduces the probability of software faults.
Still, I would hope that those who apply it don’t do it blindly by counting dots. Dot counting can help you find where to look for violations, but always keep in mind that the end goal is reducing coupling, not dots.