When you're stuck

It happens a lot, especially when working on legacy code, that you can’t figure out a “business logic” algorithm that isn’t already well documented. Sure, it’s in the code, but so are a million other things, and you can’t eyeball the part that does all the calculation. The client is asking for a change or a fix and you’re not sure where to start.
That’s when I think you can do three things at once: improve the overall structure, impose some unit testing, and solve the problem you were asked to. Refactoring does all of these.

Long story short

Refactoring is the practice of changing existing code to improve its structure without changing its function or effect. Ordinarily you do it when something changes in the requirements. For example, the simple structure that works fine when your software supports only one state’s regulations has to turn into a lookup table when you add another state.

Sometimes the requirements change is implicit though. The old system worked because Rick patched it to death, and Rick isn’t here anymore, and the new requirement is someone besides Rick has to know what it does. Commenting is a well-known (because it’s easy) but also widely ignored (because it’s rarely accurate) way to communicate, but you’re probably better off letting the code do the talking.

What that means

Suppose you’re doing a WinForms application and an event handler does an important calculation. You want to figure out what that calculation does, because it probably needs to be changed, but it’s entangled with all the code that updates the GUI and saves some stuff to a database.

The thing to do is create at least a token class that pulls the calculation into a single method or group of methods. To wit, you’d edit this:

[sourcecode language=”vb”]
Private Sub btnGo_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGo.Click
btnClose.Enabled = True
btnUpdate.Enabled = False
Dim moneyvalue as Decimal
moneyvalue = … ‘ Complex money calculation here
txtPrice.Text = "$" & String.Format("Order Total: {0:C}", moneyvalue);
End Sub
[/sourcecode]

Into this:

[sourcecode language=”vb”]
Private Sub btnGo_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGo.Click
btnClose.Enabled = True
btnUpdate.Enabled = False
Dim quantity as Integer
Dim moneyvalue as Decimal
quantity = Integer.Parse(txtQuantity)
moneyvalue = calc.GetTotalPrice(quantity)
txtPrice.Text = "$" & String.Format("Order Total: {0:C}", moneyvalue);
End Sub
Public Class PriceCalculator
Public Function GetMoneyValue(qty as Integer)
‘ Complex calculation goes here
End Function
End Class
[/sourcecode]

The simplest thing that could possibly work

What’s the point? You haven’t changed any functionality at all!

Yes, that’s the point. You have the exact same inputs and outputs, but now the PriceCalculator class can be maintained free of GUI pollution. The next step is to download something like NUnit, add it to your project, and create unit tests for all the methods of the PriceCalculator.

Here’s the crazy thing. When you write unit tests for the existing code, you will gradually close in on the intended (and actual) functionality of the code you’ve refactored. So while you put the code into a more testable format, you are also getting closer to understanding enough to make the change, and making it much easier to modify in the future.

You totally want to read more about this, and you will, if you opt in to my eZine. You get a complete mailing about once a month, with articles and link that help you do your job, as well a quick note every week or so with something funny or interesting.

If you work with software, and if you’re frustrated, then this is for you.

Look, I know you’re busy. You want to do, as they say in Extreme Programming, “The Simplest Thing That Could Possibly Work.” I’m saying this is the simplest thing that could possibly work!

Two reasons for that

For one thing, the dependent clause is important. The “simplest thing” is no good if it doesn’t work! And by “work” we mean a solution that doesn’t create more headaches than it removes. Hacking at pre-existing financial code in a GUI event handler? Well, that doesn’t work, almost tautologically. Because in the end you still have financial code in a GUI event handler.

The other thing is that the default approach, that of modifying the code in place and hoping you got it right, isn’t the simplest thing. It’s a lot of work! And it’s error-prone, which means you have to do it again probably, and that isn’t simple either.

The cost of refactoring

If you choose your oppportunities carefully, refactoring makes your code better at no cost because it is only the shortest path to getting the right answer that you wanted anyway. Truly, the question isn’t whether you have time for refactoring; the question is whether you have time not to.

A chance to talk

Do you work in a shop where obvious refactorings are “a waste of time”? Do they turn your best estimates to mush? Is it hard to do your best work because they won’t let you fnish things? I can’t immediately solve those problems unless you hire me, but I can provide a place to talk and vent.

Take five minutes away from whatever is frustrating you at the moment, and bend it to my survey on the Developer Bull Session concept. Let me know if you’re interested in talking or listening in a voice (!) conversation now and then, via conference call or stream.