Saturday, December 15, 2007

Still something about Ruby

In my continuing objections against Ruby, I've been studying the core API docs on http://www.ruby-doc.org/core/

It seems to be quite a mixed bag. A few classes seem quite reasonable but most are cluttered with obscure methods with opaque names. Let me give you a few examples:

What do you think String.tr(...) does? What about Date.amjd()? Nope, I've not got a clue either.

If you want to know when a file was last modified, which of these is clearer: mtime() or lastModified()? When you're reading code, looking for bugs or trying to modify someone else's creation, clarity is important. You read code far more often than you write it, saving a few keystrokes during authorship may impress your script-kiddy friends but it won't impress your boss when it takes ten times longer to understand afterwards, especially when you have to keep referring to the API docs to tell you what the 'hton' method does.

If all this wasn't frustrating enough, there are aliases to confuse you. What's wrong with having one method name to perform one function? Isn't Queue.pop enough? What's the point in having an alias for it called 'deq'? Whatever happened to DRY?

By far one of the worst classes in Ruby for method names, repetition and bad organisation is the Array class. It has an 'each_index' method which is the same as looping 'n' times where 'n' is the length of the array. Array.fetch(-1, nil) does the same thing as array.last(), array[-1] or array.at(-1). Abbrev is a method that only works if each of the elements in the array is a string. From an OO point of view, the Array class shouldn't have methods that deal with specific array structures and content. The same applies to the 'assoc' method. Both of these (and more, e.g. transpose) belong in separate classes. Pop and delete_at(-1) do the same thing and there seem to be at least half a dozen ways of appending something to an array.

On the whole, Ruby doesn't seem to me to be very object oriented. Yes everything is an object and there are classes and inheritance but OO goes way beyond those basic components. It's about sensible organisation and separation of concerns. It's about clarity and simplicity wherever possible, it's an entire programming paradigm, not just a language feature set.

Labels: , , ,

Tuesday, December 11, 2007

Something about Ruby

I know there are some things I don't like about Java and that it's missing some useful features but the Ruby crowd seem to be disproportionately vocal about how amazingly easy and quick (in terms of typing) things are in Ruby. In doing so they make themsevles wide open to criticism. One of the most frequent claims I hear about Ruby is how the syntax reads naturally and makes it obvious what's going on.

Yeah, right.

If I want to create a 'new object', I have to write 'object new' like this:

foo = Foo.new(...params...);

In Java it reads more naturally :

foo = new Foo(...params...);

The gap between the classname and the parentheses that is created by having the 'new' keyword between them detracts from the most important elements of the statement. Having the 'new' keyword at the beginning makes it more obvious what is going on.

Iteration suffers from the same problem. The placement of the keyword after the variable name makes it harder to see that this is in fact a loop:

@names.each do name
puts "Hello #{name}!"
end

It's not until your eye is half-way through the first line that you realise that this is a loop. Compare this with Java:

for (name : names) {
System.out.printf("Hello %1$s!", name);
}

Much clearer.

Ruby does have an apparently neat way of looping using integers like this :

4.times do
puts "Hello"
end

My problem with this is that it introduces a new keyword for iteration. The Java designers considered having 'foreach' instead of the enhanced for loop and rejected it for that precise reason. Why make the language bigger than it needs to be with too many keywords? Couldn't they have used '4.each do' instead?

A strange omission from Ruby which would have made a lot of sense and would be in keeping with its syntax is how you find the square root of a number. It's the same in Java as it is in Ruby:

a = Math.sqrt(9);

Why didn't they implement it like this?:

a = 9.sqrt();

While you can write compact code with Ruby, as you can in a lot of scripting languages, this doesn't mean it's a good thing to do. Sometimes a bit of verbosity is useful, as long as it's not excessive. The syntax of Ruby is a jumbled, inconsistent mess. It seems that is was based on a vaguely similar syntax to Java but with seemingly random changes which the authors thought were improvements. Instead, they've made the language so that a lot of statements read backwards in english. For example, 'object new' instead of 'new object' as I've already pointed out. Blocks, loops and methods have to end with the 'end' keyword (and sometimes start with 'do') but it's far easier to see blocks of code if they are delineated with the symbols { and } instead of having to read a whole word. The brain is quicker at understanding single symbols than reading words.

I could go on and on. While Ruby does have some nice features that I would like to see in Java, on the whole it's not a language that is suitable for large scale developments continuing over a number of years with dozens of different developers being involved over its lifetime. Oh and don't get me started on Ruby on Rails and it's appalling HTML markup syntax which is unneccessarily verbose and difficult to read. As for speed of development, well anyone can write a blog application if someone's already written a script to generate it for you.

Labels: , , , ,