Skip to main content

Crossing borders: A Rails case study

How day-to-day Rails development compares to Java programming

Bruce Tate (bruce.tate@j2life.com), CTO, WellGood LLC
Bruce Tate
Bruce Tate is a father, mountain biker, and kayaker in Austin, Texas. The CTO of WellGood LLC and the chief architect behind ChangingThePresent.org, he's also the author of three best-selling Java books, including the Jolt winner Better, Faster, Lighter Java. He recently released From Java to Ruby and Rails: Up and Running. He spent 13 years at IBM and later formed the RapidRed consultancy, where he specialized in lightweight development strategies and architectures based on Ruby, and in the Ruby on Rails framework.

Summary:  Ruby on Rails development and Java™ development differ in fundamental ways. In this final installment of Crossing borders, Bruce Tate outlines the major differences he's discovered by using Rails to develop a complex, scalable Web site from the ground up.

View more content in this series

Date:  10 Apr 2007
Level:  Intermediate
Activity:  2845 views

Rails developers often see their Java counterparts as stodgy, laboring relics of the past. And Java visionaries often paint Ruby on Rails as a toy with no place in any serious software development. As a consultant who has worked extensively with both approaches, I know that the truth lies somewhere in between. As this Crossing borders series closes, I'd like to do one more comparison. Rather than look at a particular technology or language, I'll focus on my current project and compare it with the Java projects I've worked on in the past. (Along the way, I'll point you to previous Crossing borders installments that dig more deeply into relevant topics.) This first-hand account should give you an appreciation of the trade-offs and potential net gains involved in using Rails for green-field development of database-backed Web applications.

The business problem

About this series

In the Crossing borders series, author Bruce Tate advances the notion that today's Java programmers are well served by learning other approaches and languages. The programming landscape has changed since Java technology was the obvious best choice for all development projects. Other frameworks are shaping the way Java frameworks are built, and the concepts you learn from other languages can inform your Java programming. The Python (or Ruby, or Smalltalk, or ... fill in the blank) code you write can change the way that you approach Java coding.

This series introduces you to programming concepts and techniques that are radically different from, but also directly applicable to, Java development. In some cases, you'll need to integrate the technology to take advantage of it. In others, you'll be able to apply the concepts directly. The individual tool isn't as important as the idea that other languages and frameworks can influence developers, frameworks, and even fundamental approaches in the Java community.

Neither Ruby on Rails nor any Java framework is the right solution to every problem. To have the best possible chance for success, you need to take a long, hard look at your business problem, understand the surrounding assumptions, and know your team. Only then can you choose a good language to solve your problem.

Last year, Arvato Systems hired me to lead a team that would build ChangingThePresent.org, a new marketplace that would bring nonprofits and donors together. Like many Internet companies, we would present tangible products that our customers could then buy. Unlike other companies, the "products" represent giving opportunities, such as an hour of a cancer researcher's time for $50, helping a blind person see for $30, or preserving an acre of the rain forest for a month for $20. We had two major challenges: an ambitious schedule and long-term complexity.

We were to start development in September, and we would need a compelling site up by November to have a real shot at getting traffic from the Christmas season. (We eventually missed the November target by two weeks.) From other bids, we knew that a Java-based solution would likely take 6 to 18 months to complete. So productivity was a huge concern, pointing away from a Java deployment.

From looking at our competition and projections, we knew we'd be able to drive traffic to the site on the order of millions of hits per day. We'd need to drive hundreds of thousands of daily hits to be successful, so scalability was also a concern. This concern pointed to a Java deployment.

Finally, we knew that even after the original site was launched, we would only be just beginning. We would launch with only three percent of our total plans. So the technology we chose would need to scale in terms of complexity as well as load. I believed that the Ruby language -- with its support for higher-level languages and features such as open classes -- and the Rails framework -- with reduced configuration requirements and a much simpler, integrated programming model -- would scale better in terms of complexity.

Though the time and scalability challenges worked against us, other factors worked in our favor. We had a completely blank slate: we could choose any technology, and any team, that we wanted. We could define the project, culture, and full technology stack. We had complete freedom to choose.

The Java language is an excellent general-purpose language. It is always pushing into new frontiers, such as embedded systems and mobile devices. The Java language also excels in the integration of broad concerns. It is high-performing, popular, and well supported in the marketplace. But as you've seen in this series, the Java language is not necessarily the best choice for green-field development of database-backed Web applications (see the article "Web development strategies in dynamically typed languages").

By contrast, the Ruby on Rails framework is new. Not many people have used Rails for high-traffic sites, and experience with multiyear development projects is almost nonexistent. Still, Rails is an extremely productive framework for database-backed Web applications. In the end, our aggressive schedules led us to choose Ruby on Rails, though we were concerned about the dearth of experience for Rails in long-term projects or high-volume deployments.

Once we'd made the decision, we found it easy to recruit talent for the project. We also found that our early productivity was fantastic -- even greater than we'd expected. We did have some early problems with stability, so we redoubled our testing efforts (see the articles "Testing in integrated frameworks, Part 1" and "Testing in integrated frameworks, Part 2"). We've since improved our stability tremendously.


Philosophy

Each framework designer works with a set of assumptions that make up that framework's overriding philosophy. Learn to live within that philosophy's constraints, and you're a happy programmer. Fight them, and you'll be smashing your equipment in frustration. Rails and Java frameworks have vastly different philosophies.

Rails is an integrated framework that heavily leverages the dynamic nature of the Ruby language (see the article "What's the secret sauce in Ruby on Rails?"). Rails developers emphasize features of the framework for productivity rather than tools and usually take a simplistic view of Web architecture, as you've seen in past articles of this series. Java designers must often craft together their environment piecemeal, choosing persistence, Web, and integration tiers independently. They often rely heavily on tools to simplify core tasks. Web architectures tend to be more complex by design.

Full integration

Where Java frameworks tend to solve one small problem such as persistence or view organization, Rails is an integrated environment. The upside for Rails developers is that they don't need to solve problems of integrating many different frameworks. Most Hibernate developers have fallen into the trap of prematurely closing connections with Java Web frameworks. The Rails view frameworks are built from the ground up to integrate with ActiveRecord, the Rails persistence framework. You'll find similar experiences when you look at the Rails frameworks for Web services, configuration, and plug-ins. Java programming supports vastly different frameworks, with different integration strategies for all of these things.

The upside for Java developers is choice. If you need to build a framework from scratch, you might considering using a SQL-based solution for database integration such as iBATIS or one of the many JDBC-based wrapping frameworks in Java programming. If, instead, you were starting with a legacy schema, you might decide to use an object-relational mapping framework like Hibernate. If you're using Rails, by contrast, you have one major choice: ActiveRecord. That means that Java frameworks, providing greater choice, sometimes make better solutions for integrated development projects. But because we were developing a green-field project, choice was not as much of an issue.

A dynamic language

The next major part of the Rails philosophy is the dynamic programming language (see the article "Typing strategies beyond the Java model"). Java tools tend to make effective use of the extra information provided by the Java typing model. Tools can recognize errors and effectively restructure, or refactor, code. Rails also effectively leverages the advantages of the programming language. Ruby is an ideal language for building domain specific languages (DSLs) (see the article "Domain-specific languages in Active Record and Java programming"). Rails heavily engages DSLs to do everything from building relationships between model objects to specifying custom components such as state machines or uploadable images. Dynamic languages are often more concise, so Rails projects are much more terse than their Java counterparts, letting users express both code and configuration more concisely. At ChangingThePresent.org, we've noticed that our top programmers can be more productive, but we do need to recruit developers with more experience. I'm happy with that compromise.

The typical Java programmer is religiously passionate about his IDE, and with good reason. The IDE gives him syntax completion, fixes trivial errors, and provides incremental compilation for a quicker cycle between coding, compiling, deploying, and testing. In recent years, development environments began taking even more advantage of the information provided by the compile cycle and static typing. IDEs now edit the abstract syntax tree (AST) instead of, or in addition to, a text representation of the code. This strategy allows powerful code refactoring tools, which are much more difficult to achieve using the same methods for statically typed languages.

Static typing does allow better tooling, but there's a downside, too. Enforcing static typing usually requires a compiler, and that compile step can absolutely crush productivity. With Rails, I can change a line of code and reload the browser, immediately seeing the results of the change. In contrast to Java developers, most Ruby developers use only a good editor. TextMate, the most popular Ruby on Rails editor, provides syntax highlighting, some code completion, and good template support for frequently used constructs. And the editor is more than enough when you throw in all of the simple Ruby-based scripts that serve as the basic toolkit for Rails. Rather than a full debugger, I can use the breakpointer script, which can stop a given application and place me in a Ruby interpreter where I can invoke methods, inspect variable values, and even modify code before resuming execution.

Simple architectures

The typical Java architecture on the Web side has a layer for domain objects, data access objects, a facade layer that provides a business-level API, a controller layer, and a view layer. This architecture is a little more complicated than the classic model-view-controller architecture, which was first pioneered using the Smalltalk language. By contrast, Ruby on Rails uses a single model layer using the ActiveRecord design pattern, a controller layer, and a view layer. We like the Rails approach, hands down. It's much more concise and leaves less room for additional complexity or errors.

Convention over configuration

Java frameworks usually use XML configuration liberally, while Rails primarily uses conventions to avoid configuration where possible. Where the programmer must specify configuration, Rails usually relies on Ruby, often in the form of a DSL, to provide configuration. For green-field development, I find convention over configuration makes sense. The strategy saves me many lines of code and simplifies the code that I do need to write. We estimate that we have about one tenth of the configuration that would be specified in a typical Java application. We sometimes lose a little flexibility, but not enough to offset the tremendous savings.

All in all, the philosophies of the Rails framework fit the problem I needed to solve for ChangingThePresent.org. The integrated stack lets me get more functionality out of the framework without needing to do excessive integration myself. The convention-over-configuration philosophy saves me time as I try to configure the site. The dynamic language gives my seasoned developers more power and flexibility, while also letting them express more powerful ideas with fewer lines of code. The framework fits my team's abilities as well as the business problem we're solving.


Persistence

The most popular persistence frameworks for the Java and Ruby languages illustrate the differences between the Java and Ruby experiences better than any other feature. Java developers usually reach for Hibernate, an object-relational mapping framework. With Hibernate, you take an existing model and an existing schema and express a map between them using annotations or XML. Hibernate classes are plain old Java objects (POJOs), with each object derived from a common base class. Most configuration is explicit, using annotations, XML, or some combination of both.

ActiveRecord, instead, is a wrapping framework, meaning each class is a wrapper around an existing class (see the article "Exploring Active Record"). ActiveRecord automatically adds features to model objects based on the contents of the associated table, such as an attribute for each column in the table. All classes inherit from a common base class. ActiveRecord primarily infers configuration from common conventions. For example:

  • ActiveRecord infers the table's name from the plural form of the class's name.
  • The name of the primary key is id.
  • The sort order for lists is determined from a field called position.

Object-relational mapping is the best solution when you have a legacy schema, perhaps not defined with an object model in mind. But when you can design the database schema explicitly for your application, you often don't need a mapping framework. We see ActiveRecord as a tremendous advantage for us. We can embrace the relational database, dropping down into SQL as needed and staying above it when convenient.

Migrations

Rails migrations let us express the differences between two versions of our schema, and the data they contain, in code (see the article "Rails migrations"). Each migration is named and numbered. I can move up or back to any version of the schema at any time. Migrations have some definite advantages, letting us:

  • Restore an older version of the schema when we push out bad code.
  • Express the schema in code instead of SQL, which is more convenient for us.
  • Be database independent, for the most part.

But migrations have limitations too. If two developers create migrations at the same time, the numbers get confused, and we must intervene manually. We minimize these problems with effective communication: Team members announce when they build a new model requiring a migration. But this model depends on a small team of developers or a slow pace of migrations.

ActiveRecord does have other limitations, some of them intentional. The Rails founder believes that database constraints and composition belong in the application instead of the database, and this causes side effects. ActiveRecord doesn't use views very well: the build process that clones the schema, copies the test data, and runs tests does not copy them correctly. ActiveRecord also has trouble in some cases with referential integrity constraints because some types of associations might connect to more than one database table. Eager loading across complex models is complex, usually requiring SQL when many rows must be joined. Inheritance is limited: with ActiveRecord, I'm forced to use a mapping strategy called single table inheritance (see Resources), which is not always optimal.

All persistence strategies are rife with compromises. I believe that ActiveRecord strikes an effective set of compromises, usually erring on the side of simplicity. All in all, ActiveRecord plus migrations is a net positive for us. We can build our solutions quickly, and we have enough access to SQL to improve performance when needed. But it would be nice to use Rails on projects having legacy schemas, when ActiveRecord is not always up to the challenge. Alternative persistence models are emerging, including RBatis, a port of the iBATIS Java framework (see Resources). It's too early to tell how effective RBatis will be.


Wrapping up

For my team and my set of circumstances, Ruby on Rails has turned out to be wildly effective. I don't yet know how the project will ultimately scale because we've been live for only three months as I write this article. We're only now starting to drive traffic. But we do know about productivity. I know that the team came in way under the budgets of competing shops, which usually bid Java solutions. I am also confident in our productivity.

Throughout the Crossing borders series, I've exposed you to languages and solutions outside of the realm of the Java experience. Programmers are, after all, craftsmen. Each master craftsman's toolbox should contain a broad set of tools that are right for each situation. Beyond tools, the perspective that you've seen here will expose you to other ideas you can use. Even now, framework designers are applying techniques found in Seaside, Rails, and even JavaScript in Java frameworks today. Look for the chance to do the same, to keep crossing borders.


Resources

Learn

Get products and technologies

  • Ruby on Rails: Download the open source Ruby on Rails Web framework.

Discuss

About the author

Bruce Tate

Bruce Tate is a father, mountain biker, and kayaker in Austin, Texas. The CTO of WellGood LLC and the chief architect behind ChangingThePresent.org, he's also the author of three best-selling Java books, including the Jolt winner Better, Faster, Lighter Java. He recently released From Java to Ruby and Rails: Up and Running. He spent 13 years at IBM and later formed the RapidRed consultancy, where he specialized in lightweight development strategies and architectures based on Ruby, and in the Ruby on Rails framework.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology, Web development
ArticleID=208515
ArticleTitle=Crossing borders: A Rails case study
publish-date=04102007
author1-email=bruce.tate@j2life.com
author1-email-cc=bruce.tate@j2life.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers