Ruby on Rails is a web programming framework written in a dynamic oo programming language called Ruby. Ruby exists for quite some time but with Ruby on Rails it was hyped during the last months.
There are some key features that make Ruby attractive:
- No compile time since it is interpreted.
- Compact syntax.
- Powerful reflection.
I was always a fan of statically typed languages like Java. With this background there are drawbacks to the Ruby approach:
- You can’t use a compiler to find type errors.
- By reading source code it is hard to find out what type an object might have.
- There are nearly no refactoring tools for Ruby available.
- Ruby has a de facto standard for web applications (Ruby on Rails) but only poor non-standard support for rich client destop applications.
But also Java has its drawbacks. After having several years of experience with large J2EE projects I these drawbacks became clearer to me.
- Although some Java IDEs can compile incrementally, recompilation of large parts of the project is often neccessary and slow.
- Java programs are full of type casts breaking type safety. That mighth change with the generics of Java 5.
- With J2EE you need lots of hard to understand XML configuration.
- The XML configuration files break type safety. The compiler becomes less and less useful.
- The refactoring support for XML configuration files is quite poor in the moment.
- Java needs much more code and configuation than Ruby. Here is a comparison. In that comparison the Ruby application also is faster than the Java application.
To me the obvious difference between Ruby and Java always was type checking. Ruby does no automatic type checking. Java does automatic type checking during compile time. Therefore Java can find more bugs than Ruby. Now I no longer believe that type checking is the point. As I wrote above type checking becomes less useful in Java systems. In Ruby and in Java a lot of real value type checking is done in unit tests. Perhaps the type checking in Ruby systems is even stronger than in Java systems. In a Ruby system the programmer knows that he has to write unit tests. In Java it seems optional to a lot of developers to write unit tests – do they think that the compile time checkings are sufficient?
So, what are the key differences between Ruby and Java in real world projects? I think there a three main aspects:
- Ruby programs are more compact than Java programs. Less lines of code means less programming errors. That is a clear advantage for Ruby.
- Refactoring is now state of the art. Java IDEs have powerful refactoring tools. Ruby has poor refactoring support und in some aspects the Ruby refactoring support will stay weak. It has the Smalltalk problem that you never now on what object a method will be called. Therefore renaming a method has to rename all methods with the same name. Therefore a big plus for Java now. But hopefully Ruby refactoring tools will evolve.
- Source code is written once and read many times. Therefore source code has to be easy to understand. I find it helpful to know what type of object the programmer of a method expects as a parameter. In Java it is easy. The type is declared in the method signature. In Ruby programs it is often hard to find out what the programmer really expected. Conventions help but I have the feeling that the Java way is superior here.
So, what has Ruby to do to gain world domination? Here are my 2 cents:
- Ruby needs a refactoring tool. At least with “Rename Class”, “Rename Method”, “Rename Attribute”, “Extract Method” and “Inline Method”. The last one might sound a bit special but Tammo Freese described the real power of the “Inline Method” refactoring in a presentation at the XP 2003 conference. We used his ideas in our Refactoring Book.
- Ruby needs at least a convention used by everyone to annotate the expected type of an object. It would be even better to check the type at runtime. Perhaps there should be a language extension for annotating dynamic type checks in an elegant standard way. This information could be used by refactoring tools also to be more specific when refactoring methods.