Revision 1 as of 2009-12-12 06:12:02

Clear message
Locked History Actions

guice/Manual/BestPractices/KeepConstructorsHidden

Guiceが生成するクラスについてのコンストラクタをできる限り隠せ

以下のシンプルなインターフェースを考えてみよう。

public interface DataReader {
 
  Data readData(DataSource dataSource);
}

このインターフェースを以下のようなpublicクラスで実装するのが普通である。

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);
   }
}

特に問題はないように見える。 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:

  • make refactoring more difficult.
  • break the interface-implementation abstraction barrier.
  • introduce tighter coupling within a codebase.

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:

  • binding the class within a Module in the same package
  • unit testing the class through means of direct instantiation

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.