Legacy Code To Testable Code #7: Introduce Parameter

Standard

You didn’t think we’ve covered everything, did you? Here’s a short reminder of what we got through:

The Legacy Code To Testable Code Series

General patternsAccessibilityDealing with dependenciesAdvanced patterns
IntroductionAdd settersExtract methodStatic constructors (initializers)
RenamingMore accessorsExtract classMore static constructors
Add overloadIntroduce parameterInstance constructors
Testable objectConditionals to guard blocks

Today we’re going to talk about the Introduce Parameter refactoring pattern. This is one of the more useful patterns to clear code from dependencies.

Here’s a method we’d like to test:

As we can see, there’s a nasty dependency right there in the middle. Since in this example the static ShouldAdd call returns a Boolean result, we can turn this result into a parameter:

Thus removing the necessity to mock the static call, or handle side effects with the static calls (hello there, Mr. Singleton!).

Now, if the static call returns an object, the same thing applies.

This time, we’ll transform the singleton instance into a parameter:

This case may not be as trivial as passing a Boolean value. Now we need to mock that object, which may be a problem, for instance (pun intended), if our OperationManager has a private constructor. In this case we can now introduce an interface we can mock:

We still need to do all the modifications, but hopefully we have refactoring tools to help us.

Cleaning up dependencies not only helps us to test directly, but also makes it easy to extract the method into a new class.

Field extraction

An interesting case is when we have a field, being used inside the method:

That shouldAdd field is a dependency. It may not look like it, but it really is. You will notice it, when you try to extract the method into a separate class.

When we need to get rid of field dependencies, we can use the same refactoring pattern. This is a transitional step on the road to extraction to a separate class.

Note that while the parameter has the same name as the field, its scope has changed, and the method now uses it, rather than the field.

 

Leave a Reply

Your email address will not be published. Required fields are marked *