For the past few months, I've gotten the privilege to develop a good sized, production Ruby on Rails application. I say privilege because it has shed light on many lessons for the way we develop in the Microsoft community. The beauty of RoR is that you don't have to spend months or years reading books and blogs on how to put together a properly architected application. This doesn't mean you're not going to shoot yourself in the foot, but it certainly reduced the risk! Additionally, if you get a new job at a different Rails shop, you typically don't have to spend a couple months trying to figure out somebody else's homegrown architecture (if you're lucky enough to find any structure at all). RoR is like a design pattern at the macro-level...pulling together the (albeit opinionated) best practices of data access, layering, and unit testing into a consolidated package. Obviously, there is never a one size fits all - there are simply too many varying needs to have a single application design fit every scenario. But it certainly fulfills the 80/20 rule...what RoR has proven is that it's highly effective, on many levels, to have a "preferred path" and common platform for the 80% of web-based application scenarios which it covers nicely. The overwhelming benefit of having this common platform - with many technical decisions made for you, such as how to validate forms and models, how to setup CRUD communications, how to communicate with the DB, and how to organize applications - is that the community is able to converge on a consolidated preferred practice.
When the GoF wrote Design Patterns, it gave the development community a formalized language to discuss common coding scenarios and recommended practices for addressing those situations. Martin Fowler did the same by formalizing "smells" and refactorings in Refactoring. This formalization and common language has made it easier for developers to discuss solutions to a problem and to get new developers ramped up to a framework which leverages some of these formalized ideas...assuming they're used appropriately. Likewise, Rails provides a formalized track for Ruby developers to develop data backed, web-based applications. This has paid dividends in the availability of guidance, the facilitation of plugins/extension, the enabling of widely used scaffolding generators, and the removal of hours/days/weeks of research and trial & error to find out how the heck do we competently write a dynamic web application with Ruby.
ASP.NET MVC is shaping up to be a spectacular framework. Frankly, it is far more than a magnitude improvement over traditional ASP.NET. But the remaining opportunity, if you will, is that it is too specific in nature to provide an end-all "preferred" path for .NET web application development. What should we unit test with? How should we talk to the DB? Who should handle dependency injection? Should the model really be in the same assembly as the web project? ASP.NET MVC is similar to NHibernate wherein it's absolutely spectacular in providing a solution for accomplishing a specific task - NHibernate for providing DB communications in a domain driven design and ASP.NET MVC for bringing the MVC pattern to .NET web development. That doesn't lessen its benefit; it simply doesn't do much to keep a developer from leveraging it inappropriately, knowing which tools should be used with it , and how to properly write a real world application.
One of the primary challenges is that there are simply soooo many options to choose from beyond just deciding to go with ASP.NET MVC. It's absolutely bewildering at times to know which assortment of tools and techniques are the best to select. (Try to recall when you first started writing .NET apps!) To further frustrate the problem, there is no "best" combination of tools and practices. But just as RoR doesn't necessarily represent the quantifiably best practices/tools for developing web-based Ruby applications, it has given enormous benefit to the Ruby community by providing a formalized, preferred approach. What's needed then, IMO, for Microsoft web development is an equivalent foundation which leverages ASP.NET MVC with a number of carefully selected tools to provide a best practice preferred path which will cover most web application scenarios. To begin the plug, that's what I hope S#arp Architecture to be. I don't intend for it to be merely an example of using ASP.NET MVC...I intend for it to be the Ruby on Rails for ASP.NET MVC which can enjoy benefit from scaffolding generators, standard practices, standard means for creating and sharing plug-ins, a common ground for sharing agreed upon best practices, etc. Although it won't be applicable in all cases, I feel it's on its way to comfortably covering the 80% of domain driven, web-based applications.
The challenges to aspiring to such a goal for #Arch, and any foundational architecture for that matter, include:
Keeping the solution simple enough to be easily learned and to develop with,
- Keeping it flexible enough to use a variety of options for the presentation layer and other facets, such as the mechanism of dependency injection if desired,
Providing tools, such as scaffolding generators and project templates to realize one of the major benefits that such a consolidated framework can provide,
Making it dead simple for developers of all skill levels to get an application up and running quickly without being overly constrained by design and without leading to maintenance nightmares down the road, and
Keeping it lean enough to avoid the choice-overload that framework bloat often leads to.
I suppose you could say that the above is my commitment to the users of the architecture. In short, I'm attempting to provide just enough judicious planning for solving common problems without compromising flexibility. To help you decide if S#arp Architecture is appropriate for your project, you'll want to consider the following assumptions, which aren't necessarily objective best practices, but which S#arp Architecture has built in:
Domain driven design is the preferred way to encapsulate your model and business logic (e.g., this is great for those of you who get the willies after looking at ADO.NET Entity Framework);
- Tiers should be loosely coupled and employ separated interface (aka, dependency inversion) to separate service dependencies from domain logic;
The ability to unit test all code, from the controller action down to the lowly DB filtering, should be available while supporting a domain driven design (i.e., you shouldn't need to create your database to test all of your business logic);
Database access and communications should require little attention and should be minimally intrusive, but without limiting those capabilities; and
Preferred practices for a few key areas should be suggested, such as model validation, CRUD mechanics, and application layering.
But even if you agree with these points, this doesn't mean that it'll be appropriate in every situation or that it won't be "too much" in very simple scenarios. Indeed, the decision of using any base architecture is akin to employing a design pattern (but bigger)...it should only be leveraged when appropriate and only when it carries its weight. At the beginning of any project, a number of architectural approach should be compared side-by-side to assist in picking the right tool for the job; a few options to consider besides S#arp Architecture include a homegrown solution, ADO.NET Entity Framework, Castle MonoRail, CSLA, or the full suite of Spring.NET tools.
A commenter on http://codebetter.com/blogs/kyle.baley/archive/2008/11/11/overview-and-review-of-s-arp-architecture.aspx also brought up great points with respect to concerns of future bloat and unnecessary complexity as frameworks evolve and grow, as the life cycle of some architectures have fallen victim to. These are enormous risks for any framework that attempts to cover the development needs of 80% of web-based applications; there are a few more tasks which need to be done to bring #Arch to version 1.0 and almost all of them are focused on further reducing complexity without limiting flexibility. Certainly one of the success factors of Ruby on Rails is that it hasn't tried to continue to add tons of new functionality with each new release; it has simply attempted to solve one area - model driven web development with Ruby - in a very clean and competent manner...and then left its approach alone. I hope S#arp Architecture emulates some of these lessons learned by providing a simple to use platform for developing domain driven, web applications with ASP.NET MVC. And once it gets to that point with 1.0, I promise we'll leave it alone. ;)
11-11-2008 4:02 PM