I’ve been looking into rails recently, partly to learn rails itself, partly to try and gain inspiration for the direction to take both the framework we use at work and Jamaica. It’s triggered me to question a lot of things that I’m doing in .NET so I’m going to attempt to record my thoughts.
Having testing and persistence baked in
One thing that has struck me is that I’m watching railscasts from years ago and they are demonstrating solutions to problems ASP.NET MVC is struggling with now. It really does have testing baked in but often not through the use of abstractions, instead they have made integration tests easy to write. It appears the entire request can be processed in memory without having to fire up a server all the way through to rendering the view. This is something OpenRasta is capable of and one of the reasons I get so excited about it.
Another benefit rails has is that it comes with a “model” baked in. This is something that is sorely lacking from ASP.NET MVC. Whereas the .NET world (particularly the ALT.NET sphere) favours NHibernate for persistence, they instead use a simple but well implemented active record implementation. Why have they chosen this? Partially because it works so well with a dynamic language, everything is DRY as code can be generated from the database at runtime. It’s also damn quick, something that has always bugged me about NHibernate is the 10-20 seconds it takes to create the session factory before you can get started.
Because NHibernate is so powerful and configurable it can quite frankly be bloody confusing for most developers, I get asked to help with problems almost daily. With active record everything is kept simple, this object is a row in that table. There aren’t often complex mapping files, it just works. Rails’ active record implementation has a layer of syntactic sugar based around pattern matching on missing methods which looks nice and works well. However, in .NET we have LINQ which is statically typed, very powerful and can serve the same purpose.
Why do we chose NHibernate?
The reasons given for choosing NHibernate are persistence ignorance, reducing the impedance mismatch, amongst others. Why do we insist on ignoring the fact that our applications are running on top of a relational database? What ever happened to embracing the technologies we are using to get the best out of them?
NHibernate lets you persist your domain models directly. So what? Who’s domain models are that much beyond dumb data stores in reality? I’d bargain it’s a hell of a lot less than those that claim to be doing domain driven design. Also, why does your domain have to be persisted directly? Why couldn’t you provide an empty domain object with a few active record objects and have it process them and spit other active record objects out the other side? Something CQRS-ish. Then your domain would contain nothing but business logic.
What does this mean?
I’m looking away from NHibernate, no tool should be chosen without question, even the great NHibernate. I just don’t think it is serving my needs as well as it could so I’m going to look for alternatives. Subsonic is top of my list, followed by revisiting LINQ to SQL, hell I might even take a look at the Entity Framework.
While we’re at it, why do we chose relational databases without question? I’ve been working with Lucene.NET a lot recently, it’s really easy to use and you get full-text indexing for free if you were to use it as a data store. Only want to deal with aggregate roots? Store all the data of that aggregate root in a single document, it can easily emulate nested structures.
Random deviation onto REST
I’m also being influenced by how REST appeals to me. It seems like a simple yet powerful way of dealing with the web. If we consider everything we work with as a resource, a representation of an idea, why can’t that representation be stored as an active record? The transition of an idea between resources could actually be a record transferring between tables. The old representation could even hold a reference to what the idea became, allowing you to redirect to the current representation. Hell, wasn’t the web made for storing and linking documents before it got bastardised into the beautiful beast we have today? Perhaps a document database would be ideally suited!
Pain points of ASP.NET MVC
Talking of REST brings me back to another problem I have with ASP.NET MVC. The routing revolves around controllers and actions rather than the resources and HTTP methods. In order to generate URIs, you will at some point end up having to manipulate strings or create anonymous objects. How do rails and OpenRasta deal with this? By using resources and their types to determine the URIs. This is so much more powerful and dare I say easier to use and understand. I can see it empowering the use of generics within .NET and it cuts out a hell of a lot of crap around URI generation.
Ah, cutting out the crap. ASP.NET MVC is testable, until you want to test something that isn’t a just a controller action. Like a HTML helper, URI generation or store the IP address of the request. Most of these things are kind of testable, but you have to mock out a complex object graph like HttpContextBase or ControllerContext. “We got rid of HttpContext.Current and replaced it with something slightly less monolithic and slight less sealed, go us!”. Know how OpenRasta deals with this? It has dependency injection at it’s core and there’s an interface that lets you retrieve everything you need, either separately or together. There’s everything from IRequest to ICommunicationContext (the equivalent of ControllerContext) and everything in between. You need it, you can retrieve it and it’s bloody easy to test.
There’s a lot of random ideas here, I can’t say which I’ll end up using. Perhaps none of them, perhaps an unforeseen combination. If nothing else writing this down has helped me distil a few of them into clearer thoughts.
Here’s to questioning everything you believe to be true.
This entry was posted on at Thursday, February 04, 2010 and is filed under Architecture, ASP.NET MVC, Open Rasta, Rails, REST, Unit testing. You can follow any responses to this entry through the RSS 2.0. You can