Essential developer skills: Refactoring C# in Visual Studio 2010

By Andrew Stellman
August 8, 2010

I've been doing a little planning for my upcoming O'Reilly Book Club for Geeks C# event. We'll be focusing on C# because, obviously, the main topic of the event is the new edition of Head First C#. But one of the topics we're covering is becoming a better C# developer, and that's a topic I've put a lot of thought into over the years—especially when it comes to programmer career advice.

Head First C# Cover

If you've been reading my blog posts, you know that I try to help novice and intermediate C# programmers improve their skills, and help progress along the developer career path. I think this goes beyond simply getting better at programming C# and .NET. There are additional skills that, in my opinion, really make a difference in your ability to code. It's possible to become an advanced programmer without them, but it's a lot easier with them. Refactoring is one of those skills, and I think that any C# developer—even a novice one—can benefit from it. If you're a C# developer looking to take the next step on your career path and you don't refactor your code regularly, this is a great starting point to help move to the next level.

What is refactoring?

It's definitely best to start off with a definition, because a lot of developers aren't 100% sure of exactly what refactoring is. Even some advanced developers haven't really done it. Jennifer Greene and I wrote a whole section on refactoring in our first book. Here's a quick excerpt:

To refactor a program is to improve the design of that program without altering its behavior. There are many different kinds of improvements--called refactorings--that can be performed.

Every programmer knows that there are many ways to write code to implement one specific behavior. There are many choices that do not affect the behavior of the software but that can have an enormous impact on how easy the code is to read and understand. The programmers choose variable names, decide whether certain blocks of code should be pulled out into separate functions, choose among various different but syntactically equivalent statements, and make many other choices that can have a significant impact on how easy the software is to maintain.

You might think that it's a little weird that we thought it was useful to teach project managers about refactoring. In fact, I feel pretty strongly about that. I think it's such an enormously powerful technique that you should explicitly plan to do refactoring in any project. If you're working with a team, refactoring is a great way to run a more effective code review.

The best part about refactoring is that while there's a great deal of depth, it's actually really easy to get started. I'll walk you through a couple of really useful, basic refactorings now. Any C# developer—even a novice—can start using them today to build better software.

Extract a method

The Visual Studio 2010 IDE has some very useful refactoring tools built in. There are all sorts of refactorings you can do, but there are a few that we use quite often. In fact, they came in particularly handy when I was working on Head First C#.

When we were writing the control-based renderer for beehive simulator program in Chapter 13, we originally included this foreach loop:

foreach (Bee bee in world.Bees) 
{
     beeControl = GetBeeControl(bee);
     if (bee.InsideHive) {
          if (fieldForm.Controls.Contains(beeControl))
          {
               // These next four lines move a BeeControl from
               // the Field form to the Hive form
               fieldForm.Controls.Remove(beeControl); 
               beeControl.Size = new Size(40, 40); 
               hiveForm.Controls.Add(beeControl);
               beeControl.BringToFront();
          } 
      }
      else if (hiveForm.Controls.Contains(beeControl)) 
      {
          // These next four lines move a BeeControl from
          // the Hive form back to the Bee form
          hiveForm.Controls.Remove(beeControl); 
          beeControl.Size = new Size(20, 20); 
          fieldForm.Controls.Add(beeControl);
          beeControl.BringToFront(); 
     }
     beeControl.Location = bee.Location;
}

Lucky for us, one of our tech reviewers was Joseph Albahari. He's a great guy, a fantastic tech reviewer, and the author of C# 4.0 in a Nutshell, which is one of the best programming language books I've ever read. pointed out that this was a little hard to read. He suggested that we extract those two four-line blocks into methods. So we selected the first block, right-clicked on it, and selected "Refactor >> Extract Method...". This window popped up:

Screenshot - Extract Method.png

Take a close look at the screenshot, especially the new method declaration in the box. Notice how the IDE examined the code that we selected and figured out that it uses a BeeControl variable called beeControl, so it added it as a parameter to the method.

To finish the refactoring, I typed in a name for the new method. I decided to call it MoveBeeFromFieldToHive() because that pretty much describes what the code does.

Then I did the same thing for the other four-line block, extracting it into a method that we named MoveBeeFromHiveToField() . Here's how that foreach loop ended up--it's a lot easier to read:

foreach (Bee bee in world. Bees) {
      beeControl = GetBeeControl( bee) ;
         if (bee. InsideHive) 
         {
              if (fieldForm. Controls. Contains(beeControl) )
                  <strong>MoveBeeFromFieldToHive</strong>(beeControl) ;
         } else if ( hiveForm.Controls. Contains(beeControl) )
                 <strong>MoveBeeFromHiveToField</strong>( beeControl, bee) ;
         beeControl. Location = bee. Location;
}

Rename a variable

One of the things that we stress in Chapter 3 of Head First C# is that choosing intuitive names for your classes, methods, fields, and variables makes your code a lot easier to understand. (You can see this for yourself—the first three chapters of the book are in this free C# eBook download [PDF]!)

The Visual Studio IDE can really help you out when it comes to naming things in your code. Just right-click on any class, variable, field, property, namespace, constant--pretty much anything that you can name--and choose "Refactor >> Rename". You can also just use F2, which comes in handy because once you start renaming things, you find yourself doing it all the time.

I selected "beeControl" in the above code from the simulator and renamed it. Here's what popped up:

Screenshot - Rename variable.png

This New Name box lets you choose a new name for the item. If we renamed this, say, to "Bobbo", then the IDE would go through the code and change every single occurrence of it to "Bobbo".

The IDE does a really thorough job of renaming. If you rename a class, it'll change every statement that instantiates it or uses it. You can click on any occurrence of the name, anywhere in the code, and the IDE will make the change everywhere in your program. It even works on namespaces, which makes it easy to rename your namespace (which you often need to do if you're using a class from one project in another—but in that case, you might consider creating a .NET assembly with a class library).

Consolidate a conditional expression

Here's a neat way to use the "Extract Method" feature. Open up any program, add a button, and add this code to its event handler:

        private void button1_Click(obj ect sender, EventArgs e) {
             int value = 5;
             string text = "Hi there";
             if (value == 36 | | text. Contains("there") )
                 MessageBox. Show("Pow! ") ;
         }
}

Select everything inside the if statement: value == 36 | | text. Contains("there"). Then right-click on it and select "Refactor >> Extract Method...". Here's what pops up: Screenshot - Extract method 2.png

Every conditional expression evaluates to a bool, so the IDE will create a method that returns a bool and replace the conditional test with a call to that method. Plus, the IDE will even figure out that it should create a static method, since it doesn't use any fields.

Take a close look at the the declaration for method the IDE wants to extract:

private static bool NewMethod(int value, string text)

The expression uses two variables called value and text, so the IDE added parameters to the method using those names. Not only will this make the code easier to read, but now you've got a new method that you can reuse elsewhere!

So those are three really straightforward—but really powerful—refactoring tools built into the Visual Studio 2010 IDE. (They've actually been in there since 2008!)

If you want to learn more about refactoring, I very strongly recommend having a look at Martin Fowler's excellent refactoring.com. I first learned about refactoring from his book, Refactoring: Improving the Design of Existing Code (Fowler, Beck, Brant, Opdyke, Roberts; Addison-Wesley, 1999).

But if you really want to get good at it, the best thing you can do is start doing it in your own code!

Andrew Stellman is the author of Head First C# and other books from O'Reilly. You can read more from Andrew at Building Better Software.


You might also be interested in:

News Topics

Recommended for You

Got a Question?