Joe White’s Blog

Life, .NET, and Cats


ReSharper, day 25: Introduce Parameter

Welcome to day 25 of my 31 Days of ReSharper.

I’ve talked about two of the three Introduce refactorings (Introduce Variable and Introduce Field). Today, I’ll cover the third: Introduce Parameter.

ReSharper's Introduce Parameter dialog box

Apart from the top pixel of the “Type” combo getting cut off, and the lack of an “Introduce constant” checkbox, this looks an awful lot like Introduce Variable. It works a lot like it, too. Stubborn blue highlights, all that stuff.

Sounds pretty mundane. But here’s the thing: it works. It’s surprisingly smart.

Here’s a silly example:

_tilesWide = GetTilesWide(_previewer);
...
private int GetTilesWide(Control control)
{
return (control.Width + TileWidth - 1) / TileWidth;
}

Suppose you want to write unit tests for this function, but you don't want to create Control instances in your tests. You could just highlight control.Width and do an Introduce Parameter.

Oddly enough, the first suggestion for a parameter name is i, instead of the more obvious width. (width is available in the combo box dropdown, though.) It's also a bit of a shame that it doesn't suggest controlWidth.

Supposing that I did type in controlWidth for my variable name, the resulting code would look like this:

_tilesWide = GetTilesWide(_previewer, _previewer.Width);
...
private int GetTilesWide(Control control, int controlWidth)
{
return (controlWidth + TileWidth - 1) / TileWidth;
}

At that point, the control parameter turns gray — you aren't using at anymore. So you can cursor onto it and use Alt+Enter to remove the unused parameter, leaving you with code that doesn't have scary dependencies and is much easier to unit test:

_tilesWide = GetTilesWide(_previewer.Width);
...
private int GetTilesWide(int controlWidth)
{
return (controlWidth + TileWidth - 1) / TileWidth;
}

(If the method had been public, then the parameter wouldn't have shown up in gray, because ReSharper isn't brave enough to look at public methods. Hopefully that will be fixed when they add #pragma support to suppress individual warnings, which they tell me will be in the next release. But hang in there; there are other ReSharper features that know how to delete parameters.)

What's cool isn't so much that it adds the parameter. That's really no cooler than adding a local variable. What's cool is that it automatically does the Right Thing at all the call sites. If one of the call sites was passing an arbitrarily complicated expression that resulted in a Control instance, that's fine: it would turn into an arbitrarily complicated expression followed by .Width.

It works for extracting more complicated expressions, too. You can use, not only other parameters, but also static methods, and even instance methods and properties on the current class. ReSharper will just do the right thing.

Here's an example that's a little closer to real life. I may or may not be anywhere close to what we were actually doing in the code, but if the rest of this post is a work of fiction, it doesn't make it any less cool.

processor.ProcessFile(FileType.Foo);
...
public void ProcessFile(FileType fileType)
{
string fileName = this.Configuration.GetFileName(fileType);
...
}

We were trying to get rid of the Configuration property, because it was scary and hard to get instantiated in a test harness. So we started by extracting a parameter for this.Configuration.

processor.ProcessFile(FileType.Foo, processor.Configuration);
...
public void ProcessFile(FileType fileType, Configuration configuration)
{
string fileName = configuration.GetFileName(fileType);
...
}

What really wowed me (and it may seem like a simple thing to you, but I've tried to write a parser before, so I appreciate this kind of stuff) is that it just did the right thing at the call site: it passed processor.Configuration. The parameter was automatically passed in terms of the right instance of the right object.

That's just cool.

There are no responses to “ReSharper, day 25: Introduce Parameter” yet.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>


Joe White's Blog copyright © 2004-2011. Portions of the site layout use Yahoo! YUI Reset, Fonts, and Grids.
Proudly powered by WordPress. Entries (RSS) and Comments (RSS). Privacy policy