Section 2.4. Use Refactoring to Speed Revision of Your Code


2.4. Use Refactoring to Speed Revision of Your Code

For most of us mortal programmers, the first version of complex code we create is not always the best it can be. As we code, we often decide to change the names of variables, factor out common routines into methods, and encapsulate member variables into properties. Some of these tasks can lead to difficulties: for example, changing the name of a variable can create subtle bugs if you forget to update references to the variable throughout the code.

Visual Studio 2005 offers a number of refactoring features that automate this process and ensure that the code is left in a consistent state.

2.4.1. How do I do that?

To learn more about the new refactoring features in Visual Studio 2005, first create a new Console application and name it SimplifyCoding. Replace the code provided by Visual Studio 2005 with the code shown in Example 2-1.

Example 2-1. Starting code for SimplifyCoding example
#region Using directives     using System; using System.Collections.Generic; using System.Text;     #endregion     namespace SimplifyCoding {        public class Dog    {       public int age;       public int weight;           public Dog(int age, int weight)       {          this.age = age;          this.weight = weight;       }           public void Method1( )       {          Console.WriteLine("This dog is overweight");       }           public void Method2(int x)       {          weight += x;          Console.WriteLine("This dog is overweight");       }              public override string ToString( )       {          return "I weigh " + weight + " and I'm " + age + " years old";       }            }        class Program    {           static void Main(string[  ] args)       {          Dog d = new Dog(5, 50);          Console.WriteLine(d);          d.weight = 70;          Console.WriteLine(d);          d.Method1( );          d.Method2(35);       }        } }


Warning: Before you run this program in the debugger, be sure to go to Tools Options, click Debugging/General, and check the box marked "Redirect all console output to the Quick Console Window." This will let you see the results of your Console application within the debugger.

This is a grossly exaggerated example of a very badly written program, but it serves to illustrate how the editor can help you improve your code. Reading through the code as written, it is hard to know what it is supposed to do because the variables and methods are poorly named. In addition, this code might be hard to maintain because some blocks of code are repeated in more than one place. This is always dangerous because it is easy to modify one block and neglect to update the other. In addition, this code exposes public member variables, a process that breaks down encapsulation and can cause maintenance headaches if you later change how you store the data held by those members (for example, if you later decide to store the dog's age and weight in a database, you'll break any class that interacts with these members of the Dog class).

We'll improve this code by renaming the variables and methods, by factoring out common code, and by encapsulating what are currently public member variables. All of these tasks are made much easier (and safer) by the new refactoring support offered in Visual Studio 2005.

Let's do this step by step.

2.4.1.1 Change a method name

Though the name doesn't tell you so, the job of Method1 is to see if the dog is overweight. Right now, that is stubbed out (it displays the message "This dog is overweight"). Begin by renaming Method1 to TestDogOverweight. As you type the new name, you'll see an orange bar under the name, as shown in Figure 2-13.

Figure 2-13. The bar that appears when you change an identifier


Click the bar and a smart tag appears offering to change the name of your method, as shown in Figure 2-14.

Figure 2-14. A smart tag for changing an identifier


Click Rename `Method1' to `TestDogOverweight' and you'll find that the name is changed in the method, as well as everywhere the method is called! Very nice. Add the following lines to TestDogOverweight:

Console.WriteLine("Need to walk the dog"); Console.WriteLine("Get Leash"); Console.WriteLine("Go for walk"); weight--;

2.4.1.2 Change a parameter name

Method2 and its parameter x would also benefit from a name change. Rename Method2 to FeedDog and rename x to howMuchFood. In each case a smart tag appears, and by using the smart tag to complete the renaming, the identifier is renamed throughout your code. Replace the Writeline statement in this method with a call to TestDogOverweight:

public void FeedDog(int howMuchFood) {    weight += howMuchFood;    TestDogOverweight( ); }

Add a new method, to awaken the dog in the morning:

public void AwakenDog( ) {    Console.WriteLine("WakeDogUp");    Console.WriteLine("Get Leash");    Console.WriteLine("Go for walk");    weight--; }

2.4.1.3 Factor out methods

Notice that the last three lines in this new method are identical to the last three lines in TestDogOverweight. Let's factor these lines out to a method. Highlight the three lines and right-click. Choose Refactor ExtractMethod. The ExtractMethod dialog appears. Name the new method WalkDog and press Enter. Hey! Presto! A new private helper method is created called WalkDog with the three lines of code, and in the place from which you extracted the method you find a call to your new method!

public void AwakenDog( ) {    Console.WriteLine("WakeDogUp");    Console.WriteLine("Need to walk the dog");    WalkDog( ); } private void WalkDog( ) {    Console.WriteLine("Get Leash");    Console.WriteLine("Go for walk");    weight--; }

Now you can go to your first method and make a call to WalkDog there, thus simplifying your code and ensuring maintainability.

2.4.1.4 Protect a field

Finally, notice that the Run method in Tester accesses the dog's weight directly:

d.weight = 70;

This works because weight is (improperly) declared to be a public member variable. We'd like to refactor all public member variables into properties. Highlight the definition of weight in the dog class and right-click. Choose Refactor Encapsulate Field. The Encapsulate Field dialog comes up and offers to name the property with a capital letter and to update references to the property, as shown in Figure 2-15.

Figure 2-15. Encapsulating a field


Notice that you have two choices for updating references. You can update only external references (references from methods outside of this class), or you can update all references. Choose External, click OK, and you can preview the changes that are about to take place. Click OK again, and the public variable is fully encapsulated as a property:

private int weight; public int Weight {    get    {       return weight;    }        set    {       weight = value;    } }

2.4.2. What about . . .

...if I want only a get method?

Although the property encapsulation creates a get and a set method, you can implement only a get method. It's just code in the editor. Once the code that implements the change is created, you are free to edit it in any way you want, including eliminating set accessors (though doing so might break your existing program if you accessed the variable from outside the class).

...what about other refactoring tasks that are available in the C# editor?

The C# editor offers quite a few tasks, including tasks for extracting an interface, promoting a local variable to a parameter, removing parameters, and reordering parameters.

...what about exploring further improvements to Visual Studio 2005?

One of my favorites is that now when you choose Find All References, you get a list of the references to the defined term. Then you can click each reference and go to the code where the item (for example, a method call) is defined, as shown in Figure 2-16.

Figure 2-16. Finding all references to a method


2.4.3. Where can I learn more?

A number of good refactoring books are available for creating well-designed object-oriented code, including Martin Fowler's seminal classic Refactoring (Addison-Wesley) and Joshua Kerievsky's Refactoring to Patterns (Addison-Wesley).



Visual C# 2005(c) A Developer's Notebook
Visual C# 2005: A Developers Notebook
ISBN: 059600799X
EAN: 2147483647
Year: 2006
Pages: 95
Authors: Jesse Liberty

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net