When evaluating what technology to use when developing QCron, we decided it was a good opportunity for us to gain some Ruby and Rails experience, and do a reality check on the hype surrounding them.
We started working in Ruby with a background of developing Java and .NET applications, with the usual frameworks (Struts, Hibernate, Jasper, Display Tag, etc.), and some academic Smalltalk background, which helped us understand the dynamic nature of Ruby faster.
Now that we have used it some and know its strengths and weeknesses, we’d like to share some of the great features we liked about Ruby. So here they are.
Everything is an object
In ruby -as in languages such as Smalltalk-, everything is an object.
This means there is no distinction between “data types”, and objects. Everything -yes, I’m repeating myself- is an object.
What are the advantages to it?
Well, you can write code that reads:
5.times do { … }
Can you imagine the same other languages? (Ok, I’m thinking Java and C#).
In the same way, you can override class methods (aka static in Java or C#) since classes themselves are objects with the same properties as any other object.
Moreover, you can add your own methods to system classes! So, if you happen to design a system where a magical number is 14, you could implement a method in Number so that:
13.is_my_magical_number? => false
14.is_my_magical_number? => true
Blocks!
Again similar to Smalltalk, Ruby provides support for code blocks. What is a code block you may ask?
Code blocks are pieces of code that get executed in the context of another method. You can think of blocks as anonymous functions.
Blocks were created to be used with collection iterators. The main logic for the abstraction is:
The client code shouldn’t need to know the internals of the class so to know how to iterate it, but the collection itself should be able to yield each of its values at a time.
As Ruby’s creator said in an interview [1], blocks evolved to be used in much more scenarios than on collections, which is fantastic.
So, collections can have a method that receives a block of code, and executes it for each of the collection values. For example:
# Array definition
a = [1, 2, 3, 4, 5, 6, 7]
# Select call on the array
a.select { i i.even? }
Here the block code is the code within curly braces. As you can see, select is a method on the Array class that iterates through the collection and keeps only the values for which the block evaluated to true. In this case, the even values.
Can you think of such a small code to achieve the same in Java? [2]
Syntax (and redundant names)
I don’t see a point on arguing on whether or not a language’s syntax is better than other’s. Every language has its fans.
That said, I really like Ruby’s syntax, because it’s a simple yet very expressive one. For instance, if you were to write a full_name method, that concatenates the first name and last name of an object, in Ruby you’d do something like this:
[first_name, last_name].join(‘ ‘)
This line creates a new array with first_name and last_name as its values, and join them separating them by a comma. While the same is possible in other languages (.NET has a Join method), I wouldn’t think of writing that code, because the code needed to instantiate a new array would clutter the code too much.
Another great sample of this are conditional expressions. In Ruby you have an if statement, but also an unless! Moreover, you can use your conditions before or after the code! So, instead of writing:
if not my_condition then
do_something
end
you could write:
do_something unless my_condition
Isn’t that great?
To end this post, I’ll conclude by saying that so far I’m impressed with the language (and with Rails, which I’ll speak of some other day). I’ll leave for other post more features such as message dispatching instead of method calls, and duck typing, which are core features that make this language so dynamic.
Is Ruby (and Rails) worth the hype? For me, clearly yes. Working with Ruby is a pleasure.
[1] http://www.artima.com/intv/closures.html
[2] Jakarta’s commons-collections help a lot by adding utility methods to Java’s collections. Yet, Java’s way to express anonymous functions (and C#’s), leaves a lot of room for improvement.