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


2 Responses to “Ruby: Complexity cannot be reduced”  

  1. Gravatar Icon 1 afsina

    Some thoughts on your java code:

    - new Date(1,1,1935) is deprecated. you can use GregorianCalendar instead. Java 7 will have better datetime handlin tough.

    - you can use static import for SongType in Java code, it would reduce the code crowd. as: SongType.TRAD_JAZZ -> TRAD_JAZZ

    Lastly,

    if (song.isMp3Type(Mp3Jazz.class) sounds a little awkward to me. it smells a little but cannot say much before i see the full code.

  2. Gravatar Icon 2 stephan

    Hi afsina, thanks for your comment.

    Some thoughts on your comment:

    - I usually use JODA or a Calendar (if I have to)

    - I wanted to stay close to the Ruby example, as the preface states: “This article contains code examples, which could be written better and which experienced Java and Ruby developers would write differently.”

    - As said there is no full code. These were some code example to illustrate the CC points made in the post (”But the examples were chosen to illustrate points”).

Leave a Reply



RSS