Over a million developers have joined DZone.

How to Write Easily Readable Code

Learn how to write easy to read code, and why the quality of your code improves with better readability. Implement these concepts and improve your code.

· Performance Zone

Evolve your approach to Application Performance Monitoring by adopting five best practices that are outlined and explored in this e-book, brought to you in partnership with BMC.

[This article was written by David Starr]

Since we read more code than we write, it makes sense to write code that is easy to read. But what makes code more readable seems a bit like asking “What makes one author more readable than another?”

There are some principles that developers tend to agree on – most notably how to express their intent in code. Ask a programmer to name some of them and you’ll likely hear something like this:

  • Well-named variables, methods, and class
  • Consistent formatting
  • Small methods
  • Minimal nesting and code branches

Let’s take some of those ideas and apply them in practice, starting with a functional, if confusing, bit of code and improving it.

Improving Your Code: Go Bowling

The game of bowling has a simple algorithm to calculate the score of a game, but I’ve noticed that most recreational bowlers don’t know how their game is actually scored. The base scoring is simple: You get one point for each pin knocked down. There are bonuses if you knock down all ten pins. If a bowler scores a strike (all 10 pins down on one roll), the score goes up by ten, plus adds the value of the next 2 rolls. If a bowler gets a spare (all ten pins down in 2 rolls), then the score increases by ten plus the value of the next roll.

The model below shows a bowling game and how it is scored. Strikes are shown as a X and spares are shown as a /.

Bowling

The downloadable zip file contains 2 working examples of solutions (before andafter) to Bob Martin’s bowling kata; if you haven’t heard of it, it’s a great exercise to study. The Game class is the subject of this article. The Game class’s Roll() method accepts the number of pins knocked down when a ball is rolled down the alley, and provides a GetScore() method to determine the bowler’s final score.

The C# code in the before folder of the downloadable code grew organically over a set of small but increasing requirements. I haven’t improved it at any step, so, sadly, the style is similar to production code I see all the time. If you aren’t familiar with how bowling is scored, see if you can figure it out by reading the in the algorithm in the code. Don’t worry if it gets too mind numbing to keep up with the array indexing, we’ll be fixing this implementation as we go to make the algorithm more obvious.

Now we’ll change (or refactor) this code into something more readable that will should make the algorithm for the game of bowling obvious, or at least discoverable, to any reader. First, notice the naming of variables. The class level variable _index could improve by being more obvious as to what it’s indexing. Renaming the variable gives us the following slightly more readable code.

int[] _rolls = new int[21];

int _rollIndex = 0;

internal void Roll(int i)

{

_rolls[_rollIndex++] = i;

}

The next thing that could stand some improvement is the name of the variable passed into the Roll method. What is this method expecting? Obviously an integer, but what does that integer represent?  Here’s what my IDE shows me when I look at that method from a caller point of view.

game1

Not the most intuitive method signature, is it? If I want to know what the “i” represents, I’ll probably need to go into that class and look at the details to glean the intent. The image below is what I see after renaming the variable to better match the intent of the Roll() method. That’s a more intuitive method signature. I can see that the parameter represents the number of pins knocked down on a single roll.

Game2

Now let’s focus on the variable names in the GetScore() method in the beforeexample, which is the heart of this class. Looking at the GetScore() method you can see that there are some variables with less than intuitive names. Here’s what the method looks like after renaming them for readability.

int rollIndex = 0;

int score = 0;

for (int frameIndex = 0; frameIndex < 10; frameIndex++)

{

. . .

}

That’s a little better. Now we can see the algorithm is walking though the _rolls array one frame at a time, and the rollIndex variable keeps track of the rolls within each frame. We can also tell at a glance the result we are calculating is actually the score, although that was generally implied by the GetScore() method name, it still adds a bit of clarity.

Going a step further, I will pull some of the conditional code to a method (called the “Exrtact Method Refactoring”). For example, I will change if (_rolls[rollIndex]==10) to be if (ThisFrameIsAStrike(rollIndex).  Now the code starts to read like simple conversational language. These changes slow the writer down a tiny bit, but speed up the reader a great deal — and we know that most maintenance is reading, not writing.

But what about the actual scoring? It still takes a bit of concentration to work our way through those array elements and understand what is happening. Let’s perform some more Extract Method refactoring to clean those up a bit. The resulting class has more code in it, because of the private clarification methods, but the logic of the core GetScore() algorithm is now easy to read. Check the aftersolution to see a final implementation of the Game.cs class.

for (int frameIndex = 0; frameIndex < 10; frameIndex++)

{

if (FrameIsStrike(rollIndex))

{

. . .

}

else if (FrameIsSpare(rollIndex))

{

. . .

}

else

{

. . .

}

}

Through some simple renaming and extracts to method we have greatly cleaned up this class to make it more readable. Note how the code reads almost as sentences.

Let’s talk through one more example before we call it a day.

Searching for Primes

Sometimes readability isn’t about renaming things, but instead about the structure of the code itself. This following code is a complete and working solution to thePrime Factors kata, which is another great learning tool to add to your toolbox.

The method GetPrimes() takes an integer and returns its prime factors. The variables are already well named and if you spend a moment reading the code you can likely grasp its intent.

public int[] Factor(int numToFactor)

{

var factors = new List<int>();

var possiblePrime = 2;



while (numToFactor > 1)

{

while (numToFactor%possiblePrime == 0)

{

factors.Add(possiblePrime);

numToFactor /= possiblePrime;

}

possiblePrime++;

}

return factors.ToArray();

}

While this is a complete and working solution to the Prime Factors kata, many kata practitioners factor this code to make it even shorter and terser. In fact, the primary logic can be expressed in 2 short lines of code.

public int[] Factor(int numToFactor)

{

var factors = new List<int>();



for (int candidate = 2; numToFactor > 1; candidate++)

for (; numToFactor % candidate == 0; numToFactor /= candidate)

factors.Add(candidate);





return factors.ToArray();

}

While the code is indeed shorter in this implementation, I find it harder to read. This implementation takes the standard structures of a for loop and uses them in ways that we aren’t used to seeing. The outer loop compares the numToFactor in the slot we usually expect to see the indexer compared. The inner loop looks a bit strange as it doesn’t even declare an indexer. This is perfectly allowable in C#, but isn’t a construct one sees often.

Take a moment to try and grok the 2 line solution. Did it take more or less time to read than the first solution that uses more lines of code? As a reader, I appreciate the more verbose solution with while loops.

A Programmer’s Responsibility

Making our code readable is tremendously important to the developer that inherits it, and reduces the overall cost of owning the code. Simple techniques like naming things well and extracting code into clarification methods is easy and can go a long way toward improving readability without much work on the developer’s part. Being clever with language capabilities or tight algorithms can be useful, and it arguably improves the developer’s geek status, but it can easily lead to less readable code.

The next time you are finished writing some gnarly code, do your teammates and favor and take a few moments – perhaps a minute per page of code – and apply some simple renames for ease of reading. You’ll save them time in maintenance, and, if your team does code reviews, you might save yourself some time answering questions!

Learn tips and best practices for optimizing your capacity management strategy with the Market Guide for Capacity Management, brought to you in partnership with BMC.

Topics:
code quality ,performance ,code ,monitoring ,bowling

Published at DZone with permission of Denis Goodwin, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}