Ruby: Complexity cannot be reduced

There is a lot of discussion about concise code. Comparing Java to Ruby, obviously Ruby has more concise code (This article contains code examples, which could be written better and which experienced Java and Ruby developers would write in differently. But the examples were chosen to illustrate points).

Compare this Ruby code taken from the Pragmatic book

songType = if song.mp3Type == MP3::Jazz
            if song.written < Date.new(1935, 1, 1)
              Song::TradJazz
            else
              Song::Jazz
            end
          else
            Song::Other
          end

with the corresponding Java code:

public SongType getType(Song song)  {
       if (song.isMp3Type(Mp3Jazz.class) {
               if (song.isWrittenBefore(new Date(1,1,1935)) {
                       return SongType.TRAD_JAZZ;
               } else {
                       return SongType.JAZZ
               }
       } else {
               return SongType.OTHER;
       }
}

Java has more code than Ruby in this example, but the cyclomatic complexity is the same for both examples. Although the size of the Ruby example could be reduced, in this version the LOC is also the same. You can't reduce the CC with choosing another language, only by choosing another algorithm or language paradigm.

When adding comments to the code examples like this

/**
 * Gets the song type from a song. This does not
 * return the mp3 type information from the song
 * but tries to determine the song type from the mp3 type,
 * time period and other enviroment variables
 *
 * @param song the song which should be checked
 * @return the song type for the song
 */
public SongType getType(Song song);

or like this for a dynamic-reference-typed language:

/**
 * Gets the song type from a song. This does not
 * return the mp3 type information from the song
 * but tries to determine the song type from the mp3 type,
 * time period and other enviroment variables
 *
 * @param {Song} song the song which should be checked
 * @return {SongType} the song type for the song
 */
 def type(song) ...

The difference between the two language styles dimish and the CC [1] to understand the code for a developer which has never seen the method is the same. In his head he has to order and solve the nested if statements to come to an understanding of what the method does. He might parse the Ruby example faster, because it's more concise, but the understanding part after the mental parsing is the same. Current studies show though that people don't read and parse text word by word but detect meaning by looking at patterns of word beginnings and endings. This would suggest that less code doesn't increase parsing speed a lot.

If conciseness of code is the deciding factor for faster understanding written code, then languages like K should be instant (some K programmers claim to instantly understand code by seeing it). A Hilbert matrix [2] in K [3] looks like this:

 {1%(!x)+\:1+!y}

The Java example from before can be written more understandable, for example with the Hamcrest library. This code is even less concise, but easier to understand

public SongType getSongType(Song song)  {
       if (is(song.getMp3Type, equalTo(Mp3Jazz.class)) {
               if (is(song.written(), before(1,1,1935)) {
                  return SongType.TRAD_JAZZ;
               } else {
                  return SongType.JAZZ
               }
       } else {
               return SongType.OTHER;
       }
}

It would be very interesting to see studies which compare code styles, conciseness and cyclomatic complexity and how they releate tounderstanding code which you haven't written. Because as Robert Glass writes in the excellent facts and fallacies of software engineering: "Fact: Maintenance is the most important life cycle phase with 40-80% of the cost." I have currently the feeling that most language innovation happens with rapid development, not low maintainance.

[1] http://www.fromthetrench.com/category/cyclomatic-complexity/
[2] http://en.wikipedia.org/wiki/Hilbert_matrix
[3] http://www.langreiter.com/space/k-notes

Stephan Schmidt Administrator
CTO Coach , svese
Stephan is a CTO coach. He has been a coder since the early 80s, has founded several startups and worked in small and large companies as CTO. After he sold his latest startup he took up CTO coaching. He can be found on LinkedIn or follow him in Twitter.
follow me