Working towards software quality

Software quality remains to be an illusive topic. It's hard to define, measure or enforce.

One way to to define software quality is how well functional and non functional requirements are met. This implies that requirements exists and are accurate. It also implies that the quality of the software changes whenever the requirements change! This is typically the type of software quality that will keep your manager and your client happy, for the time being...

For software that will be used and modified after the initial requirements have been satisfied (most software fall into this category), quality needs to be measured on a deeper level. Aspects like maintainability, changeability, testing, etc comes into play. This however remains hard to measure and enforce.

There are however certain things that contributes to software quality that aren't that hard to measure or implement. Here is a list with some of those things:
  • Requirements
  • Software design
  • Coding standards
  • Version control
  • Bug tracking
  • Source code documentation
  • Code reviews
  • Automated clean builds
  • Automated testing
  • Code analysis tools
  • Config management
  • User interaction

It may be worthwhile to elaborate on topics such as requirements, design and documentation. These are things that can cause considerable overhead when done incorrectly. It a good idea to approach requirements, designs and documentation as tools that are used to arrive at a certain point. As such they contribute to the quality of the software, but does not necessarily represents the system in its current state.

Having all of the above mentioned things in place will not equate to high quality software. It still remains something that needs to be propagated and pursued by all involved parties.

Deep indentation

Having many levels of indentation can seriously hamper readability (and thus the understandability) of code. These indentation levels are normally a result of nested conditional statements and try-catch blocks.

How many levels are too many?

Many people feel that 4 levels of indentation is the limit. This is not a hard rule, but serves as a good guideline.

Another guideline is that your source file should never contain a line of code that gets wrapped around or needs side scrolling. Unfortunately this is dependant on your screen resolution and font size. For some people the limit is at 80 characters (the Linux kernel uses this measure) other people feel that this measure is outdated and wastes screen real estate.

The basic idea is that whenever the amount of indentation levels make it difficult to understand the code, it's too many.

How do I fix it?

One way suggested in “Refactoring: Improving the Design of Existing Code” by Martin Fowler is replacing the conditional with Guard Clauses. Ex.
method body
if condition1 is true
if condition2 is true

else
can be replaced with
method body
if condition1 is false
return
if condition2 is true

else
Sometimes it is possible to rework the logic of the method. You may find that some conditionals are excessive or that it can be simplified further.

Many times though, this is an indication that other problems exist in your code. Things like methods that are too big, constant testing for null, using lots of “Type Codes”, implementing different states in one object, etc. In a lot of these cases, addressing the other problems will also fix the problem of multiple indentation levels.

Method stubs and Unused Code

A common thing we all do is creating stub methods on a class and implementing methods we do not immediately use. Both can lead to errors and incorrect results in parts of the code that use method stubs or (previously) unused code.

Method Stubs

Method stubs are functions that aren't implemented. The method body is normally empty, or returns a hard coded value in order to compile. Luckily they are easy to spot. There's nothing wrong in using method stubs when writing and testing the initial interface of a class, but no method stubs should be left hanging around in your code! If you do have method stubs, this can be corrected in one of two ways:

  1. Remove the method stub

  2. Implement the method stub

Most of the time you should remove it. You should only implement a method stub if it is actually used!

Unused Code

Another problem that is more difficult to spot is unused (and untested) code. If you are writing a library that are used by other people you cannot easily determine what methods are used and which ones are not. In this case your test cases should test all methods (actually all code paths).

The best way of avoiding unused methods, is to only create a method when you need it. This is stating the obvious, but we all tend to implement methods we don't use immediately (or ever). Lets look at an example:

A common class we all need and code at some stage is a Vector class. There are many well defined operations that can be performed on a vector, like calculating the length, converting it to a unit vector, addition, subtraction, dot product, cross product, etc. It is very easy to quickly go and define a vector and all the methods for working with it.

Chances are good that you do not immediately need all the methods that you thought up for you class and that that they will contain bugs. Once again, there are two ways of solving this:

  1. Use the method (in a test case)

  2. Remove the method

Option 1 should be executed if you still foresee that it is very likely that the method will be used in the near future or if the implementation entailed a large investment of effort. Most of the time you should strongly consider removing the method.

To sum it up: When writing code, be minimalistic, when using existing code, remove clutter.

Regards

Dirk

Code Smells

From Wikipedia: “In computer programming, code smell is any symptom in the source code of a program that possibly indicates a deeper problem.”

We all need to get things done and most of the time we need to do them in a hurry. Unfortunately the result is that our code are not always a clean as it should be. Fortunately we are not alone in this world and other people experience the same problems that we do.


Code Smells are one of those things that can help us to identify when we are doing things that may hurt ourselves in the future. We may not always be able to fix them, but whenever you encounter a Code Smell, see if you can either justify it or fix it.


Code Smells are not the problem themselves, but they indicate that other problems exist in the code. Solving them is important, but it is even more important to understand why they are bad.

Code Smell for the week: Huge methods/functions

Whenever a method becomes too big it gets hard to follow the logic of the method. Such a method should be broken down into smaller methods that groups together related functionality. If the refactored methods then contains unrelated functionality, consider moving them to separate classes.

When doing the refactoring of big methods, it is common to encounter problems like the constant use of a shared variable throughout the method. This is in its own a Code Smell and may be mentioned at a later stage.

When is a method TOO big?

The size of a method is not the only determining factor. Whenever your method performs more than one definable thing, it's probably too big.

Another telling factor is the levels of indentation within the method. If you start having more than 4 levels of indentation in one method, you have good reason to believe that the method is too big. In methods that are too big, it can become very hard to follow the indentation levels.

Some things to consider:

  1. Don't overdo it. Functions that are too small can hamper the readability of the code.
  2. Don't expose functions to the global name space unless needed.

Please discuss Code Smells amongst each other. It is often more important to know why code smells are bad rather than knowing how to fix them. Knowing why they are bad will most likely result in us producing less Code Smells.

From the attic

Most programmers have a stash of old software projects somewhere. I decided to go and dig up those projects I have and commit them on github. They can all be found

Minesweeper (c++)
I wrote Minesweeper because of my ego back in 2002. A friend of mine was going on about how difficult it is to implement minesweeper, so I decided to see how difficult it could really be. It can now be found here. Here is a screenshot of what it looks like:



Tetris (c++)
This is another classic. Every aspiring game programmer (overeager teenager) have probably written a clone of Tetris. This was my attempt, it's called Blockys Bow, can't remember why I called it that? You can find the source here




Connect More than Three (java)
I enjoyed playing the plastic version of this game, so I decided that that's enough reason to create an intangible one. This was done in Java, some of my first code therein.



Snake (java)
Last and probably least as well. At some time in my life I was clearly bored, didn't have many friends or more disturbingly found it interesting enough, who knows? Point being, I implemented a snake like game in java. As you can see from the screen shot below, everything didn't work like is should. Enjoy the source if you want.



Well, that's all for today. If I receive any motivation (in the form of comments or your projects on github) I'll dig up that stash of pascal code thats lying around somewhere.