united-coders

TwitterFacebookGoogleRSS
  • Home
  • Authors
    • Christian Harms
    • Nico Heid
  • Newsletter
Home » basic rules for code readability and the if statement

basic rules for code readability and the if statement

Posted on August 1, 2011 by Christian Harms Posted in Uncategorized 9 Comments

Some reader knows my preference for programming languages like python or javascript. One reason is the readability (yes, this is possible with many languages except brainfuck or whitespace). Once we write some lines of code, but other developer has to read the lines of code several times while code reviews, debugging or refactoring.

Code should be readable like your normal language. I will start with a funny condition.

if ( !notOk != false ) {
  userObj.ask();
}

This is only confusing and you will never formulate this expression in a natural language. With several steps this term can be simply resolved:

  • ( !notOk != false )
  • ( !notOk == true )
  • ( !notOk)
  • now you should rethink the variable name:
    isOk = !notOk

And the result is more readable:

if ( isOk ) {
  userObj.ask();
}

if – if – if trees

After removing some comments and other code lines this is an other typical coding style:

if ( A ) {
  if ( !B ) {
    if ( C ) {
      f();
    }
  }
}

There shorter variant for clever coder looks like this line:

if ( A ) if ( !B ) if ( C ) { f(); }

But using logical operators the line is more readable:

if ( A && !B && C ) { f(); }

If you refactor a function with some levels of if-statements try to use logical operators instead of the if – trees. But it should be readable like a natural language.

Be careful while using & and/or comparing integer! Single & is in most languages the bit-wise AND operator, check the examples:

ANSI-C:
1 & 2 = 0
1 && 2 = 1 //it’s true, and true is 1

JavaScript:
1 & 2 = 0
1 && 2 = 2 // the first is true, so return the second

python:
1 & 2 = 0
1 and 2 = 2 # like the JavaScript variant

Java:
1 & 2 = 0
1 && 2 // not valid with int

The if – true – false assignment function

function isNameSet(name) {
  if (name===null || name==="") {
    return false;
  } else {
    return true;
}

Sometimes this construct is hidden in many lines of code and can found in other languages too. But in this simple form the more elegant solution is easy to understand:

function isNameSet(name) {
  return !(name==null || name=="");
}

But you only want to check it the value of name is set. Many languages like Javascript (read the all about types by Matthias Reuter) can convert the value directly into a truthy value (read more on The Elements of JavaScript Style by Douglas Crockford.

function isNameSet(name) {
  return name;
}

After reducing the function to nothing you can remove it and use the string-value directly in a condition.

if (!name) {
  name = window.prompt("What’s your name?");
}

use the ternary operator (carefully)

function genderStr(gender) {
  if ( gender == "m" ) {
    return "male"; 
  } else {
    return "female";
  }
}

The function can be generalized:

function trueFalseStr(cond, trueStr, falseStr) {
  if (cond) {
    return trueStr;
  } else {
    return falseStr;
  }
}

Or you can use the ternary operator (avaible in many languages):

return (gender == "m")? "male" : "female"

With python (since v2.5) the following term is available instead of the “?” operator:

return "male" if gender == "m" else "female"

An other variant works with the example values and is readable too:

return (gender=="m") and "male" or "female"

yoda conditions

I offered in a older arctile the helpful yoda conditions. This simple example show the difference:

if (value = 42) {
   ...
}

For preventing assignment in a condition (and get a compiler warning) use the constant first:

if (42 = value) {
   ...
}

I have to withdraw in the content of readablitiy my suggestion for yoda conditions!

many if statements for mapping values

I found a nice thread on stackoverflow.com:

function norm(v) {
  size = 7;
  if ( v > 10 ) size = 6;
  if ( v > 22 ) size = 5;
  if ( v > 51 ) size = 4;
  if ( v > 68 ) size = 3;
  if ( v > 117 ) size = 2;
  if ( v > 145 ) size = 1;
  return size;
}

There are many variants, the one with JavaScript with ternary operators is not readable:

function norm(v) {
  return return v > 145 ? 1 : v > 117 ? 2 : v > 68 ? 3 : v > 51 ? 4 : v > 22 ? 5 : v > 10 ? 6 : 7;
}

Or the calculated variant in ANSI C. It works only if a boolean value can converted to integer.

int norm(int x){
  return 7 - (x>10) - (x>22) - (x>51) - (x>68) - (x>117) - (x>145);
}

If would change the limits for a more readable variant (in python):

def norm(v):
    if   v< 11: size=7
    elif v< 23: size=6
    elif v< 52: size=5
    elif v< 69: size=4
    elif v

And now the variant can written as a list comprehension (ok, not better readable, but funny):

def norm(v):
    return 1+len([x for x in [11, 23, 52, 69, 118, 146] if v

my conclusion

Try to read your code as a story. It should have an introduction and then things should happen step-by-step. For deeper information try to learn more about clean code and check out clean code books on amazon.

  • Bio
  • Latest Posts
My Google+ profile

Christian Harms

I am working as a software developer and project manager in germany. After my graduate computer science I started in 2000 as a developer for a warehouse management system. my python knowledge grow up as a team member for one of the TOP3 german portal and freemail services. 2012 switched to the automotive industry to share my knowledge about open source and agile development. In spare time I submit to some coding contests and interesed in smaller developments.

Latest posts by Christian Harms (see all)

  • google code jam 2013 – tic-tac-toe-Tomek solution - April 16, 2013
  • Google code jam 2013 – the lawnmower - April 14, 2013
  • code puzzles and permutations - April 11, 2013
« Google Code Jam – Space Emergency
How many angry birds defeat how many pigs in google+? »

9 thoughts on “basic rules for code readability and the if statement”

  1. Anonymous says:
    August 1, 2011 at 15:46

    Your second version of isNameSet returns the reverse sense from the others.

  2. Keith Thompson says:
    August 1, 2011 at 15:49

    In the second version of your isNameSet() function, you reversed the sense of the test, so it returns true if the name *isn’t* set. You also replaced “===” by “==” (I don’t know JavaScript well enough to understand the implications of that). It should be something like:

        function isNameSet(name) {
          return name !== null && name !== ””;
        }
    

    (I’m assuming here that “!==” is the opposite of “===”, and that an empty name is considered “unset”.)

  3. Christian Harms says:
    August 1, 2011 at 15:49

    *ups* the was a missing ! in the function – thanx!!!

  4. Christian Harms says:
    August 1, 2011 at 16:04

    I should copy every version of the function into the article. Thanx – this is also correct.

  5. David Ellis says:
    August 1, 2011 at 16:23

    For both legibility and compactness of code in JS, I would write the last example as follows:

    function norm(v) {
        var out = null;
        [145, 117, 68, 51, 22, 10, -Infinity].forEach(function(val, ind) {
            if(!out && v > val) { out = ind+1; }
        });
        return out;
    }
    

    If the performance of this function was a problem, first change it to a standard for(var i = 0; …) loop with a break, then if still a problem, use its sorted nature to binary search the array, but those are both (in my eyes) less readable than the above code.

  6. Jens Finkhäuser says:
    August 1, 2011 at 16:33

    I think of readability as a highly contentious issue. While some constructs like your initial example of ( !notOk != false ) can easily be improved upon, others are more difficult to gauge.

    When I was still working for your company, I ran into the problem that someone really disliked that I often used: multiple return statements per function. To me, the following is very readable:

    function f(param)
    {
      if (null == param) {
        return;
      }
    
      if ("" == param) {
        return;
      }
      // Do something.
    }
    

    By contrast, this here requires more brainpower to understand (even more so if you don’t use a simplified example as I do):

    function f(param)
    {
      if (null != param && "" != param) {
        // Do something.
      }
      // Single point of return
    }
    

    There are reasonable reasons for either variant. The second version produces much fewer lines of code, which allows more of the context of whatever line of code has your attention to be on screen at the same time. The first version on the other hand makes the contract of the function abundantly clear.

    I still strongly favour the first variant; to me it’s a question of clarifying the code itself, rather than better fitting the code to whatever editor settings you prefer. YMMV.

  7. David Ellis says:
    August 1, 2011 at 18:10

    Actually, if this sort of pattern shows up often in the source, it would probably make sense to generalize it:

    function range(rangeArr, val, action) {
        //Assumes rangeArr is a sorted, least-to-greatest array
        //where a range is defined as rangeArr[n] < = x < rangeArr[n+1]
        for(var i = 1; i < rangeArr.length; i++) {
            if(val < rangeArr[i] && val >= rangeArr[i-1]) {
                break;
            }
        }
        return action(i);
    }
    

    Then norm can be defined as:

    function norm(v) {
        return range([-Infinity, 11, 23, 52, 69, 118, 146], v, function(i) { return i; });
    }
    

    This way the action to be taken can be changed as needed via the callback function (though in this case it aligns perfectly with the defined problem). I am assuming that you want as many ranges as are defined elements in the array. If that last implied range (146->Infinity) is not desired, the callback would have to throw an error for that value.

  8. Christian Harms says:
    August 1, 2011 at 18:47

    Hi Jens, we both know the pro and cons are long discussed and mostly the “single return” option can be found in some style guide. Thanx for the long comment – see some comments on stackoverflow.com .

  9. Nafees says:
    August 6, 2011 at 09:52

    I usually prefer single return and a template like below

    public Boolean isSomeTest(int toEvaluate) {
    	Boolean retValue = null;
    	if(/*some-condition*/) {
    		retValue=true;
    	} else {
    		retValue=false;
    	}
    	return retValue;
    }
    

    Makes it clear all along the procedure that this field “retValue” is going to capture the return value and then finally it will be returned.

Leave a comment Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tags

android code jam code puzzle hackercup hosting java javascript permutations project euler python server

Recent Comments

  • garcinia cambogia walmart on Free IP to Geo Location script
  • Yoda Conditions | Pack 6 – Palo Alto on What are yoda conditions?
  • Nico Heid on The art of escaping
  • hardik on Use Android ActivityGroup within TabHost to show different Activity
  • james on Use Android ActivityGroup within TabHost to show different Activity

Recent Posts

  • A scalable, affordable WordPress hosting, lessons learned
  • google code jam 2013 – tic-tac-toe-Tomek solution
  • Google code jam 2013 – the lawnmower
  • code puzzles and permutations
  • Code Jam – Candy Splitting

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

Copyright

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.
© united-coders
  • Some reader knows my preference for programming languages like python or javascript. One reason is the readability (yes, this is possible with many languages except brainfuck or whitespace). Onc