|
KeepConstructorsHidden
Keep constructors on Guice-instantiated classes as hidden as possible.Consider this simple interface: public interface DataReader {
Data readData(DataSource dataSource);
}It's a common reflex to implement this interface with a public class: public class DatabaseDataReader implements DataReader {
private final ConnectionManager connectionManager;
@Inject
public DatabaseDataReader(
ConnectionManager connectionManager) {
this.connectionManager = connectionManager;
}
@Override
public Data readData(DataSource dataSource) {
// ... read data from the database
return Data.of(readInData, someMetaData);
}
}A quick inspection of this code reveals nothing faulty about this implementation. Unfortunately, such an inspection excludes the dimension of time and the inevitability of an unguarded code base to become more tightly coupled within itself over time. Similar to the old axiom, Nothing good happens after midnight, we also know that Nothing good happens after making a constructor public: A public constructor will have illicit uses introduced within a code base. These uses necessarily will:
Perhaps worst of all, any direct use of a constructor circumvents Guice's object instantiation. As a correction, simply limit the visibility of both your implementation classes, and their constructors. Typically package private is preferred for both, as this facilitates:
As a simple, mnemonic remember that public and @Inject are like Elves and Dwarfs: they can work together, but in an ideal world, they would coexist independently. |
Sign in to add a comment
You tell us what not to do but not what we should do? Private class? Private ctors?
Package local/private class is my preference. Or the same for (or protected) constructor depending on your use case. A lot of this depends on how the specific class in intended to be used.
The doc's main point is, prefer depending on interfaces and let Guice call new, as this gives you the maximum amount of control and flexibility of design.