fiGure 8-7
144 .
chaPter 8 code SnippeTS And reFAcToring
reviewing existing snippets
An excellent feature of the Snippet Editor is the view it offers of the structure of any snippet file in
the system. This means you can browse the default snippets installed with Visual Studio, which can
provide insight into how to better build your own snippets.
Browse to the snippet you’re interested in and double-click its entry to display it in the Editor
window. Figure 8-7 shows a simple snippet to Display a Windows Form. Four main panes contain
all the associated information about the snippet. From top to bottom, these panes are described
in Table 8-1.
InformationPanesforSnippets : table8 - 1
Pane function
Properties The main properties for the snippet, including title, shortcut, and description
Code Defines the code for the snippet, including all Literal and Object replacement
regions
References If your snippet will require assembly references, this tab enables you to define them
Imports Similar to the References tab, this tab enables you to define any Imports
statements that are required in order for your snippet to function correctly
Browsing through these tabs enables you to analyze an existing snippet for its properties and
replacement variables. In the example shown in Figure 8-7, there is a single replacement region with
an ID of formName and a default value of “ Form ” .
To demonstrate how the Snippet Editor makes creating your own snippets straightforward, follow
this next exercise, in which you create a snippet that creates three subroutines, including a helper
subroutine:
1 Start the Snippet Editor and create a new snippet. To do this, select a destination folder in
the tree, right-click, and select Add New Snippet from the context menu that is displayed.
2 When prompted, name the snippet “Create A Button Sample” and click OK. Double-click
the new entry to open it in the Editor pane.
Note that creating the snippet does not automatically open the new snippet in
the Editor — don’t overwrite the properties of another snippet by mistake!
3 The first thing you need to do is edit the Title, Description, and Shortcut fields (see
Figure 8 - 8):
Code snippets revealed .
145
.
Title: Create A Button Sample
.
Description: This snippet adds code to create a button control and hook an event
handler to it
.
Shortcut: CreateAButton
fiGure 8-8
4 Because this snippet contains member definitions, set the Type to “Member Declaration.”
5 In the Editor window, insert the code necessary to create the three subroutines:
Vb
Private Sub CreateButtonHelper
CreateAButton(controlName, controlText, Me)
End Sub
Private Sub CreateAButton(ByVal ButtonName As String, _
ByVal ButtonText As String, _
ByVal Owner As Form)
Dim MyButton As New Button
MyButton.Name = ButtonName
146
.
chaPter 8 code SnippeTS And reFAcToring
MyButton.Text = ButtonName
Owner.Controls.Add(MyButton)
MyButton.Top = 0
MyButton.Left = 0
MyButton.Text = ButtonText
MyButton.Visible = True
AddHandler MyButton.Click, AddressOf ButtonClickHandler
End Sub
Private Sub ButtonClickHandler(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
MessageBox.Show("The " & sender.Name & " button was clicked")
End Sub
c#
private void CreateButtonHelper()
{
CreateAButton(controlName, controlText, this);
}
private void CreateAButton(string ButtonName, string ButtonText,
Form Owner)
{
Button MyButton = new Button();
MyButton.Name = ButtonName;
MyButton.Text = ButtonName;
Owner.Controls.Add(MyButton);
MyButton.Top = 0;
MyButton.Left = 0;
MyButton.Text = ButtonText;
MyButton.Visible = true;
MyButton.Click += MyButton_Click;
}
private void MyButton_Click(object sender, EventArgs e)
{
MessageBox.Show("The " + sender.Name + " button was clicked");
}
6 .
You will notice that your code differs from that shown in Figure 8-8 in that the word
controlName does not appear highlighted. In Figure 8-8, this argument has been made a
replacement region. You can do this by selecting the entire word, right-clicking, and selecting
Add Replacement (or alternatively, clicking the Add button in the area below the code window).
7 .
Change the replacement properties like so:
.
ID: controlName
.
Defaults to: “MyButton”
.
Tooltip: The name of the button
accessing refactoring support .
147
8 Repeat this for controlText:
.
ID: controlText
.
Defaults to: “Click Me!”
.
Tooltip: The text property of the button
Your snippet is now done and ready to be used. You can use Visual Studio 2010 to insert the snippet
into a code window.
accessinG refactorinG suPPort
There are a number of ways to invoke the refactoring tools in Visual Studio 2010, including from the
right-click context menu, smart tags, and the Refactor menu in the main menu (for C# developers only).
Figure 8-9 shows the Refactor context menu available for C# developers. The full list of refactoring
actions available to C# developers within Visual Studio 2010 includes Rename, Extract Method,
Encapsulate Field, Extract Interface, Promote Local Variable to Parameter, Remove Parameters, and
Reorder Parameters. You can also use Generate Method Stub and Organize Usings, which can be
loosely classified as refactoring.
fiGure 8-9
The built-in refactoring support provided by Visual Studio 2010 for VB developers is limited to the
symbolic Rename and Generate Method Stub. Additional refactoring support for VB developers
is provided by CodeRush Xpress, which can be
accessed via the right-click context menu (which
dynamically changes so that only valid refactoring
actions are displayed), or via the smart tags
(as shown in Figure 8-10) that it displays
when a refactoring is available for the current
fiGure 8-10
selection (which can be clicked, or activated by
pressing Ctrl+`).
148 .
chaPter 8 code SnippeTS And reFAcToring
CodeRush Xpress adds support for all of the refactoring tools that C# has, and it adds many
more (to both languages). Examples of additional refactorings include Create Overload, Flatten
Conditional, Inline Temp, Introduce Constant, Introduce Local, Move Declaration Near Reference,
Move Initialization to Declaration, Remove Assignments to Parameters, Rename, Reorder
Parameters, Replace Temp with Query, Reverse Conditional, Safe Rename, Simplify Expression,
Split Initialization from Declaration, and Split Temporary Variable.
refactorinG actions
The following sections describe each of the refactoring options and provide examples of how to use
built-in support for both C# and CodeRush Xpress for VB.
extract Method
One of the best ways to start refactoring a long method is to break it up into several smaller methods.
The Extract Method refactoring action is invoked by selecting the region of code you want moved out
of the original method and selecting Extract Method from the context menu. In C#, this will prompt
you to enter a new method name, as shown
in Figure 8-11. If there are variables within
the block of code to be extracted that were
used earlier in the original method, they
automatically appear as variables in the method
signature. Once the name has been confirmed,
the new method is created immediately
after the original method. A call to the new
method replaces the extracted code block.
For example, in the following code snippet, if you wanted to extract the conditional logic into a
separate method, you would select the code, shown in bold, and choose Extract Method from the
right-click context menu:
c#
private void button1_Click(object sender, EventArgs e)
{
string connectionString = Properties.Settings.Default.ConnectionString;
if (connectionString == null)
{
connectionString = "DefaultConnectionString";
}
MessageBox.Show(connectionString);
/* ... Much longer method ... */
}
This would automatically generate the following code in its place:
c#
Private void button1_Click(object sender, EventArgs e)
{
fiGure 8-11
refactoring actions .
149
string connectionString = Properties.Settings.Default.ConnectionString;
connectionString = ValidateConnectionString(output);
MessageBox.Show(connectionString);
/* ... Much longer method ... */
}
private static string ValidateConnectionString(string connectionString)
{
if (connectionString == null)
{
connectionString = "DefaultConnectionString";
}
return connectionString;
}
CodeRush Xpress handles this refactoring action slightly differently for VB developers. After you
select the code you want to replace, CodeRush Xpress prompts you to select a place in your code
where you want to insert the new method. This can help developers organize their methods in
groups, either alphabetically or according to functionality.
Figure 8-12 illustrates the aid that appears which enables you to position where the method should
be inserted using the cursor keys.
fiGure 8-12
After selecting the insert location,
CodeRush Xpress inserts the new method,
giving it an arbitrary name. In doing so it
highlights the method name, enabling you
to rename the method either at the insert
location or where the method is called (see
Figure 8-13).
Using the Extract Method refactoring on the
following code:
Vb
Private Sub Button1_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
fiGure 8-13
150 .
chaPter 8 code SnippeTS And reFAcToring
Dim connectionString As String = My.MySettings.Default.ConnectionString
If connectionString Is Nothing Then
connectionString = "DefaultConnectionString"
End If
MessageBox.Show(connectionString)
'Much longer method
End Sub
And renaming the method to give it an appropriate name will result in the following code:
Vb
Private Sub Button1_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
Dim connectionString As String = My.MySettings.Default.ConnectionString
ValidateConnectionString(connectionString)
MessageBox.Show(connectionString)
'Much longer method
End Sub
Private Shared Sub ValidateConnectionString(ByRef connectionString As String)
If connectionString Is Nothing Then
connectionString = "DefaultConnectionString"
End If
End Sub
encapsulate field
Another common task when refactoring is to
encapsulate an existing class variable with a property.
This is what the Encapsulate Field refactoring action
does. To invoke this action, select the variable you
want to encapsulate and then choose the appropriate
refactoring action from the context menu. This gives
you the opportunity to name the property and elect
where to search for references to the variable, as
shown in Figure 8-14.
The next step after specifying the new property
name is to determine which references to the class
variable should be replaced with a reference to the new
property. Figure 8-15 shows the preview window that
is returned after the reference search has been completed. In the top pane is a tree indicating which
files and methods have references to the variable. The checkbox beside each row indicates whether
a replacement will be made. Selecting a row in the top pane brings that line of code into focus in
the lower pane. Once each of the references has been validated, the encapsulation can proceed. The
class variable is updated to be private, and the appropriate references are also updated.
The Encapsulate Field refactoring action using CodeRush Xpress works in a similar way, except
that it automatically assigns the name of the property based on the name of the class variable. The
interface for updating references is also different, as shown in Figure 8-16. Instead of a modal dialog,
fiGure 8-14
refactoring actions .
151
CodeRush Xpress presents a visual aid that can be used to navigate through the references (or you can
navigate between references using the Tab key). Where a replacement is required, click the check mark
or press Enter. Unlike the C# dialog box, in which the checkboxes can be checked and unchecked as
many times as needed, once you accept a replacement there is no way to undo this action.
fiGure 8-15 fiGure 8-16
extract interface
As a project goes from prototype or early-stage development to a full implementation or growth
phase, it’s often necessary to extract the core methods for a class into an interface to enable other
implementations or to define a boundary between
disjointed systems. In the past you could do this
by copying the entire method to a new file and
removing the method contents so you were just
left with the interface stub. The Extract Interface
refactoring action enables you to extract an
interface based on any number of methods within
a class. When this refactoring action is invoked
on a class, the dialog in Figure 8-17 is displayed,
which enables you to select which methods are
included in the interface. Once selected, those
methods are added to the new interface. The new
interface is also added to the original class.
In the following example, the first method needs
to be extracted into an interface:
c#
public class ConcreteClass
{
public void ShouldBeInInterface()
fiGure 8-17
152 .
chaPter 8 code SnippeTS And reFAcToring
{ /* ... */ }
public void AnotherNormalMethod(int ParameterA, int ParameterB)
{ /* ... */ }
public void NormalMethod()
{ /* ... */ }
}
Selecting Extract Interface from the right-click context menu and selecting only the