Javaにおける「疎結合」はどこまで許されるか
Javaにおける「疎結合」はどこまで許されるか
「疎結合(loose coupling)」は、設計においてしばしば正義のように語られます。
しかし、疎結合であることは常に正しいのでしょうか?
本記事では、「疎結合であること」それ自体が設計上の目的ではなく、目的を実現するための“手段”であるという前提に立ち、
Javaで疎結合を設計する際の限界、そしてレビュー時に注目すべき判断基準を整理します。
疎結合とはなにか? ――定義の再確認
設計上の「疎結合」とは、モジュールやクラス間の依存度を下げ、変更の影響範囲を狭める設計方針です。
- 密結合(tight coupling):あるモジュールの変更が他に直結する構造
- 疎結合(loose coupling):依存の方向・内容を制御して、影響範囲を明示的に限定する構造
疎結合は以下のような文脈で登場します:
- インターフェースによる依存の抽象化
- DI(Dependency Injection)による依存の注入
- オブザーバパターンなどによる制御の間接化
Javaにおける疎結合の実践パターン
1. インターフェースで依存先を抽象化する
public interface MailSender {
void send(String to, String message);
}
public class NotificationService {
private final MailSender mailSender;
public NotificationService(MailSender mailSender) {
this.mailSender = mailSender;
}
public void notifyUser(String userId) {
// ...
mailSender.send(userId, "Hello");
}
}
- 依存先(MailSender)をインターフェースにし、実装は注入により決定
- テストや拡張のための柔軟性が確保される
2. DIによるインスタンス制御
JavaではSpringなどのDIコンテナを通じて、実装の差し替えやモック化が可能になります。
@Bean
public MailSender mailSender() {
return new SmtpMailSender();
}
DIによる疎結合は、構成ファイルや設定の柔軟性に依存しますが、コード上は明確に抽象化が維持される設計になります。
疎結合の「行き過ぎ」による設計ミス
1. 意味のないインターフェース化
public interface Logger {
void log(String message);
}
public class DefaultLogger implements Logger {
public void log(String message) {
System.out.println(message);
}
}
Loggerの実装が1つしかない、もしくは差し替える必要が全くない場合、抽象化による疎結合は“設計コストの増加”を招くだけになります。
将来的に変更・差し替えが必要な場合に備えて疎結合にする。
逆に言えば「差し替え予定がないなら疎結合である必要はない」こともあります。
2. 疎結合化の副作用:トレース性・責務の不明瞭化
インターフェースが乱立すると、呼び出し元と実装の関係が見えにくくなり、構造が不透明になります。
// どの実装が使われているか、IDE上でも追跡困難
Service service = container.resolve(Service.class);
テスト性や柔軟性は高まっても、日常の保守・デバッグにおけるトレースコストが増加する可能性も考慮すべきです。
レビュー観点:「疎結合であるべき理由があるか?」
チェックリスト
疎結合の目的が「変更に強くするため」であるかを確認し、過剰抽象による構造の不透明化が起きていないかを重点的に見る。
設計補足:疎結合と「局所的最適化」
疎結合を層・単位・責務という文脈で設計するなら有効ですが、
個別のクラスレベルでむやみに導入すると、構造は複雑化しやすくなります。
適切なスコープでの疎結合が必要
- サービスの呼び出し先だけでなく、呼び出し元との関係性を設計に含める
- クラス内で完結する責務に対してまでインターフェースを導入しない
- インターフェース化する責務の粒度を見誤らない
まとめ:「疎結合」は常に良い設計ではない
疎結合は、「柔軟性」「拡張性」「テスト容易性」を得る手段として非常に強力です。
しかし、以下の観点から過剰な抽象化には設計上の注意が必要です。
- 疎結合にする目的が明確か?
- その疎結合が実際に活用されているか?
- 抽象化によって構造が逆に追いづらくなっていないか?
レビューアーは「疎結合にすべきか?」ではなく、
「その疎結合が何をもたらし、何を失っているか」を問う視点を持つべきです。