Ruby: Productive Programming Language
Every few years something significant happens in the land of computer programming. In my opinion the Ruby computer language is such a landmark.
Over the years I have seen programmer productivity go up. These are no hard measured calculations, but I have the impression that every five years the speed of delivering software doubles. Not only that, the curve for writing maintainable software appears to increase linearly too. A lot of that speed can be attributed to the tools of a developer, and core to these tools is the computer language.
Computer languages are essentially alike. There are more similarities than differences between any language. Nevertheless, the differences have a large impact on solving problems, finding ways of expression and human interaction. For example, LISP, a language of great beauty and simplicity in conception, reflects its allegiance more to computers than to humans. A language easy to interpret is not necessarily easy to program, as many a student can attest. LISP's most amazing feature is that it shows with how few rules one can create a powerful computer language.
Structured languages like Pascal and C clearly bridged a gap between native assembler and quick, human-readable coding. C is still widely used where performance matters--it is possible to write close to the assembler, as the Linux and BSD kernels prove.
With C++ in the early nineties, I personally went through a period of exploration and discovery. Classes, objects, containers, operator overloading, the works. Reading Stroustrup's classic book was crucial to understanding C++ as a language, and I loved it. But with hindsight I can see it takes something extra to become productive in C++; it is not for everyone.
Java came to the rescue. A much simpler language with an elegance in OOP (object-oriented programming), Java does have some down sides, like slow JVMs dealing with large libraries. The language itself has some short comings too. Many experienced C++ programmers use Java, and the complaint will come that it feels like working with their hands tied behind the back. Nevertheless Java is great for corporate-type team programming efforts. As a language it goes some way in enforcing structure and using OOP concepts.
In parallel, two other languages made a mark in the nineties: Perl and Python. Both are (interpreted) scripting languages and have some real advantages over C++ and Java in terms of delivery time of software (more on that below). With current levels of computing power, performance is hardly an issue for most "user-land" software.
Perl was a revolution in a way. and most of its productivity boost was due to the introduction of a full programming language with light notation for regular expressions, arrays and especially hashes.
Perl has some real problems, though, as almost everyone will assert who has participated in large Perl programming efforts. Perl has OOP extensions, but they are non-obvious and laborious. I did enjoy learning Perl OOP because it taught me a lot about OOP itself and how to implement OOP in a language as a single hack. Writing Perl OOP, however, is no joy. Maintaining a large Perl source base is only possible with the highest level of discipline by the coders, and the language itself does not help enforcing correct coding practices.
Python is cleaner as a language though its OOP was added as an afterthought--and it shows. I spent some serious time looking into Python and did not like it that much. It gives a lot but runs short, for example, with object elements all being public. In a team effort, that means developers have trouble understanding how their classes are being used (or abused). In this situation, I would even have trouble trusting my own code. Operator overloading is ugly, the syntax of a colon after an if statement I find to be non-obvious, etc. The indentation idea is clever, but somehow it doesn't improve code readability. In short, Python almost makes it but not quite.
Late last year I got my hands on the Ruby book by the (self-named) pragmatic programmers, Dave Thomas and Andy Hunt. The book also has an on-line version. I read the book in one go, and it goes into the hall of fame of important computer books, as far as I am concerned, right next to the Stroustrup. After reading it, I almost skipped sleep for a week because I was so excited by the implications of Ruby, a programming language that reads like poetry.
The author of Ruby, Yukihiro Matsumoto, aka Matz, knows his languages (LISP, Small Talk, Perl, Python and others) and aimed to create his perfect language. Ruby follows the Principle of Least Surprise and, funny enough, gets close. It feels, in fact, exactly like the computer language I have wanted to design all my life (without really knowing it).
Ruby was developed after 1994 and does not carry the baggage of Perl and Python; it is the new kid on the block. It comes with extensive libraries, not as rich as Perl's CPAN, but after a year of working with Ruby, I haven't missed any critical components. Ruby is complete with HTML and FTP classes, CGI support, XML parsers, database libraries, GTK and Qt bindings and even a pure Ruby BTree library. It is also quite straightforward to link up Ruby and Python libraries, which gives it an even richer base. Ruby is well supported on UNIX and Windows; developing on UNIX and deploying on Windows works without a hitch, including GUI development.
A very interesting study related to developer productivity was conducted by Lutz Prechelt. The outcome is that the amount of time needed for software delivery is directly correlated to the number of code lines that have to be written. Projects written in C++ and Java take double the number of lines as projects in Python and Perl, so the development effort takes roughly twice the time.
Writing code in Ruby improves productivity even more, surpassing Perl and Python. The syntax is very forgiving and feels natural; for example, there are no semi-colons.
if i == 15 print i end
Maybe I am worse than other developers, but I find I often have to execute an edit/compile cycle because of an end-of-line typo. Less interruptions make programming a flow-like effort, and it is amazing how often a piece of Ruby code is written and running in one go.
Because of Ruby's light syntax for defining a new class, it is really easy to create new ones and write support for testing at the class level:
# form.rb # # Form class derived from Document class Form < Document def initialize # ---- Constructor end def mymethod s # ---- Do something with s and return s print s s end end
This results in OOP design-on-the-fly and prevents the coder from lazily opting for other solutions. I have to admit that in Perl my OOP would degenerate because of the effort involved. With Ruby this never happens.
Certain language features available with Ruby are not available with the others. Ruby supports closures, which assign code responsibilities to the proper object result in cleaner code. Writing "for" and "while" loops is rare in Ruby. Also, less error-prone and cleaner constructs, like "each", become natural to implement.
Instead of (Java-like) every time:
Form form = forms.first(); while (form != form.last()) { if (form.valid()) { // ---- Do something } form = form.next(); }
the Ruby way is:
class Forms < Array def each_form each do | form | yield form if form.valid end end end forms.each_form do | form | # ---- Do something end
and the proper responsibility is captured within the Forms object.
For more complex projects maintainability becomes an issue. Proper OOP design helps bring structure and makes the source code logical and transparent. All these languages support OOP to a certain degree, but Ruby shines in ease of use and predictability.
Delving deeper into the niceties of Ruby is beyond the scope of this article. I strongly recommend the book by Thomas and Hunt and also Matz's Ruby in a Nutshell. The latter book is merely a reference, though, and won't take you through the dazzling heights that Programming Ruby will.
People often ask the following questions:
Why should I learn another programming language?
Or laziness versus love. Every computer language has something to offer, and the added insights will make you a better programmer. Java taught me to write better C++; Ruby taught me so much I don't intend to go back.
Why move from Python?
If you are happy with Python, there is, arguably, not a significant reason to switch. There are even two pretty strong cases for Python: the Zope WWW framework and Jython, both of which are very attractive in specific circumstances.
There are quite a number of Python programmers that have switched to Ruby. It may be a lot more rewarding than it looks. Remember the days when people were questioning a change from Perl to Python? Once switched no one appears to want to go back.
ESR made quite a strong case in Linux Journal a while back for moving from Perl or C++ to Python. All his arguments are familiar and applicable to Ruby.
Why move from Java?
Ruby's role may be to both strengthen and replace Java. Java's strength, at this moment, is for medium to large server-side projects and distributed environments. Ruby kicks in on the deployment side and for writing proof-of-concepts. Meanwhile a lot of programming concepts in Ruby are related to Java. I can see Ruby playing a role in these environments once bindings become available. Matz is working on a byte-code version of Ruby, and a JRuby project took off on jruby.sourceforge.net.
Java is strongly embedded as a language in corporate environments, however, and will be for some time to come. In addition, working with Java is intentionally very verbose, but that also means it takes a lot of time to achieve the same results.
What about Perl6?
Perl6 appears to have a lot of new features. Mostly, though, it is still vapourware. Meanwhile Perl, even in its version 5 incarnation, contains a lot of baggage. Even if it tries to provide functionality similar to Ruby, it will never be as clean.
I have more than five years of Perl under my belt and only one of Ruby. Coding Perl still makes me revisit syntax issues often and reread information on functions. With Ruby my experience is that going back to the manuals is a much rarer occasion. I don't expect Perl6 to change that.
For raw performance, C/C++ is still the best choice. For large multiplatform team efforts you may be best off with Java. But when it comes to delivering speed and proof-of-concepts, you should think seriously about using Python or Ruby. Perl I would reserve for system administration tasks.
Ruby has some distinct advantages over Python. It is a far cleaner OOP language with excellent features, and it supports Perl's regex type terse notation. It also scores high in enabling one to write short concise and maintainable code. In fact I do most of my development in Ruby now, touching Java and C++ only when I have to.
Ruby may not be a new paradigm, nor represent a new generation, but it combines the best of many programming languages and takes productivity to a new level. I am not original in stating that Ruby may supersede both Perl and Python and will make many a Java programmer envious.
Programming Ruby by David Thomas and Andrew Hunt, Addison-Wesley, October 2000, ISBN: 0201710897. Also on-line at www.rubycentral.com/book.
Ruby in a Nutshell by Yukihiro Matsumoto, November 2001, ISBN 0-59600-214-9. See www.oreilly.com/catalog/ruby for more information.
The Ruby Language web site is www.ruby-lang.org/en/.
The Ruby Application Archive contains many libraries and bindings and can be found at www.ruby-lang.org/en/raa.html/.
The pragmatic programmers are at www.pragmaticprogrammer.com/ruby/.
The C++ Programming Language, Bjarne Stroustrup, Addison-Wesley; ISBN: 0201700735
Pjotr Prins is senior developer for Causeway Technologies and has a real passion for development. He is convinced of the lower cost of maintenance of Linux systems (deploying some 30 ROCK Linux servers), Editor-in-Chief for the EUP E-zine and contributor to ROCK Linux and other open-source projects.
email: pjotr@thebird.nl