Starting to load test and performance profile an application you have developed is always an exhilarating time: I compare this with the Whack-A-Mole game, where, instead of funny animal heads, you hammer your classes down the execution tree until most of the time gets spent in code that is not yours.
Interestingly, I have seen the design of my application evolve while optimizing the critical parts of it. It is truly refactoring, as no feature gets added, but the code gets better performance wise.
Consider the following example that has arisen. Here is the original application design:
Profiling shown that computing the values of the context was really expensive and that these values were not always used by the target object.
I refactored to the following design:
In this design, the context values are only computed when the target object requests them, using a simple callback mechanism.
One could wonder why I did not simply remove the original context object and made O2 call O1. This would work but would have several disadvantages:
- unnecessarily increasing coupling between these two classes,
- visible design change, while I wanted the refactoring to respect the existing contracts between objects (the context in that case).