Ever since Visual Basic developers heard about C# refactoring--a set of features that help developers restructure code--they've been green with envy. Surely it makes just as much sense to give VB'ers a similar set of refactoring tools for managing and modifying their code.
Although VB 2005 refactoring was a top developer request, the VB team had no way to fit in such a significant change late in the beta cycle. (Instead, they're hard at work putting the finishing touches on edit-and-continue and a library of more than 500 code snippets.) However, they came up with an innovative solution that might be just as good--partnering up with another company to include support for basic refactoring. Today, you can download a free version of Refactor, the Developer Express refactoring software. By the final release of .NET 2.0, Refactor will be included with Visual Studio, and you'll be able to buy a more configurable and extensible version of the same tool from www.devexpress.com.
Refactoring is the one-size-fits-all name given to a set of coding shortcuts that help you rework code on the fly. The distinguishing characteristic of refactoring is that it's intelligent. For example, you're already familiar with basic IDE features like cut and paste or search and replace. The refactoring versions of these features understand VB syntax. That means they can dynamically tailor other portions of your code to keep it synced up and simplify your work.
The best way to learn to work with refactoring is to try it out. So download the free Visual Basic 2005 refactoring tool, and then experiment with some of the techniques in the following sections.
|
Related Reading Visual Basic 2005: A Developer's Notebook |
This refactoring trick is a great way to tame large blocks of code by splitting a portion off into a separate method. It's also one of the easiest refactoring tools to get under your belt.
Imagine you start with the following console application:
Module InvestmentCalculator
Sub Main()
Dim InterestRate, Years, FinalValue, MonthlyPayment As Double
Console.Write("Interest Rate: ")
InterestRate = Val(Console.ReadLine())
Console.Write("Years: ")
Years = Val(Console.ReadLine())
Console.Write("Final Value: ")
FinalValue = Val(Console.ReadLine())
MonthlyPayment = Pmt(InterestRate / 12 / 100, _
Months, 0, -FinalValue, _
DueDate.BegOfPeriod)
Console.WriteLine("Result: " & MonthlyPayment.ToString("C"))
End Sub
End Module
The code here is quite straightforward. It asks the user to enter three pieces of
information (an interest rate, number of years, and final value) and calculates the final value with
compounded interest using the Pmt() function. The problem is that the calculation code is
intermingled with the code for getting the user input and displaying the result. Although it's still manageable in this example, it's not hard to imagine a much more complicated
set of calculations that would introduce some real organizational headaches. To start
simplifying this code, you can use refactoring.
Once you've installed Refactor, you have three ways to trigger it. First, position your
code to a place where refactoring is available. This part takes a little getting used to, but
as you play with the tool you'll start to learn where the refactoring points are in your code
(for example, in a variable declaration, a method declaration, and so on). When your code
is in the right place, you'll see a small smart tag marker appear. In this case, start by
selecting the content of the Main() method.
Now, simply click on this marker to pop open a menu with your current refactoring choices (see Figure 1). Alternatively, you can press Ctrl-tilde (~), or right-click on the program element and look for the Refactor submenu.

Figure 1. The refactoring tag
If you don't see the refactoring marker when you expect to, the problem could be an error in your code, as the refactoring smart tags won't appear if there's an active IntelliSense tag flagging an error.
|
In this example, choose Extract Method from the refactoring smart tag. A red arrow will appear in the editor window, which you can move using the up and down arrow keys (Figure 2). Once you've found the place where you want to create the new method, press the Enter key.

Figure 2. Positioning the new method
The refactoring tool will create a new method and replace the code in Main() with the method call. The name of the method is generated automatically based on the containing
method, with the word Extracted added to the end. So in this example, refactoring
creates a method named MainExtracted(). However, the name is highlighted in green, and you can change it by typing in a more suitable choice. As you type, both the method
name and the method call will be adjusted (Figure 3).

Figure 3. Naming the new method
Once you're finished, you'll end up with this unspectacular result:
Private Sub CalculateInterest()
Dim InterestRate, Years, FinalValue, MonthlyPayment As Double
Console.Write("Interest Rate: ")
InterestRate = Val(Console.ReadLine())
Console.Write("Years: ")
Years = Val(Console.ReadLine())
Console.Write("Final Value: ")
FinalValue = Val(Console.ReadLine())
Dim Months = Years * 12
MonthlyPayment = Pmt(InterestRate / 12 / 100, _
Months, 0, -FinalValue, _
DueDate.BegOfPeriod)
Console.WriteLine("Result: " & MonthlyPayment.ToString("C"))
End Sub
Sub Main()
CalculateInterest()
End Sub
This gives you the starting point for rearranging your code, but it doesn't offer much more. The input code and the calculation code is still thrown unceremoniously together in the same method.
But now that you understand the basic technique, you can also do something much more useful. To try this out, undo your changes so that you return to the initial code version. Then select just the calculation code, which in this case constitutes the following lines:
Dim Months = Years * 12
MonthlyPayment = Pmt(InterestRate / 12 / 100, _
Months, 0, -FinalValue, _
DueDate.BegOfPeriod)
Extract this method. Now the refactoring tool gets much more intelligent. It notices that
the values you're using--InterestRate and Years--are defined elsewhere in the method and thus need to be supplied to the method. It also spots the fact that the MonthlyPayment
result is displayed afterward, and so must be a return value. The resulting code is much
closer to what you want:
Sub Main()
Dim InterestRate, Years, FinalValue, MonthlyPayment As Double
Console.Write("Interest Rate: ")
InterestRate = Val(Console.ReadLine())
Console.Write("Years: ")
Years = Val(Console.ReadLine())
Console.Write("Final Value: ")
FinalValue = Val(Console.ReadLine())
MonthlyPayment = GetMonthlyPayment(InterestRate, Years, FinalValue)
Console.WriteLine("Result: " & MonthlyPayment.ToString("C"))
End Sub
Private Function GetMonthlyPayment(ByVal InterestRate As Double, _
ByVal Years As Double, ByVal FinalValue As Double) As Double
Dim MonthlyPayment As Double
MonthlyPayment = Pmt(InterestRate / 12 / 100, _
Months, 0, -FinalValue, _
DueDate.BegOfPeriod)
Return MonthlyPayment
End Function
In this example, you don't even need to rename the extracted method. The refactoring
tool realizes you're returning a value that you've named MonthlyPayment, and defaults
to the sensible method name GetMonthlyPayment().
|
At this point, you might decide that you have a near-perfect method declaration, but you want to change the order of the parameters. To accomplish this, move to one of the variables in the function declaration:
Private Function GetMonthlyPayment(ByVal InterestRate As Double, _
ByVal Years As Double, ByVal FinalValue As Double) As Double
When you select the refactoring tag, you'll see the option for reordering the parameters. Choose this. You'll now be able to slide variables from one place to another using the left and right arrow keys. When you've rearranged them the right way, press Enter. Here's one possibility:
Private Function GetMonthlyPayment(ByVal Years As Double, _
ByVal FinalValue As Double, ByVal InterestRate As Double) As Double
The refactoring tool will show you all the places in the code where you call this method, and you can choose to change them individually (click on the checkmark icon) or all at once (click on the double checkmark icon). Without this tool, you'd be exposed to the possibility of error. Because all the variables are the same type, you might inadvertently keep a piece of code that calls the method but has these values in the wrong order.
The last trick I'll cover allows you to make your code more explicit by breaking
down log lines of code. Currently, the Pmt() function performs an inline interest rate
calculation.
MonthlyPayment = Pmt(InterestRate / 12 / 100, _
Months, 0, -FinalValue, _
DueDate.BegOfPeriod)
It might clarify your code to expand that with a separate variable. (And even if it doesn't, keep in mind that these tools are great for examples where your code is that much more complex--we've all seen hideously tangled lines of code that do too much at once.)
To refactor this code, move to the interest rate calculation and choose the refactoring
option Introduce Local. You'll be prompted to name a new local variable, and will end up
with this code:
Dim MonthlyInterestPercent As Integer = InterestRate / 12 / 100
MonthlyPayment = Pmt(MonthlyInterestPercent, _
Months, 0, -FinalValue, DueDate.BegOfPeriod)
You can use a similar technique to replace hardcoded values with constants.
To learn more about refactoring, surf over to www.devexpress.com/Support/BestPractices/IDE/Refactor, which has an exhaustive list of refactoring features. Or, better yet, download the Refactor 2005 tool and start experimenting.
In April 2005, O'Reilly Media, Inc., released Visual Basic 2005: A Developer's Notebook.
Sample Chapter 2: The Visual Basic Language (PDF) is available free online.
You can also look at the Table of Contents, the Index, and the full description of the book.
For more information, or to order the book, click here.
Matthew MacDonald is a developer, author, and educator in all things Visual Basic and .NET. He's worked with Visual Basic and ASP since their initial versions, and written over a dozen books on the subject, including The Book of VB .NET (No Starch Press) and Visual Basic 2005: A Developer's Notebook (O'Reilly). His web site is http://www.prosetech.com/.
Return to the Windows DevCenter.
Copyright © 2009 O'Reilly Media, Inc.