Refactoring

 < Day Day Up > 



You might have noticed that I didn’t carry out the final step of the TDD plan: refactoring to remove duplication. Refactoring is another concept that deserves a section of its own. This concept was also publicized by XP advocates, with Martin Fowler’s Refactoring: Improving the Design of Existing Code (Addison-Wesley, 1999) remaining the best work on the subject. Fowler defines refactoring as “the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.”

Refactoring GetDownload

As an example, there are several bits of duplication in the code that you just saw for the GetDownload method. Now that I have unit tests that cover the expected behavior of the code, I can refactor the code to remove this duplication. Here’s the revised code:

 // GetDownload uses the information in a Download object  // to get the specified file from the Internet to a local  // hard drive. Any download errors are wrapped in a  // custom exception and returned to the caller, along with  // the failing Download object.  public void GetDownload(Download d)  {      string filename = string.Empty;      string foldername = string.Empty;      WebClient wc = new WebClient();      try      {          // This method should never be called without          // a Source URL          Debug.Assert(((d.SourceUrl != string.Empty) &&              (d.SourceUrl != null)),              "Empty SourceUrl",              "Can't download a file unless a Source URL is supplied");          // If no filename specified, derive from SourceUrl          filename = ReplaceNull(d.FileName,              Path.GetFileName(d.SourceUrl));          // If no download folder specified, use default          foldername = ReplaceNull(d.DownloadFolder,              DefaultDownloadFolder);          // Ensure that we got a folder name somehow          Debug.Assert(foldername != string.Empty,              "Empty foldername",              "Download folder not set and no default supplied");          string TargetFile = Path.Combine(foldername, filename);          // Use WebClient to do the download          wc.DownloadFile(d.SourceUrl, TargetFile);          // Set file size in the Download object          FileInfo fi = new FileInfo(TargetFile);          d.Size = fi.Length;      }      catch (Exception e)      {          // Bubble any exception up to caller, with custom info          throw new DownloadException("Unable to download" ,d, e);      }      finally      {          wc.Dispose();      }  }  // Replace a possibly-null string with another string  // Returns the original string if it's not null or  // empty, otherwise returns the replacement string  private string ReplaceNull(string MaybeNull, string Replacement)  {      if((MaybeNull == string.Empty) ||          (MaybeNull == null))      {          return Replacement;      }      else      {          return MaybeNull;      }  } 

The new code isn’t shorter than the original, but most developers would agree that it’s a bit “cleaner” or “more beautiful.” These are terms that are difficult to define, but for the most part, developers know cleaner code when they see it.

More important, the code still passes the unit tests after these changes. Without the unit tests, it’s difficult or impossible to have the confidence that your refactorings won’t break something.

Refactoring Tools

Some refactoring patterns occur frequently (Fowler’s book is largely a catalog of such patterns). For instance, you might pull out repeated code to its own procedure, as I did in refactoring GetDownload. Or you might turn fields into properties, or vice versa, or create a superclass based on two similar classes. Making such changes is routine work—and routine work is a good source of automated tools.

TECHNOLOGY TRAP: Code Thrashing

start example

You should always have a purpose in mind when you refactor your code. Perhaps it’s time to remove duplicated code caused by cut-and-paste programming. Perhaps you’ve realized that a class isn’t general enough and needs a new superclass. But beware of refactoring just because you can. When your next coding task looks difficult or boring, it’s easy to decide that it’s time to clean up the existing code. A session of converting fields into properties can be just the ticket when you’re trying to avoid real work.

There’s a second problem that sometimes turns up in refactoring when a team of developers is involved. If different developers have different ideas about what makes for beautiful code, they can waste a lot of time second-guessing each other. A tip-off to this behavior is a set of source code check-in comments like this:

  • 4-7-04 MG Converted fields to properties

  • 4-8-04 SJ Converted properties to fields

  • 4-10-04 MG Converted fields to properties

  • 4-11-04 SJ Converted properties to fields

If you find such a list of comments in your own source code control system, it’s time to get the team together over a pot of coffee or a pizza and discuss the problem. Shared vision and coding standards can help you avoid the issue in the first place, but be ready to listen to everyone concerned. It’s possible that one of the developers involved has spotted a problem with the code that the rest of the team doesn’t yet understand.

end example

Automated refactoring is an area where several other development environments (notably Smalltalk and Java) are well ahead of .NET. However, some tools are available for .NET:

  • dotEasy A free Visual Studio .NET add-in that evaluates code based on various metrics and that plans to support automatic refactoring of problematic code. (www.doteasy.com.uy/)

  • The C# Refactoring Tool Supports a number of standard refactorings, including smart renaming, encapsulating fields, extracting methods, moving members, and more. Costs $110 per user. (http://dotnetrefactoring.com/)

  • C# Refactory A full-featured refactoring tool that integrates with Visual Studio .NET. At $99, it offers a solid set of refactorings in a well-designed interface. (www.xtreme-simplicity.net/CSharpRefactory.html)

  • Flywheel A $449 tool for designing and refactoring .NET code. It supports refactoring by drag and drop in the Flywheel interface. (www.velocitis.com/)

If you find that TDD works well for you, or you’re faced with a complex pile of existing object-oriented code that needs to be cleaned up and rearranged, it’s worth evaluating these tools to see whether they can help.



 < Day Day Up > 



Coder to Developer. Tools and Strategies for Delivering Your Software
Coder to Developer: Tools and Strategies for Delivering Your Software
ISBN: 078214327X
EAN: 2147483647
Year: 2003
Pages: 118

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net