Thursday, May 3, 2007

Another reason to love ReSharper

Whenever I look at a class in code for the first time, I try to figure out what its responsibilities are.  Ideally, I would look at unit tests exercising the public interface.  These unit tests will give me a description of functionality, code showing usage, and most likely some assertions describing and verifying behavior.  If there aren't any unit tests, I have to resort to figuring out what the code is doing by examining the code (which is about 10 times slower than looking at unit tests).

First off, I'll look at the using directives at the top of the file.  Using directives can provide a key insight into the behaviors and responsibilities of a class, since the using directives show me what the dependencies are.  For highly cohesive, loosely coupled code, you probably won't see a ton of using directives, as a general rule of thumb.  I was a little disheartened when I saw these using directives:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.DirectoryServices;
using System.Data.SqlClient;
using System.Drawing;
using System.Drawing.Design;
using System.ComponentModel.Design;
using System.Configuration;
using System.Xml.Serialization;
using System.Xml;
using System.IO;

using GL = System.Globalization;
using CMP = System.IO.Compression;
using MSG = System.Messaging;

using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Security;
using MyCompany.Commerce.BusinessObjects.Shipping;
using MyCompany.Commerce.Core;
using SCF = MyCompany.Commerce.StoreConfiguration;
using MyCompany.Commerce.Core.BusinessObjectManager;
using SH = MyCompany.Commerce.BusinessObjects.Ecomm.Security.SecurityHelper;
using ctx = MyCompany.Commerce.BusinessObjects.StoreContext;
using MyCompany.Sales.Security;
using MyCompany.Sales.Profile;
using Microsoft.ApplicationBlocks.ExceptionManagement;

Wow.  That's a lot of using directives.  Boooo.  It looks like this class cares about web services, ADO.NET, XML serialization, IO, session state, and the list goes on and on.  Waaaay too much for one class to care about.  If there were a such thing as code referees, this class would get red carded for a flagrant foul of the Single Responsibility Principle.  Luckily, I have Resharper.

ReSharper to the rescue

ReSharper is pretty much crack for developers.  Once you use it for a week or even a day, you'll find it nearly impossible to develop without it.  So how did ReSharper help me in this situation?  With a nifty "Optimize using directives" refactoring of course.  The "Optimize using directives" refactoring will remove unused using directives, and can also add new ones where you've qualified type names with namespaces.  Here are the using directives after the refactoring:

using System;
using System.IO;
using System.Web.Services;
using System.Xml.Serialization;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using BO = MyCompany.Commerce.BusinessObjects;
using Microsoft.ApplicationBlocks.ExceptionManagement;
using MyCompany.Commerce.BusinessObjects.Shipping;
using MyCompany.Commerce.Core;
using SCF = MyCompany.Commerce.StoreConfiguration;
using MyCompany.Commerce.Core.BusinessObjectManager;
using SH = MyCompany.Commerce.BusinessObjects.Ecomm.Security.SecurityHelper;
using ctx = MyCompany.Commerce.BusinessObjects.StoreContext;
using MyCompany.Sales.Security;
using MyCompany.Sales.Profile;

HUGE improvement in readability.  Now I can be fairly certain what the external dependencies of this class are, as we reduced the number of using directives from 34 (!) to 18, around half.  There's still way too many dependencies, I'd like to see this number reduced to around 5 or so.  ReSharper will also sort the using statements to group common directives together (it doesn't work for using aliases).  Now it's not as big a leap as it was before to try and figure out what this class does.  That's one less ibuprofen I'll need today :).  Of course, if this class had been properly unit tested, I wouldn't need the ibuprofen in the first place, but that's another story.

2 comments:

Ilya Ryzhenkov said...

Did you try ReSharper 3.0 (which is Release Candidate currently) and it's new feature "Find referenced code"? It looks like exactly what you need to analyse type dependencies.

Jimmy Bogard said...

I've been limiting my ReSharper beta experiences to an Orcas VM I have, but it's been looking great so far (aside from LINQ, but that's to be expected). It's tough to try, on my regular dev machine, a beta or RC for a tool that's absolutely vital to my productivity.