Ruby vs. Java Myth #2: Ruby feature X makes code unmaintainable

  • Posted By Stuart Halloway on June 03, 2007

Welcome to the second installment. You can catch the first myth here.

Ruby includes a variety of features that lead to compact, expressive code, e.g. open classes, dynamic evaluation, soft encapsulation rules, easy metaprogramming, and closures. These features demo well, but developers who have not used them fear that they will lead to unmaintainable code.

In reality, Ruby's powerful features make code more maintainable, when used correctly. (Learning to use these features correctly will be the subject of another myth.)

What makes code maintainable? You should be able to easily

  • Understand the overall design of an application or module
  • Find code you are looking for
  • Read the code
  • Make changes to the code
  • Verify that the changes work

Given these criteria, how do Java and Ruby stack up? I believe that the responsibility for maintainable code lies 80% with the programmer, and only 20% language and tools. With that caveat in mind, let's look at each point in turn.

Understand overall design. Advantage: Neither. In my experience, no language is very helpful here. Good abstractions help. Java and Ruby share many abstractions in common: implementation inheritance, classes, polymorphism, encapsulation, etc. The Java world has much better support for navigating these abstractions, via IDEs such as IntelliJ IDEA. On the other hand, Ruby has some useful constructs that Java lacks. Mixins help keep code more organized. Ruby makes it easy to create DSLs that accurately reflect and document your design.

Find the code you are looking for. Advantage: Java. Java's IDE support wins hands down. (It is worth remembering that many of us adopted Java when this IDE support was nonexistent.)

Read the code. Advantage: Ruby. Now we are down to the level of individual classes and methods. At this level, Ruby code is easier to keep DRY, and therefore easier to read. If you do not believe that Ruby is easier to keep DRY, then read about the Blub paradox.

Change the code. Advantage: Ruby. When you change code, you often move past the uses anticipated by the original author. At this point the compiler gets in your way, because some of the original author's assumptions need to be bent or broken. Change is much easier in a dynamic language.

Verify that the changes work. Advantage: Neither. If you are serious about quality, then you need to test. Manual testing is infeasible, so you need automated testing: unit tests, acceptance tests, continuous integration, the works. Both Java and Ruby provide good support for these.

Neither Ruby nor Java can make your code maintainable. I propose that we replace the old myth (feature X makes code unmaintainable) with no myth at all. If your primary argument for choosing a language is a presumption that language X will cause people to write maintainable code, then you have either a bad presumption, or the wrong people. You would be better off to pick a language at random, and change either the presumption or the people.

Comments
  1. BenJune 03, 2007 @ 02:33 PM

    I disagree with points 4 and 5. Having rolled out 5 smallish rails apps, implementing plugins, engines, custom generators etc (e.g. not just basic sites), I KNOW changing code in Java is easier. Its easier because I can refactor. Things dont break. I dont refactor in ruby because every time I did it was so horrible to manually fix everything, including the tests. So ruby loses on both counts.

    I know Java wins on both 4 and 5, hands down. How many million line Java projects have you managed, and how many 100KLOC ruby projects? I have managed both and at 1/10th the LOC, ruby was 5x more work to maintain, change and refactor.

    Understanding BASIC code, ruby wins hands down. The understanding of “tricky” code I am not so sure; I have never seen a piece of java code I can’t figure out, including obfuscated bytecode. I have definitely seen ruby code I cant, unobfuscated.

    FYI: When scala gets great refactoring support it will outclass both languages.

  2. DylanJune 03, 2007 @ 06:47 PM

    I think “Find the code you are looking for” should be reworded to be “Has the best IDE”. A lot of people do not use IDE’s, and, regardless of language, just grep.

    Heck, a proficient command-liner could grep, and be editing the necessary code, faster than any user of ‘any’ IDE. Ask any die hard Ed/VIm/Emacs user :)

    Otherwise, great article !

  3. JoeJune 03, 2007 @ 07:11 PM

    Ben, It sounds like you could just use a little more practice reading Ruby. Effectively reading code takes practice in any language. Ruby has a lot of clever idioms that can look foreign to some.

    I actually also disagree on point 4, but I lean the other way. Dynamic languages make it so much easier to write tests that it’s more likely that the tests will get written. Tests are also more of a necessity in dynamic languages because of the lack of the compiler. Given that, I think that Ruby has the advantage on code changes simply because it’s more likely to find better test coverage on an existing Ruby project than an existing Java project.

  4. DylanJune 03, 2007 @ 08:13 PM

    I’ll disagree with Ben on both of his points :)

  5. Stephan SchmidtJune 04, 2007 @ 05:17 AM

    Talking to some people with big Rails deployments – they disagree. It would be refreshing if someone in all this language comparisons would cite a study, e.g. comparing the maintainance efforts for a 5 year old, 10k classes application. Then we would all be wiser and wouln’t need to speculate.

    I’ve been working on 1.5MLOC projects, currently I can not imagine doing them with a dynamic language, even if the code could be reduced to 500KLOC with a dynamic language because it’s more concise.

  6. Bob LeeJune 04, 2007 @ 09:49 PM

    Concision != Readability. You have to strike a balance between too much and too little information. Ruby has too little. Java sometimes has too much—closures will certainly help.

    I think Ruby is popular with some consultants because they spend more time writing than reading code. In big, long lived applications, maintenance has to be the #1 priority.

    Ruby is popular with some Java programmers because they don’t want to learn about types. I can’t blame them. Understanding types is hard. Programming Java without understanding types and truly utilizing an IDE is paying a hefty price and getting no return; of course you’re going to prefer Ruby.

    From my experience, types are worth the learning curve. The resulting code may be longer than the Ruby equivalent, but oftentimes I actually type less to accomplish it.

    That said, I think dynamic languages are good for glue code. For example, code which maps HTTP request parameters to objects. I also think types should be optional, but I don’t like Groovy, and I’ll take mandatory types over no types at all. I’ll be keeping an eye on Gilad Bracha’s new company in this regard.

  7. BenJune 05, 2007 @ 01:29 PM

    Umm im not sure I need to understand how to read ruby code better. Again I ask – how many 100Kloc ruby projects have you managed? How many 1M+loc java projects? I dont hear an answer.

    Its the problems you get when you have multiple dependencies (e.g. pdf report writing wouldnt work when we used rmagik and rails engines due to mixin conflicts) that make the code hard to understand, not the language itself. Its the problem of the power of the language – that with the ability to redefine things in one tiny snippet of code somewhere you have the ability to screw with stuff other people depend on. In java (which I use synonymously with eclipse), you simply call “show-call-hierarchy” to find anything calling it.

    Think about it – your code – yes your code – can work completely differently when using 1 small piece of code a few lines long. Thats absolute power, but easily screwed up. If you have managed big projects in ruby (and I mean rails) then you will understand the pain.

    Personally, I dont believe Java to be a blub language. You can do amazing things in java, eloquent, beautiful code; yet most developers are incapable of doing this. Its not the language people, its the coders. If ruby never had rails (DHH), it wouldnt have been a success. Look at zope before rails came along – python web dev was a joke.

    1 developer changed the world, but it could have just as easily been in Java, erlang or fortran (maybe) – its not the language, its the brains behind the framework.

    There are MANY frameworks that do very similar things in Java-land – but they all exist behind company doors. Rails IS slow compared to these, trust me, I have worked with one.

  8. Stephan SchmidtJune 05, 2007 @ 08:56 PM

    @Joe: ” Dynamic languages make it so much easier to write tests that it’s more likely that the tests will get written.” Care to provide an example?

    Otherwise I second everything Bob said except that I like Groovy.

    And from some very big Perl an Python projects, and some smaller Ruby projects in the 90ies, when we all first encountered dynamic languages, my experience is mostly bad. We had to drop some very large Perl applications (I know, it’s Perl) because noone left in the company could maintain them.

  9. Brian PontarelliJune 11, 2007 @ 08:07 PM

    Just a few things:

    1. Open classes can make reading code difficult because the code for the class is no longer centralized. This can be prevented by good standards and code reviews.

    2. When you saying reading code I’m inferring you mean a specific snippet of code written by an intelligent person. Therefore, I would say Ruby has some minor language advantages and major library advantages. The latter can easily be fixed in Java using the correct commons package such as Java.net commons. The former will hopefully show up at some point.

    Just as an example of #2:

    Map m = map(“key”, “value”, “key2”, “value2”); List l = asList(“foo”, “bar”, “baz”); String result = join(l, ”,”);