Friday, December 02, 2005

An argument for using Ruby on Rails rather than Java

I was a little nervous about telling my boss I'd decided that the apps we were going to be building would be implemented in Rails rather than J2EE. After all, he is an ex-Oracle guy who knows J2EE. I was hired because of my J2EE background. And all the conversations we'd had to-date were around using J2EE (although not in any technical detail).

I took a few minutes one Saturday afternoon and wrote up my reasoning on the subject. The primary goal being to produce something quickly. Since we're still in the process of hiring, the initial applications we'll be building will be done by existing engineers who don't know J2EE any better than they do Ruby or Rails. So I figured we needed to take a hit with the learning curve anyway. It is a good opportunity to get tooled up with Rails. If it doesn't work out, we will have built a decent prototype and can build the real system(s) in Java.

Here's my email to him (only slightly edited). The code examples are from Ruby on Rails and J2EE: Is there room for both? I took a little poetic license with some of the explanations, but that was because I wanted to keep it as brief as possible. I thought about using some of the diagrams from the RoR vs J2EE article, but figured that would get too technical.

(Said that I'm using RoR on our project)

First some history:

Over the past 5 years or so I've been deeply immersed in the J2EE world and have been following the architectural trends there carefully. The overall trend is abandonment of the "heavyweight" J2EE framework itself for a collection of lighter weight frameworks. For example, a few years ago, the common consensus among J2EE architects was that EJB was typically not necessary in most applications, and even in cases where it provided useful capabilities, it was difficult to implement and too expensive to maintain simply for transactionality or object/relational mapping. New frameworks have been popping up all over the place—Spring, Hibernate, Tapestry, WebWorks, etc.

I'm a big believer in development frameworks. Too many shops spend too much of their time reinventing the wheel building application infrastructure when they should be using existing best practice pattern implementations and concentrating programmers on the "domain" problem at hand. J2EE and Java have blazed a trail, proven the value of design patterns, and taken a lot of knocks along the way. Java and J2EE are battle scared as a result. And J2EE in particular has picked up a lot of baggage that it would probably be better without.

During this same period, architects discovered where the core value from component frameworks like J2EE lies, and distilled this into new frameworks. A big surprise was how productive programmers are using these new frameworks. A good example is in object/relational mapping. For example, given the problem of defining an "order" object and providing persistence, in the most productive Java persistence framework in use today (Hibernate), three major aspects need to be considered:

  1. Modeling the "order" entity in a database. This might involve a table called "orders" with columns like Id and Name, and a relation to another table named "items".
  2. Tooling up and deploying a Servlet or J2EE container (i.e, Tomcat) and the Hibernate framework
  3. Writing (and maintaining) code such as the following:
  

<hibernate-mapping>
<class name="models.Order" table="ORDERS"
dynamic-update="true" dynamic-insert="false"
discriminator-value="null">

<id name="id" column="id" type="java.lang.Long"
unsaved-value="null">

</id>

<set name="items" lazy="false" inverse="false"
cascade="none" sort="unsorted">
<key column="id"/>
<one-to-many class="models.Item"/>
</set>

<property name="name" type="java.lang.String"
update="true" insert="true"
access="property" column="name"/>
</class>
</hibernate-mapping>


(Hibernate Mapping File)

public class Order {
    private Set items;
     private String name;
     private Long id;
     public Long getId() { return id;}
     public void setId(Long id) { this.id = id;}
     public Set getItems() { return items;}
     public void setItems(Set items) { this.items = items; }
     public String getName() { return name; }
     public void setName(String name) { this.name = name; }
}

(Order JavaBean)

Rails was developed from the beginning as a framework that natively implements some of the best practice patterns. In the case of persistence, it implements the object relational pattern defined in the pattern texts as an "Active Record." This implementation takes advantage of Ruby's abilities for reflection. It reduces the above Java implementation of an "order" entity stored in a database to the following three tasks:

  1. Modeling the "order" entity in a database. This might involve a table called "orders" with columsn like Id, Name, and a relation to another table named "items".
  2. Tooling up with the Rails framework (no separate Servlet container/OR framework is necessary)
  3. Writing the following source code:
class Order <>
  has_many :items
end

In the above example, if you would like to add a new attribute to your order entity in your object model, you need only add a new column to your orders table in the database. The Rails framework uses the reflection capabilities of Ruby to expose the new attribute to the object model, and thus to your application.

Another huge productivity gain from Rails is the elegant implementation of the Model View Controller (MVC) interaction pattern. In Java/Struts works well initially, but its configuration based approach can quickly become a tangled mess and over time tends to evolve into a rigid, brittle application that is difficult to extend and maintain.

Rails implements MVC as a first class citizen in the framework. And breaks out the model (for example, the "Order" object above), the controller (which implements action classes and methods that act on the model), and the view (in this case, Rails HTML files), into separate files in their own directories under a common application source structure. Again, using Ruby's capabilities for reflection, Rails wires together the MVC components into a running application based simply on naming conventions, object inheritance and the location of source in certain directories. The result is an elegant and surprisingly modular implementation of MVC. For example, was able to add the "file upload" capabilities to our existing prototype by finding a Rails implementation of file upload on the Internet and dropping the MVC component files into the appropriate directories in our project. This was within only a couple of days of getting started with Rails.

One other highlight to mention is that Rails is cited as being the easiest web framework available for implementing Ajax style web programming. Ajax is an acronym standing for Asynchronous JavaScript and XML. If you use any of Google's applications (such as Gmail or Google Maps), Flickr, Amazon's A9.com, you'll notice that a ton of functionality is implemented without round trips from the browser to the server. This model of programming is catching on fast, and is one of the driving forces behind Rails' explosive growth. The authoritative Rails book, Agile Programming with Ruby on Rails recently reached #1 in Amazon's sales rankings in the Computers/Internet category. It's ranks roughly 250 in Amazon's overall sales. Developers are really excited about using Rails. Use of Rails attracts talent to our work.

My current thinking is that we use Rails to get a lot done quickly. In addition to rapid development, we'll tool up the developers with best practice patterns in mind. If long term we need to shift technology, we've codified good patterns and architecture into our team—something that's harder to teach, in my experience, than a particular technology or framework.

0 Comments:

Post a Comment

<< Home