Improve_Understandability_by_Encapsulating_If_Else_Checks_in_Descriptive_Method_Calls

Quick Profile

Alex Ooi Profile Picture
Hometown: Melbourne, Australia
Specializations: Java, Ruby on Rails
University: Software Engineering & Economics, Melbourne University
High School: VCE, Melbourne High School
Links:
 

Popular Articles

Thursday, May 27, 2010

Often, IF checks result in rather hard to understand and unwieldy code. The logic for whether something is true or false can draw attention away from what the code is actually supposed to do. To help improve the understandability of your code, why not extract the "checking" code into its own method!

Before

This is a real example of some code I was working with today. It is clear that the understandability of the "if" condition could be improved.

     
           public void doSomething()
           {

                  // java code

                  if( (originalData != null && updatedData != null) 
                             && originalData.getManualDemand() != null 
                             && updatedData.getManualDemand() == null)
                  {
                        // java code
                  }
                  else if (originalData == null || hasChanged(originalData, updatedData))
                  {
                        // java code
                  }

                  // more java code!!!
           }

Essentially, it is checking if the original and updated data still exists, but that the value of the "Manual Demand" has been deleted. I had already done something similar with the "hasChanged" method (which was far more complex), so lets see what the code looks like when we refactor the "if" check....

After


           public void doSomething()
           {

                  // java code

                  if(hasManualDemandBeenDeleted(originalData, updatedData))
                  {
                        // java code
                  }
                  else if (isNew(originalData) || hasChanged(originalData, updatedData))
                  {
                        // java code
                  }

                  // more java code!!!
           }

           private boolean hasManualDemandBeenDeleted(Data originalData, Data updatedData)
           {
               return (originalData != null && updatedData != null) 
                                    && originalData.getManualDemand() != null 
                                    && updatedData.getManualDemand() == null;
           }

           private boolean isNew(ChargeableDemandData originalData)
           {
               return originalData == null;
           }

The "doSomething()" suddenly becomes much more readable! It is immediately obvious to someone reading "doSomething()" what might cause the code to run through either one of the conditions. And if they ever wanted to dig into the exact conditions which may cause "hasManualDemandBeenDeleted" to return true, then the code can be quickly found via the helpful lookups of any decent IDE ;)

Also, note that I extracted out the "originalData == null" check in the "else if" into its own method (isNew). This illustrates that no condition is too small to extract out into a method! If you think that introducing a descriptive method in place of an explicit condition will improve the understandability of your code, then do it! After all, most IDEs will have a helpful extract method refactor tool just a quick shortcut away (in IntelliJ it is ctrl-alt-m)....

Striving for Self Documenting Code?

Notice how neither method needs commenting because the names are descriptive enough? Also, notice how the IF and ELSE conditions proooobably don't need documentation relating to the conditions that would trigger them? Once again because the method calls in the if/else blocks are sufficiently descriptive ...

Understanding other developers code is usually not a trivial task. I'm far from perfect and I'll be the first to admit that the code I write can get pretty nasty sometimes. However, I do strive to improve the understandability of the code I am responsible for, firstly for the sake of those developers who will have to maintain the systems I work on, and secondly because I hope that they will do the same for me :) And although this technique is but a small step towards that ultimate goal, I do believe it is a worthwhile one for 2 simple reasons. Because it is soo easy to refactor code nowadays with the help of IDEs, and the readability improvements are clear for all to see.

Comments ...

You should not be checking for nulls.
Use a strategy pattern and utilize polymorphism instead of if else.
Posted by tester on Tuesday, May 25, 2010 at 07:07 PM
But surely, despite the best efforts of polymorphism, the if/else syntax is
still very valid. Especially when introducing a seperate class for each logical
path would be overkill. For example, when the code in the if/else block is just
a one liner ...
Posted by Alex Ooi on Tuesday, May 25, 2010 at 07:34 PM
Yes, if/else has its place. But you're just basically moving complexity around.

If you designed your app to have a concept of NULL objects strategy, then you
can remove the null if statements.

e.g.

function foo(a) {
if (a!=null) a.call();
}

can be changed to

function foo(a=A_NULL) {
a.call();
}

where A_NULL.call() does nothing.
Posted by tester on Tuesday, May 25, 2010 at 10:34 PM
The null object pattern could be applicable here if you're writing an app from
scratch... but if ur taking over an app which has over 10 years of work, then
its a little late to introduce that pattern ... or at least too time consuming
:(

but dude, i hear what ur saying ... AND I KNOW WHO U ARE!!! LOL ...
Posted by Alex Ooi on Tuesday, May 25, 2010 at 11:03 PM

Add a Comment

*
*
You must answer the following simple maths question before your comment will be accepted.
*