Java Reference
In-Depth Information
An effective design strategy is to pass to an object any other object that's outside its
immediate business logic. The choice of peripheral objects can be controlled by
someone higher in the calling chain. Ultimately, as you move up in the calling layers,
the decision to use a given logger or configuration should be pushed to the top level.
This strategy provides the best possible code flexibility and ability to cope with
changes. And, as we all know, change is the only constant.
7.3.1
Refactoring example
Refactoring all code so that domain objects are passed around can be time consum-
ing. You may not be ready to refactor the whole application just to be able to write a
unit test. Fortunately, there's an easy refactoring technique that lets you keep the
same interface for your code but allows it to be passed domain objects that it
shouldn't create. As a proof, let's see how the refactored DefaultAccountManager
class could look. See listing 7.5; modifications are shown in bold.
Listing 7.5
Refactoring DefaultAccountManager for testing
public class DefaultAccountManager implements AccountManager {
private Log logger;
private Configuration configuration;
B
public DefaultAccountManager() {
this(LogFactory.getLog(DefaultAccountManager.class),
new DefaultConfiguration("technical"));
}
public DefaultAccountManager(Log logger, Configuration configuration) {
this.logger = logger;
this.configuration = configuration;
}
public Account findAccountForUser(String userId) {
this.logger.debug("Getting account for user [" + userId + "]");
this.configuration.getSQL("FIND_ACCOUNT_FOR_USER");
// Some code logic to load a user account using JDBC
[...]
}
[...]
}
Notice that at B , we swap the PropertyResourceBundle class from the previous list-
ing in favor of a new Configuration interface. This makes the code more flexible
because it introduces an interface (which will be easy to mock), and the implementa-
tion of the Configuration interface can be anything we want (including using
resource bundles). The design is better now because we can use and reuse the Default-
AccountManager class with any implementation of the Log and Configuration
interfaces (if we use the constructor that takes two parameters). The class can be con-
trolled from the outside (by its caller). Meanwhile, we haven't broken the existing
interface, because we've only added a new constructor. We kept the original default
 
 
 
 
 
Search WWH ::




Custom Search