As an introduction to this concept, let's consider the following code:
String[] array = {Joe, Sam, Dave, Charley};
int end = array.length;
for (int i = 0, i < end; i++)
{
array[i] = "Mr. " + array[i];
}
From reading this code, we come to the understanding that an array of String objects are each concatenated with the String "Mr. ". Although that is fairly clear, our variable names do not help a programmer understand the object's purpose (i.e. "array", although good at describing that the object is an array, does not do very well to expound on the fact that this is an array of String objects, much less that the String objects are all names of (presumably) men. We therefore have a good opportunity to refactor this code in order to rename more sensical variables.
From Udacity's course, there are a couple of approaches to refactoring variable names.
- Create test cases with expected results prior to refactoring code
- Fully implement refactored variable names BEFORE removing any current code
Creating test cases for the above code is fairly simple:
for (String name : array)
{
System.out.print(name + ", ");
}
println();
System.out.println("Expected result: Mr. Joe, Mr. Sam, Mr. Dave, Mr. Charley");
The above code will suffice in printing the contents of array after the for loop completes execution. Now we are ready to refactor the code.
Per the above example, we would like to rename "array" to a more appropriate name that will denote that the contents of the variable. Therefore, instead of
String[] array = {Joe, Sam, Dave, Charley);
the more descriptive
String[] arrayOfMaleNames = {Joe, Sam, Dave, Charley);
will be more readable for future programmers who come upon this code. Before removing the old representation of array, per Udacity's approach and method, we should find all representations of array throughout the current code prior to removing. Therefore, we get
String[] array = {Joe, Sam, Dave, Charley};
String[] arrayOfMaleNames = {Joe, Sam, Dave, Charley};
int end = array.length;
int end = arrayOfMaleNames.length;
for (int i = 0, i < end; i++)
{
array[i] = "Mr. " + array[i];
arrayOfMaleNames[i] = "Mr. " + arrayOfMaleNames[i];
}
This modification must also be made to our tester
for (String name : array)
for (String name : arrayOfMaleNames)
{
System.out.print(name + ", ");
}
println();
System.out.println("Expected result: Mr. Joe, Mr. Sam, Mr. Dave, Mr. Charley");
Now that the modification has is ubiquitous, we are ready to remove all instances of array, yielding:
//Main code
String[] arrayOfMaleNames = {Joe, Sam, Dave, Charley};
int end = arrayOfMaleNames.length;
for (int i = 0, i < end; i++)
{
arrayOfMaleNames[i] = "Mr. " + arrayOfMaleNames[i];
}
//tester
for (String name : arrayOfMaleNames)
{
System.out.print(name + ", ");
}
println();
System.out.println("Expected result: Mr. Joe, Mr. Sam, Mr. Dave, Mr. Charley");
Next, we will modify the for loop. Because all indexes in the array will be accessed, there is no use in creating a separate index to go through all of the array values. This would be a different case if the array had been instantiated with, say, 100 indexes of which only the first 4 were utilized. Instead, since the array is fully implemented with the four strings "Joe, Sam, Dave, Charley" for the array's four indexes, we are ok implementing the for loop as follows:
int end = arrayOfMaleNames.length;
for (int i = 0, i < end; i++)
{
arrayOfMaleNames[i] = "Mr. " + arrayOfMaleNames[i];
}
for (String name : arrayOfMaleNames)
{
name = "Mr. " + name;
}
After writing the refactored for loop we are ready to remove the old code, yielding:
//Main code
String[] arrayOfMaleNames = {Joe, Sam, Dave, Charley};
for (String name : arrayOfMaleNames)
{
name = "Mr. " + name;
}
//tester
for (String name : arrayOfMaleNames)
{
System.out.print(name + ", ");
}
println();
System.out.println("Expected result: Mr. Joe, Mr. Sam, Mr. Dave, Mr. Charley");
Finally, we still have a 'magic' String "Mr. " to deal with. This is considered a 'magic' String, or object in general, because there is no precedence for why this particular String was chosen, and if it exists in several places throughout the code, it could be very tedious to replace (what if instead of "Mr. " we wanted to implement "Dr. " for example?). It is better to declare this value in a separate variable, then replace the 'magic' String with that variable. After writing our refactored code:
String[] arrayOfMaleNames = {Joe, Sam, Dave, Charley};
String abbreviation = "Mr. ";
for (String name : arrayOfMaleNames)
{
name = "Mr. " + name;
name = abbreviation + name;
}
Removing the old code yields:
//Main code
String[] arrayOfMaleNames = {Joe, Sam, Dave, Charley};
String abbreviation = "Mr. ";
for (String name : arrayOfMaleNames)
{
name = abbreviation + name;
}
//tester
for (String name : arrayOfMaleNames)
{
System.out.print(name + ", ");
}
println();
System.out.println("Expected result: Mr. Joe, Mr. Sam, Mr. Dave, Mr. Charley");
After comparing the test result prior to refactoring to the result after refactoring, we see that the results are the same, and our refactoring is complete (for now)!
No comments:
Post a Comment