Code Smell – Bad Smell in Code : Understanding Shotgun Surgery
You can insert calls to wait(), sleep(), yield(), and priority() in your code by hand. It might be just the thing to do when you’re testing a particularly thorny piece of code.
Here is an example of doing just that:
public synchronized String nextUrlOrNull() {
if(hasNext()) {
String url = urlGenerator.next();
Thread.yield(); // inserted for testing.
updateHasNext();
return url;
}
return null;
}
The inserted call to yield() will change the execution pathways taken by the code and possibly cause the code to fail where it did not fail before. If the code does break, it was not because you added a call to yield(). Rather, your code was broken and this simply made the failure evident.
There are many problems with this approach:
– You have to manually find appropriate places to do this.
– How do you know where to put the call and what kind of call to use?
– Leaving such code in a production environment unnecessarily slows the code down.
– It’s a shotgun approach. You may or may not find flaws. Indeed, the odds aren’t with you.
What we need is a way to do this during testing but not in production. We also need to easily mix up configurations between different runs, which results in increased chances of finding errors in the aggregate.
Clearly, if we divide our system up into POJOs that know nothing of threading and classes that control the threading, it will be easier to find appropriate places to instrument the code. Moreover, we could create many different test jigs that invoke the POJOs under different regimes of calls to sleep, yield, and so on.
Recent Comments