Refactoring: Replace Integer With Boolean

You have an integer variable holding one of two values used as a conditional flag.

Replace the integer with a boolean variable.

Motivation

The C language did not provide a true boolean type until C99[1], so integer variables containing 0 or 1 (or any non-zero value) are often used as a substitute. Programmers that have built habits from C compilers often use integer variables as boolean flags. In a language with true boolean types, such as C99, C++, C# and Java, a boolean type should be used along with the constants for true and false to more clearly convey the usage of the variable.

Mechanics

  1. Identify a variable being used in conditional statements as a boolean flag.
  2. Change the type of the variable from int to bool.
  3. Locate each location where the variable is assigned. Change the value of the expression to one of type bool.
  4. Locate each location where the variable is read and adjust the expression. If the variable is read in a boolean expression, change the expression as appropriate for the variable. If the variable is read in an integer expression, generate zero and non-zero values for false and true, respectively.

Example

FractInt is a C program whose first release was in 1988, well ahead of the bool support in C. FractInt has been converted to C++, which supports a true boolean type. We want to change the variables in FractInt that act like boolean values to true boolean types. Due to the procedural nature of the original FractInt code, many of these pseudo-boolean integer type variables exist.

1. Identify a variable being used as a pseudo-boolean.

Looking around for a likely candidate in the FractInt source[2], we find the variable use_list is a likely candidate in the function set_symmetry. Using the “Find in Files” feature of Visual Studio .NET 2005, we identify these lines of source code using this global variable:

Find all "use_list", Match case, Whole word, Subfolders, Keep modified files open, Find Results 2, "Current Project", "*.cpp;*.h"
calcfrac.cpp(3033):static void _fastcall set_symmetry(int symmetry, int use_list) /* set up proper symmetrical plot functions */
calcfrac.cpp(3157):		if (use_list == 0 && (!xaxis_between || (xaxis_row + 1)*2 != g_y_dots))
calcfrac.cpp(3180):		if (use_list == 0 && (!yaxis_between || (yaxis_col + 1)*2 != g_x_dots))
Matching lines: 3    Matching files: 1    Total files searched: 114

We can see that use_list is treated as a boolean value and passed into the function set_symmetry as a parameter. We can further look for invocations of the function set_symmetry to see how the value of the parameter is provided. Using Find in Files again and filtering the results to calls to set_symmetry, we get:

calcfrac.cpp(734):          set_symmetry(g_symmetry, 0);
calcfrac.cpp(1080):     set_symmetry(g_symmetry, 1);

The use_list argument is set as a simple constant value each time set_symmetry is called. We can now look at changing use_list‘s type from int to bool.

2. Change the type from int to bool.

Since use_list is a parameter to set_symmetry we change the declaration of set_symmetry from:

static void _fastcall set_symmetry(int symmetry, int use_list)

to:

static void _fastcall set_symmetry(int symmetry, bool use_list)

3. Locate each location where the variable is assigned and generate an expression of type bool.

In this case the value is being assigned to use_list when the function is being called. These lines:

calcfrac.cpp(734):          set_symmetry(g_symmetry, 0);
calcfrac.cpp(1080):     set_symmetry(g_symmetry, 1);

will be changed to:

calcfrac.cpp(734):          set_symmetry(g_symmetry, false);
calcfrac.cpp(1080):     set_symmetry(g_symmetry, true);

Everywhere the use_list value is assigned is now generating an expression of type bool.

4. Locate each location where the variable is read and adjust the expression.

In the case of use_list, the variable is only read in two places inside set_symmetry. In each case, the variable is read in the expression use_list == 0. We can replace this expression with the equivalent !use_list. These lines in set_symmetry change from:

calcfrac.cpp(3157):     if (use_list == 0 && (!xaxis_between || (xaxis_row + 1)*2 != g_y_dots))
calcfrac.cpp(3180):     if (use_list == 0 && (!yaxis_between || (yaxis_col + 1)*2 != g_x_dots))

to:

calcfrac.cpp(3157):     if (!use_list && (!xaxis_between || (xaxis_row + 1)*2 != g_y_dots))
calcfrac.cpp(3180):     if (!use_list && (!yaxis_between || (yaxis_col + 1)*2 != g_x_dots))

This completes the refactoring.


[1] C Programming Language (WikiPedia)

[2] FractInt SubVersion revision 1305

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: