DotNetCurry Logo

Code Refactoring (Software Gardening - Pruning)

Posted by: Craig Berntson , on 3/22/2015, in Category Software Gardening
Views: 55909
Abstract: Code refactoring isn’t code rewriting. Refactoring is the process of restructuring existing computer code without changing its external behaviour. This Software Gardening article talks about what is refactoring, why to refactor your code and the built-in refactorings in Visual Studio.

Comparing software development to constructing a building says that software is solid and difficult to change. Instead, we should compare software development to gardening as a garden changes all the time. Software Gardening embraces practices and tools that help you create the best possible garden for your software, allowing it to grow and change with less effort. Learn more in What is Software Gardening.

Comparing Code Refactoring to Pruning

Imagine that you have a beautiful rose garden. It takes many hours of work to keep it beautiful and the roses healthy.

Did you know, a key aspect of growing roses is pruning.

That is, you need to cut out the dead and dying flowers so that the young, healthy buds can thrive. Pruning roses also gives them a more attractive shape.

But pruning can also be applied elsewhere.

For example, in the timber industry, where entire mountainsides of forest need to be kept healthy, different types of pruning are used.

The first of these is selective cutting, where specific types of trees are identified and only those are cut. Then there is thinning, where large trees are cut out of thick heavy forests, so the small trees that are struggling can grow and be healthy. Finally, there is clear-cutting, which is used to completely clear a side of a mountain of all trees.

Certain types of trees will not survive if selective cutting or thinning is used, so clear-cutting is the only alternative.

Also, if a forest is attacked by disease or insects, clear-cutting may be used to remove a section of forest in an effort to save the entire forest.

In all cases, the timber company replants trees so that new growth will keep the forest healthy. In all cases, the forest is still a forest.

Pruning has not changed the functionality of what nature gave.

This article is published from the DotNetCurry .NET Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months. Subscribe to this eMagazine for Free and get access to hundreds of free .NET tutorials from experts

Do you prune your software?

Just like the roses or the forest, pruning is necessary to keep software healthy.

As software gardeners, our term for pruning is refactoring.

The first important thing you need to know about refactoring is that it isn’t rewriting.

Refactoring is defined as “the process of restructuring existing computer code – changing the factoring – without changing its external behavior”. Source

Let’s think back to a past column I wrote about unit testing.

The process of unit testing is shown in Figure 1. You can see that refactoring is a key part of unit testing. And, not surprisingly, unit testing is a key part of refactoring. After all, how do you know if you haven’t changed the external behavior of the piece of code, without testing?

refactoring

Figure 1: The unit testing process includes refactoring

Code Smells

The most famous book on refactoring was written by Martin Fowler. Its title is “Refactoring: Improving the Design of Existing Code”.

The book is a catalog of refactorings and includes a chapter called “Bad Smells in Code” that discusses ways to identify and fix problematic code that could be a good candidate for refactoring. The smells include duplicated code, long methods, large classes, and long parameter list. (I once had to update code written by someone else and found a class with a constructor that had 144! parameters). There are nearly 20 more code smells listed.

In addition to describing code smells and cataloging refactoring patterns, the book gives reasons to refactor: improve the design of software, make software easier to understand, help you find bugs, and help you to program faster.

This last one seems contradictory. How can you program faster if you have to refactor the code? The answer is that refactoring makes it easier to read the existing code.

Martin Fowler also lists what he calls, “The Rule of Three”, which are three rules for when to refactor. First, you should refactor when you add function. Second, refactor when you need to fix a bug. And third, refactor as you do a code review.

Once you’ve identified the specific code smell, the book points you to refactorings that can be used to fix it. You can fix the code with copy and paste. But there is a better way. Visual Studio has some built-in refactoring tools that are easier to use than copy and paste.

Code Refactoring in Visual Studio

Hover over a variable in the Visual Studio editor (for this column, I used the free Visual Studio 2013 Community Edition, which is functionally equivalent to VS 2013 Professional), then right-click and select Refactor. You’ll see that six refactorings are available. You will also notice that each refactoring has a keyboard shortcut that begins with Ctrl+R.

vs-refactoring-menu

Figure 2: The Visual Studio refactoring menu

In the rest of this column, I will take you through each of these refactorings.

Refactoring: Rename

The late computer scientist Phil Karlton said, “There are only two hard things in Computer Science: cache invalidation and naming things.” (A variation says “There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.”).

How often have you named a class, variable, or other object and after sometime realized that the name you chose turns out to be wrong? How often have you needed to name something and wasted time trying to come up with just the right name for it before even typing it into your editor?

Often times the correct name comes to you only after you’ve seen how it will be used in the code. This is where Rename Refactoring comes into play.

Martin Fowler describes Rename Method, “An important part of the code style I am advocating is small methods to factor complex processes. Done badly, this can lead you on a merry dance to find out what all the little methods do. The key to avoiding this merry dance is naming the methods…Remember you code for a human first and a computer second” (Refactoring, p. 273)

In Visual Studio, the Rename Refactoring works on more than just a method. It can be used on variables, classes, even namespaces. Place the cursor on the object to be renamed and press Ctrl+R,Ctrl+R (think of this as Refactor, Rename). The Rename dialog appears.

rename-refactoring

Figure 3. Caption: The rename dialog is used for the rename refactoring.

Enter the new name and select the options you want, then select OK.

If you checked Preview reference changes, you will get an additional dialog showing you where each refactoring takes place and what the changes will look like. You can then unselect the places you don’t want the refactoring to occur.

preview-changes

Figure 4: The Preview Changes dialog

Click Apply in the Preview Changes dialog and the refactorings will be made.

Refactoring: Extract Method

One of the rules for good methods is that a method should do only one thing. Also, a good method will be short and not require you to scroll though lots of code. This next refactoring, Extract Method helps you fix these issues by removing code and putting it in its own method. You can also use this refactoring to simplify code.

From Martin Fowler: “Extract Method is one of the most common refactorings I do. I look at a method that is too long or look at code that needs a comment to understand its purpose. I then turn that fragment of code into its own method.” (Refactoring, p. 110)

To use this refactoring, highlight the code to extract, then press Ctrl+R,Ctrl+M (Refactor, Method). Here’s some real code from one of my projects.

if (viewModel.NewEmailParentTable.ToLower() == "company" && viewModel.NewEmailIsDefault)
{
    var companyEmailAddresses = _context.CompanyEmailAddresses.Include("EmailAddress");
    if (companyEmailAddresses.Any())
    {
        var currentDefault =
            companyEmailAddresses.FirstOrDefault(e => e.EmailAddress.IsDefault).EmailAddress;
        if (currentDefault.Id != viewModel.NewEmailAddressId)
        {
            currentDefault.IsDefault = false;
            _context.EmailAddresses.Attach(currentDefault);
            _context.Entry(currentDefault).State = EntityState.Modified;
            _context.SaveChanges();
        }
    }
}

After I wrote the code and it passed unit tests, I went back to refactor. The original method was about three screens long. This piece of code has a smell in that it has several nested if statements. I highlighted the entire code section and pressed Ctrl+R,Ctrl+M. The Extract Method dialog was displayed.

extract-method

Figure 5: The Extract Method dialog

Notice how the refactoring tools figured out what parameters the method needed and set those up automatically. I entered the name for the new method and clicked OK. Visual Studio did all the work of creating the method in my class and replacing the selected code with a single line of code. I then refactored the nested if statements.

Later on, I decided my original name wasn’t quite right and used the Rename refactoring to change the name of the method. In the end, the code is easier to read and maintain.

Refactoring: Encapsulate Field

The next refactoring, Encapsulate Field, turns a field into a property. Look at this code:

public class Line
{
    public int length, width;
}

public class MyLine
{
    public static void Main()
    {
        Line line = new Line();
        line.length = 12;
        line.width = 1;

        // Some code to draw the line on the screen
    }
}

Length and width are technically fields, not properties because they don’t have getters or setters.

Let’s change that, but first, here’s what Martin Fowler has to say, “One of the principal tenets of object oriented programming is encapsulation, or data hiding. This says that you should never make your data public. When you make data public, other objects can change and access data values without the owning object’s knowing about it. This separates data from behavior…Encapsulate field begins the process by hiding the data and adding accessors. But this is only a first step. Once I’ve done Encapsulate Field, I look for methods that use the new methods to see whether they fancy packing their bags and moving to the new object with a quick Move Method.” (Refactoring, p. 206)

Now let’s look at how to do this refactoring in Visual Studio. Put the cursor on length in the Line class then press Ctrl+R,Ctrl+E (Refactor, Extract). The Encapsulate Field dialog is displayed.

encapsultate-fields

Figure 6: Use the Encapsulate Field dialog to change a field to a property

Visual Studio recommended ‘Length’ as the property name. You can change it to something else if you want. When you click OK, a Preview dialog is displayed. Click Apply there. Here’s the refactored code.

public class Line
{
    public int length, width;

    public int Length
    {
        get { return length; }
        set { length = value; }
    }
}

public class MyLine
{
    public static void Main()
    {
        Line line = new Line();
        line.Length = 12;
        line.width = 1;

        // Some code to draw the line on the screen
    }
}

This is nice and tidy and follows a common standard that property name begin with a capital letter.

Refactoring: Extract Interface

Interfaces are a terrific way to get reuse and inheritance in your code. They also make code easier to unit test because it’s quite easy to mock an interface. The Extract Interface refactoring is very useful for that legacy code that you need to test and it looks at the class and creates an interface for it.

Here’s Martin Fowler’s take: “Classes use each other in several ways. Use of a class often means ranging over the whole area of responsibilities of a class. Another case is use of only a particular subset of a class’s responsibilities by a group of clients. Another is that a class needs to work with any class that can handle certain requests…Interfaces are good to use whenever a class has distinct roles in different situations. Use Extract Interface for each role.” (Refactoring, pp 341-342)

Let’s see this refactoring in action. Here’s the original method. Note that I’ve left out the actual implementation code.

public class CustomerRepository
{
    public Customer Find(int id) {}
    public IQueryable< Customer > GetAll() { }
    public void InsertOrUpdate(Customer customer) { }
    public void Save() { }
    public void Delete(int id) { }
    public Customer GetByPartialName(string name) { }
}

Place the cursor on the class name and press Ctrl+R,Ctrl+E (Refactor, Extract) to display the Extract Interface dialog. Visual Studio suggests a name for the Interface and allows you to select which methods to include. I selected all except GetByPartialName. When you click OK, Visual Studio created a new file (ICustomerRepository) and placed it in the same folder as the original class.

extract-interface

Figure 7: Extract Interface

interface ICustomerRepostory
{
    void Delete(int id);
    Customer Find(int id);
    IQueryable< Customer > GetAll();
    void InsertOrUpdate(Customer customer);
    void Save();
}

The original class is then changed to inherit from the new interface.

public class CustomerRepostory : ICustomerRepostory
{
    public Customer Find(int id) {}
    public IQueryable< Customer > GetAll() { }
    public void InsertOrUpdate(Customer customer) { }
    public void Save() { }
    public void Delete(int id) { }
    public Customer GetByPartialName(string name) { }
}

Now it’s easier to mock the code or substitute a different repository implementation for this one.

Refactoring: Remove Parameters

Getting all the parameters you need for a particular method is hard. As you develop the functionality, you realize that some parameters aren’t needed at all. Others may turn into properties or fields. It’s easy to do this if the method is called one or two times, but what if you call it many times from many places in the project? Then it becomes more difficult. This next refactoring helps you remove parameters.

Sticking with the pattern of this discussion, here’s Martin Fowler’s explanation: “A parameter indicates information that is needed; different values make a difference. You caller has to worry about what values to pass. By not removing the parameter you are making further work for everyone who uses the method.” (Refactoring, p. 277)

To use this refactoring, place the cursor over either the method definition or usage and press Ctrl+R, Ctrl+V (Refactor, remoVe) to display the Remove Parameters dialog.

remove-parameters

Figure 8: It’s easy to remove parameters with the Remove Parameters dialog.

Select the parameter to remove and press Delete. The parameter you want to remove is then shown in strikeout font and a preview of the method is shown. Click OK. If you selected Preview reference changes, a second dialog showing the changes is displayed. Click Apply. Visual Studio then refactors out the parameter.

Refactoring: Reorder Parameters

Do you think about the order of parameters in a method? Does it really matter?

Good coding practices says it does.

You should order parameters from most important to least important and optional parameters should fall at the end.

Now, you may have a differing opinion and that’s okay.

But this refactoring helps you get parameters in the order needed. Interestingly, this is one refactoring pattern Martin Fowler doesn’t catalog.

Now on to the usage.

Place the cursor on the method definition or usage and press Ctrl+R, Ctrl+O (Refactor, reOrder). The Reorder Parameters dialog is displayed.

reorder-parameters

Figure 9: Changing parameter order with the Reorder Parameters dialog.

Select the parameter to move, then use the mover arrows on the right. You can optionally preview changes. Click OK, then Apply if you previewed changes. Again, Visual Studio does all the updates for you.

Summary

There you have it. You’ve learned a bit about what refactorings are and why you want to refactor your code. I have shown you the built-in refactorings in Visual Studio.

If you look at the Martin Fowler book, you’ll see dozens of refactorings. He also has an online catalog with even more refactoring at http://refactoring.com/catalog/.

If you want more automatic refactorings, look to tools like Resharper or CodeRush. These commercial tools add enhancements to the built-in Visual Studio refactorings and add even more refactorings.

Refactoring your code is important to keep it maintainable and easy to read. It also helps reduce potential bugs and could improve your application’s performance. It’s pretty clear that refactoring is a practice that will keep your code lush, green, and vibrant.

Read our Software Gardening article series.

Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+
Further Reading - Articles You May Like!
Author
Craig Berntson works for one of the largest mortgage companies in the US where he specializes in middleware development and helping teams get better. He has spoken at developer events across the US, Canada, and Europe for over 20 years and is a Grape City Community Influencer. Craig is the coauthor of 'Continuous Integration in .NET' available from Manning. He has been a Microsoft MVP since 1996. Craig lives in Salt Lake City, Utah. Email: dnc@craigberntson.com Twitter: @craigber.


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Laurence on Monday, March 23, 2015 8:45 AM
I spent 3 hours reading the entire software series. To sum it up, it was FANTASTIC!
Comment posted by Erik Dahl on Tuesday, March 24, 2015 4:30 PM
Great article.  I especially liked the "refactor -rename" section with the two hard things in computer science and that you write for people first and computer second.  Really resonated with me.  Nice work and summary of the process!
Comment posted by Craig Berntson on Tuesday, March 24, 2015 5:16 PM
Laurence, Thank you. I hope to keep the good stuff coming. Next up is a series of articles on Seeds.

Erik, much appreciated.

Comment posted by Mugnaio on Thursday, April 2, 2015 9:34 AM
On your refactor of Line you left the field length public.
BTW, the "Rule of three" is about code duplication, it says that you can have a second duplication of code, but the third time you have to refactor.