he next version of C# will feature a code refactoring engine built into the Visual Studio environment. A term coined by Martin Fowler, code refactoring allows you to change the code structure without changing or affecting what the code itself actually does. For example, changing a variable name or packaging a few lines of code into a method are code refactoring. The main difference between C# 2.0 refactoring and a mere edit or find-and-replace is that you can harness the intelligence of the compiler to distinguish between code and comments, and so on. This article provides a preview of Visual C# 2.0 code refactoring by first discussing refactoring in general, then providing an overview of Visual C# 2.0 refactoring by walking though the various options and discussing their use and benefits.
Perhaps the single most important contributor to the long term maintainability of an application is how well laid-out and structured the code base is. Elements such as proper variable names, naming conventions, a consistent look and feel to statements, code format, and style enable readability by any developer, not just the one who wrote the code. Member variables encapsulation decouples clients from servers. Cohesive interface definitions enables interface reuse in other contexts. Allocation of interfaces to components is key to modular development and reuse. Eliminating blocks of repeated code by factoring it into a method increase quality because you only need to fix a defect in a single place.
As a result, once you've laid out the initial code structure, many developers spend a lot of effort manually polishing it, pruning and grooming variables, methods, and interfaces. This manual process, while essential, is somewhat error-prone because it allows for mistakes, and it does not automatically enforce any standard. Tool-based refactoring can automate much of the manual process, making developers more productive and the resulting code base of higher quality. Tool-based refactoring relies heavily on the complier and its ability to discern and keep track of various symbols in the code.
|Figure 1. The Refactor Pop-up Context Menu: Use this context menu to rename variables, parameters, methods, or types.|
Refactoring may or may not change the public interface of a typeit is at the discretion of the developer whether the changes made should be limited to the internals of a single component or it should trigger a massive update of all the clients as well. In its simplest form, refactoring can rename types, variables, methods, or parameters, extract a method out of a code section (and insert a method call instead), extract an interface out of a set of methods the type already implements, encapsulate type members in properties, automate many formatting tasks and auto-expand common statements. This is what Visual C# 2.0 reformatting supports, and it is the subject of this article. Note that in this upcoming version, reformatting changes are limited to an assembly, and do not propagate to client assemblies, even in the same solution. More advanced forms or refactoring are also possible. For example, a refactoring engine could analyze your code for similar code sections that could be factored into a separate method, perhaps with different parameter values. Refactoring could enforce compliance with a coding standard and propagate changes across a set of interacting assemblies. No doubt, future versions of Visual C# .NET and other enterprise development tools from Microsoft will provide these and other advanced features. But for now, here are the refactoring features of Visual C# 2.0.
|Figure 2. The Rename Dialog: This dialog lets you preview renaming changes before you apply them and set options for renaming the contents of comments and embedded strings.|
You can use refactoring to intelligently rename a variable, parameter, method, or a type. Intelligently means that the refactoring tool will distinguish between literal names and words in comments, and different versions of an overloaded method. That is, when renaming a method, you will get the option to change the name of that particular version of the method (in its definition and all its call sites), or all overloaded versions of that method. You can invoke refactoring in two ways: you can select Refactor from the top level Visual Studio .NET menu, or you can Select from the pop-up context menu. For example, to rename the type Form1 to ClientForm, right-click anywhere in your code where type Form1 is present (in its definition or places it is being used), and select Rename...
from the Refactor menu, as shown in Figure 1
This will bring up the Rename dialog box shown in Figure 2 where you can preview the changes (always a good idea), and instruct the refactoring tools to rename inside comments and strings as well.
|Figure 3. The Preview Changes Dialog: You can select which change to apply, and even refresh the dialog to pick up new occurrences.|
for the new form name and click OK. The Preview Changes dialog box shown in Figure 3
presents all the places in the assembly, across files, when the type Form1 is present. You can clear the checkbox before any occurrence where you do not want the renaming to take place. You can also double-click on each preview change to go to its code line. You can even keep the Preview Changes dialog box open, work on your code, and click the Refresh button (middle button in the dialog toolbar) to pick up the latest occurrences of the literal.
When you are satisfied with the list of changes, click the Start button to apply the rename. You can use refactoring to rename namespaces, types, variables, methods, properties, and parameters. Note that if you are used to naming the file after the type it contains (such as Form1.cs), after renaming a type you will need to manually rename the file as well.