Wednesday, January 03, 2007

Rails: Enterprise Ready

"Is Rails Enterprise Ready?"

I've avoided the question since I started working with Rails. In fact, if pressed, I previously would have stated that Rails wasn't enterprise ready. Claiming that it isn't ready is much easier than proving that it is.

But, now things are different. I'm working on a development team with 14 coders. Our application has it's own database and also integrates with 2 other legacy databases. Our application also integrates with external services via SOAP and RESTful web services. The application currently has a unit test suite that consistently runs in less than 1 second. It also has a domain model that is separated from the UI by inserting a Presenter layer.

Did Rails handle this type of environment out of the box? No. However, Ruby + Rails made it easy to extend Rails where it was necessary. Since I was able to easily extend the framework to my needs, I'm now completely comfortable stating that Rails is "Enterprise Ready". In fact, out of the box Rails solves about 80% of the problems I have, which is better than most "Enterprise" software I'm usually working with.

Out of the box, Rails expects you to be working with one database that you have full control over. Sometimes, life isn't that easy. Luckily, back in January of 2006 Dave Thomas wrote a blog entry on how to create and share database connections to additional databases. Using this article as a reference, we were able to fairly easily integrate our application with our database and the 2 legacy databases we needed to both read and write to.

Connecting to external services was also an easy task. We wrote a few Gateways that took advantage of Net::Http. These Gateway classes took our domain objects, mapped them to valid request objects for the external services, and formatted the result to our needs.

We've spent a lot of time ensuring that our test suite is quite solid, yet ran as fast as possible. The first step was removing access to the database from the unit tests. After that, we also looked at allowing ActiveRecord::Base subclasses to be tested without needing access to the database. The result is a sub 1-second unit test run that provides greater than 80% code coverage.

We also spent a fair amount of time on creating Presenter classes that sit between the UI and the Models. In our application several of the pages contain more than one domain model. For example, a page may collect a billing address and credit card information. Instead of creating several models in the controller we create one presenter instance that collects and validates input. The presenter instances also contain methods that can create model objects from the validated user input. The result is a clean domain model and an easily unit testable presentation layer.

Above are, in my opinion, the significant changes we made to mold Rails to our needs on this project. There were a few other changes we made that were not as major but also contributed to the success we've had so far. For example, we stopped using migrations because of some pain we were feeling due to our team size. Instead, we drop and recreate our database with every build using ActiveRecord::Schema.define, a tip we picked up from Dave Thomas. We also automated our check in process to ensure everyone follows the same steps before checking in. This has lead us to very few broken builds.

Rails is great for building web applications. For building enterprise web applications, Rails is often good enough. And, for building complicated enterprise web applications, Rails is easily extendable. Because of this, Rails is Enterprise Ready.

11 comments:

  1. You say you need to read and write to legacy databases – how do you get round the lack of two-phase commit, or is it not an issue for you?

    ReplyDelete
  2. Kerry,
    Luckily, it has not been an issue for us yet.

    ReplyDelete
  3. Jay,
    Thanks for this fantastic writeup. Somehow I've missed your blog in the past but you're at the top of my rss feed reader now. These testing links and information were just what I needed.

    ReplyDelete
  4. Anonymous10:18 AM

    I've really enjoyed your unit testing post. Will you do a post about using Presenters?

    Keep up the great work!

    ReplyDelete
  5. Anonymous10:20 AM

    Thanks for the great write up!

    I am interested in your statement that you have a unit test suite that run in less than one second.

    I am interested in how you achieved such a short duration. Our unit and functional test suite takes minutes rather than seconds.

    Thanks again,
    sinclair bain

    ReplyDelete
  6. Anonymous10:21 AM

    Never mind. Clicking links can be helpful :)

    ReplyDelete
  7. Sinclair,
    Our unit tests do not hit the database, which is generally the bottleneck in Rails unit tests. I've written several entries on how to create better/different unit tests.

    Specific to Rails:
    http://jayfields.blogspot.com/2006/06/ruby-on-rails-unit-tests.html
    http://jayfields.blogspot.com/2006/09/rubyrails-unit-testing-in-less-than-1.html
    http://jayfields.blogspot.com/2006/12/rails-activerecord-unit-testing.html
    http://jayfields.blogspot.com/2006/12/rails-unit-testing-activerecord.html

    General testing entires:
    http://jayfields.blogspot.com/2006/06/some-test-driven-development.html
    http://jayfields.blogspot.com/2006/06/more-test-driven-development.html

    ReplyDelete
  8. Jay, thank you for sharing the scope and success of your project.

    It bares repeting. You and your team have taken the tools, Ruby and Rails, and used them to craft a solution for this project. It is this fact - that Ruby and Rails facilitate crafting a solution - that make them "enterprise" ready.

    ReplyDelete
  9. I admire the kind of work you guys put in to this, but aren't you saying that Rails isn't Enterprise Ready, rather you've bend it to become so, in fact to such a degree that it's hardly recognized as Rails any more? All for the better, of course.

    That's not to say that any other technology is any more Enterprise Ready than Rails.

    I'd like to interpret your post so that the point is it takes careful, well thought out design decisions to make good software under needy, volatile domains. On top of that, general purpose Frameworks don't always make it easier unless you start customizing them to overcome their restrictions.

    ReplyDelete
  10. As usual, great post. IN YOUR FACE ENTERPRISE!

    ReplyDelete
  11. Kerry, you may find this interesting:

    http://www.addsimplicity.com/adding_simplicity_an_engi/2006/12/2pc_or_not_2pc_.html

    ReplyDelete

Note: Only a member of this blog may post a comment.