I'll put up some code samples soon, but I'd better write the skeleton down before I forget it :-)
Converting a method body into a delegation to strategy
When?
- I am trying to test the method.
- The parameter(s) to pass into the method is too complicated to construct/has an external dependency.
- The parameter(s) to pass to the method is too complex to mock out; doing so would entail multiple ExpectAndReturn() calls.
- I am trying to stub out this method but I don't want to override its class.
Wrapping a static call in a instance method.
When?
- I'm trying to test the containing method.
- The static call has an external dependency.
Result:
- The instance method is part of the interface. My test implementations of this interface does what I want it to.
- The method I'm testing gets an extra parameter, which is the object that I'm injecting.
- The class gets an extra field which is initialised to the default-behaviour implementation in the constructor / some appropriate place.
The 'SWAT' class
This is a really cool refactoring I got to do a few days back. Doubtless, some book will refer to it, but I describe it here.
When?
- A class has too much functionality that must be moved to a higher level than the class, or to a different class.
- The system has a lot of references to the functionality that must be moved.
Steps:
- Create a SWAT class. It does not need a terribly meaningful name at this point since it may be removed at the end of the refactoring.
- Inject an instance of the SWAT class into the bloated class C. My preference is the constructor, but it could be a setter injection too.
- Find all methods in class C that need moving.
- Duplicate all those methods in your SWAT class with the exact same functionality. You may need to inject an instance of class C to do this.
- Replace the method bodies (of the methods that need moving) in class C with delegations to the injected SWAT instance. You may have to pass in this as a parameter in almost all these delegated calls.
- You will still have the methods inside class C but they will now all delegate to the SWAT instance.
- Find all the usages of those methods and replace them direct calls to the SWAT instance. This will probably take the longest time.
- How do you get the SWAT instance outside class C? You may need to inject it from higher.
- Remove all the methods in class C that are no longer used.
- Now do what you want with your SWAT calls. Break the SWAT class into various classes because it might have unrelated pieces of functionality, or give it a nice name.
- Done!