2014年7月7日月曜日

Google GuiceのBest Practicesを訳してみた - Guiceがインスタンス化するクラスのコンストラクタはできるだけ隠蔽する

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

ちょっと見ただけでは、このコードには何も問題がないようにみえる。不幸なことに、

よく知られたことだが、コンストラクタをpublicにするといいことは何もない。publicコンストラクタは、ソースとともに誤った使用方法を広めてしまう。誤った使用方法には次のようなデメリットがある。
  • リファクタリングが困難になる
  • インターフェースによる抽象化を破壊する
  • ソースとの結びつきを強める
何よりも悪いのは、コンストラクタを直接使用すると、Guiceによるインスタンス化を避けることになる。

正すためには、単純に実装クラスとコンストラクタの両方の可視性を制限すればよい。通常はパッケージプライベートを選択すればよく、次のような効果が得られる。
  • クラスを同じパッケージ内のModuleでバインドする
  • クラスを対象とする単体テストは、直接インスタンス化する
publicと@Injectはエルフとドワーフのようなものだと覚えておくとよい。彼らは協力することもできるが、独立して存在しているのだ。

参照
Keep constructors on Guice-instantiated classes as hidden as possible.

0 件のコメント:

コメントを投稿