次のシンプルなインターフェイスについて考える。
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コンストラクタは、ソースとともに誤った使用方法を広めてしまう。誤った使用方法には次のようなデメリットがある。
- リファクタリングが困難になる
- インターフェースによる抽象化を破壊する
- ソースとの結びつきを強める
正すためには、単純に実装クラスとコンストラクタの両方の可視性を制限すればよい。通常はパッケージプライベートを選択すればよく、次のような効果が得られる。
- クラスを同じパッケージ内のModuleでバインドする
- クラスを対象とする単体テストは、直接インスタンス化する
参照
Keep constructors on Guice-instantiated classes as hidden as possible.
0 件のコメント:
コメントを投稿