flow.
"Flow is a condition of deep, nearly meditative involvement." - Tom DeMarco

Three Easy Refactorings to Improve the Readability of Your Code

Monday, August 13, 2007 8:52 PM
One of the best things that you can do to give your code a long and happy life is to improve its readability.  Lucky for you, readability is one of the simplest things to improve.   There a tons a little tricks out there that can instantly make your code more maintainable, cleaner, and easier to read.  In fact, we discussed some of these today during a code review and I'd like to share just a few of them with you...

Update 08/20/2007:  I had so many great tips from the comments that, upon an excellent suggestion from mysterious "R", I decided to add them to the original post.  Here they are:
Courtesy of Thomas Eyde
Here's another one: Replace the not operator with false comparement:

if (!map.ContainsKey(key))

to

if (map.ContainsKey(key) == false)

I find that easier to both read and understand.

Courtesy of Ciz
if (!string.IsNullOrEmpty(name)) { ... }

do this:

bool nameIsValid = !string.IsNullOrEmpty(name);
if (nameIsValid) { ... }

Courtesy of Iv
án
Using comments for specifying the parameter name of a boolean value...
adapter.OpenConnection(@"C:\data\records.mdb", true /*useIntegratedSecurity*/, false /*useConnectionPool*/);

or

Console.Write(adapter.GetValue(0 /*CompanyName*/));

Courtesy of Klaus Hebsgaard
Instead of replacing numerical and boolean literals with named constants, try replacing them with enums since not only does this still provide readability but it also forces future developers to continue the standard

We now return you to your regularly scheduled blog posting.  Thanks for all of the great comments guys!


Replace boolean literals with named variables
Think back to the last time you saw one of those methods loaded down with boolean after boolean.  All of those values made perfect sense when you wrote the method...six weeks ago.  But, what about now?

adapter.OpenConnection(@"C:\data\records.mdb", true, false);


Do you remember what that 'true' represented?  What about the 'false'?  Is it still as clear as it was six weeks ago?  Probably not.  But what if you had used named variables in place of those literal booleans?

 

bool useIntegratedSecurity = true;

bool useConnectionPool = false;

adapter.OpenConnection(@"C:\data\records.mdb", useIntegratedSecurity, useConnectionPool);


Makes a little more sense now, doesn't It?  We can tell at a glance that the second parameter tells us that we're using integrated security for authentication.  And we can tell from a second glance that the third parameter tells us that we're not drawing from the pool for this connection.

Replace numerical literals with named constants
Ever seen one of those methods chock full of magic numbers that no one seems to know that they do but you?  Sure, we all have.  Here's a better one.  Ever seen one of those methods chock full of magic numbers that even you can't remember what they all do?  Once again...we all have.  In fact, here's one of those little gems right now...

 

Console.Write("Printing values...");

Console.Write(adapter.GetValue(0));

Console.Write(adapter.GetValue(1));

Console.Write(adapter.GetValue(2));

Console.Write(adapter.GetValue(3));

Console.Write("End values.");


So what's that first value that's being printed?  Hmm, ok how about the second?  Thought so.  The Third?  Fourth?  That's what I thought.  But, I'm sure you knew two weeks ago when you wrote it and that's all that matters...right?  Wrong.  Let's try to put some named values in there...

 

const int CompanyName = 0;

const int CustomerName = 1;

const int CustomerPhoneNumber = 2;

const int ProductName = 3;

 

Console.Write("Printing values...");

Console.Write(adapter.GetValue(CompanyName));

Console.Write(adapter.GetValue(CustomerName));

Console.Write(adapter.GetValue(CustomerPhoneNumber));

Console.Write(adapter.GetValue(ProductName));

Console.Write("End values.");


Now, what's that first value being printed?  What about the second?  Third?  Fourth?  It's a little bit easier this time around isn't it?

Replace indexers in nested for loops with meaningful variable names
i, j, and k.  Every coder's favorite name for loop variables.  Not that they're bad names, they're perfectly fine names.  In fact I may name my next trio of gold fish those very name.  But those are gold fish...not loop variables.  Let's take a look at the following code and see how little sense it makes...

 

for (int i = 0; i < 100; i++)

{

    for (int j = 0; j < 100; j++)

    {

        for (int k = 0; k < 100; k++)

        {

            alpha.Process(values[i][j][k]);

        }

    }

}


Three dimensions, three completely undescriptive variable names.  Does anyone want to take a guess at what these dimensions represent?  Didn't think so.  But how about after we add some better names for the index variables?

for (int rows = 0; rows < 100; rows++)

{

    for (int columns = 0; columns < 100; columns++)

    {

        for (int keys = 0; keys < 100; keys++)

        {

            alpha.Process(values[rows][columns][keys]);

        }

    }

}


 

What do you think now?  Can you guess what we're looking at here.  Do you have better ideas about what types of things we may be looking for?

These were three easy tricks that you can do to improve the overall readability of your code.  Keep in mind that although they technically are refactorings, they do little to change the overall structure of your code.  These are very low risk changes.  These are simply aesthetic changes but notice how much of a difference they make to the overall quality to your code.

Simple changes, big improvements.

kick it on DotNetKicks.com
Digg!

Feedback

# re: Three Easy Refactorings to Improve the Readability of Your Code

Which is why I always wished named variables took off in a mainstream language.

adapter.OpenConnection(@"C:\data\records.mdb", useIntegratedSecurity: true, useConnectionPool: false);

is even better.

Ruby fakes named variables by using hashes, but C#'s syntax is too verbose to get away with that unfortunately. 8/14/2007 10:46 AM | Matt

# re: Three Easy Refactorings to Improve the Readability of Your Code

For the first two examples I would recommend enums, since this forces future developers to keep the code readable.... 8/15/2007 2:50 AM | Klaus Hebsgaard

# re: Three Easy Refactorings to Improve the Readability of Your Code

Klaus,
That's a great idea! I didn't even think about enums so I'm really glad that you mentioned it.

Thanks for the thought!
Jeremy 8/15/2007 10:01 AM | Jeremy

# re: Three Easy Refactorings to Improve the Readability of Your Code

I'm guilty of the obscure booleans all too often. Thanks for the reminder not to do that. 8/15/2007 12:47 PM | Dave

 re: Three Easy Refactorings to Improve the Readability of Your Code

I prefer explicit, sometimes verbose, code so I agree with all three refactorings. However, I am curious of your stance on Hungarian notation. I am in the minority but I think Hungarian notation adds value to the code - just like explicit declarations of boolean parameters add value.

One of the primary knocks against Hungarian is that you can "hover" over the variable to determine its type (so you don't need an "s" in front of a string). The same is true for your first example, you can hover over "OpenConnection" to see the parameters.

I'm certainly not attempting to start a Hungarian vs. Non-hungarian debate, but I'm curious of your stance on the "hover debate".

Great post. 8/15/2007 4:45 PM | MattH

 re: Three Easy Refactorings to Improve the Readability of Your Code

You can use comments for that:

adapter.OpenConnection(@"C:\data\records.mdb", true /*useIntegratedSecurity*/, false /*useConnectionPool*/);

or

Console.Write(adapter.GetValue(0 /*CompanyName*/)); 8/15/2007 4:48 PM | Iván

# re: Three Easy Refactorings to Improve the Readability of Your Code

Hi MattH

I have to admit, I've always been a little torn on Hungarian notation as well. I was a pretty big fan of it back in my early days but I have to admit that I left it behind along with my C++ skills.

Here's my thoughts, I like nice clean code so I do like being able to drop the type prefix from the variable and just focus on the variable name itself. That said, however, I don't think that I buy that you don't need to specify the type because you can just hover over it in your editor. First, because not everyone uses an editor with that functionality and I think any decision regarding coding style should be made independent of the editor. I.e., my code should be just as easy to understand in Visual Studio as it is in Notepad. Secondly, I personally rarely mouse over my variables to determine the type since it requires me taking my hands off of the keyboard.

So...where does that leave our question about Hungarian Notation? While I am happy to leave behind the i's in front of my integers and the f's from my floats in favor of cleaner, more concise variable names, I don't necessarily believe that we've reached a point where we can depend on the editor to determine our types for us. So even though we're not at that point now, maybe we can reach that point some day or at least we know where we need to go to get there.

Food for thought...

Thanks for the comment, MattH

Jeremy 8/15/2007 10:24 PM | Jeremy

 re: Three Easy Refactorings to Improve the Readability of Your Code

Matt: a mainstream language like Visual Basic, for example? 8/16/2007 4:43 AM | Andrew

# re: Three Easy Refactorings to Improve the Readability of Your Code

Good sugegstions in this article. I wonder if FxCop already checks for "Replace boolean literals with named variables" but I am almost sure things like "const int ProductName = 3;" are considered "magic numbers" and should be substituted by, like Klaus Hebsgaard already pointed out, enums.
Anyways, good article, +1 kick. 8/16/2007 9:25 AM | tobsen

# re: Three Easy Refactorings to Improve the Readability of Your Code

Great tips Jeremy. I also like to explicitly define variables for things like validation, so instead of:

if (!string.IsNullOrEmpty(name)) { ... }

do this:

bool nameIsValid = !string.IsNullOrEmpty(name);
if (nameIsValid) { ... } 8/16/2007 10:32 PM | Ciz

# re: Three Easy Refactorings to Improve the Readability of Your Code

Ciz,

Great tip! I have to admit that I'm often guilty of collapsing several statements into one line though I must say that your example conveys the "name is valid" idea much clearer.

Thanks for the tip!
Jeremy 8/17/2007 11:17 PM | Jeremy

 re: Three Easy Refactorings to Improve the Readability of Your Code

Here's another one: Replace the not operator with false comparement:

if (!map.ContainsKey(key))

to

if (map.ContainsKey(key) == false)

I find that easier to both read and understand. 8/19/2007 12:32 PM | Thomas Eyde

 re: Three Easy Refactorings to Improve the Readability of Your Code

Jeremy, can you update note with tips from comments? 8/20/2007 6:28 AM | R

# re: Three Easy Refactorings to Improve the Readability of Your Code

Thomas,
That's a great idea. I never liked the !expression syntax and always resorted to using gratuitous parenthesis to separate the ! from the expression which I still never was crazy about. It never occurred to me to just explicitly use the false.

Great tip!
Jeremy 8/20/2007 9:51 PM | Jeremy

# re: Three Easy Refactorings to Improve the Readability of Your Code

R,
Great idea! I've updated the post to include all of the new tips at the beginning. Hopefully this will encourage even more people to add to it.

That's one of the great things about having a blog, it's amazing how many unexpected things that you learn from your readers!

Thanks for the idea!
Jeremy 8/20/2007 9:53 PM | Jeremy

# re: Three Easy Refactorings to Improve the Readability of Your Code

Sometimes its all about preference.

i.e I'll take this any day.

f (!string.IsNullOrEmpty(name)) { ... }

over this:

bool nameIsValid = !string.IsNullOrEmpty(name);
if (nameIsValid) { ... }

and thats because I'll only assign the result of that expression to a variable if I plan on using the variable more than once. Secondly, It looks neat with it as part of the if statement than a variable.

Comments within parameters - that's horrible to me, at the end of the day, your code will look more or less like a Christmas tree. 9/4/2007 2:43 PM | Andre

Post a comment





 

Please add 8 and 5 and type the answer here: