ソフトウェア開発において「関心の分離(Separation of Concerns)」は基本原則の一つである。
しかし、よくあるアンチパターンとして、ドメインロジックと表示形式が密結合してしまうケースがある。
この状態が何を引き起こすのかを具体的に解説する。
💡 密結合とは?
ここで言う「密結合」とは、ある層の変更が別の層にも影響を与える状態を指す。
例えば、ユースケースが以下のように「JSONの構造そのもの」を返していたとしよう。
func (u UseCase) Execute(...) map[string]interface{} {
return map[string]interface{}{
"id": "123",
"question": "...",
...
}
}
このようにユースケースが表示形式(ここではJSON)に直接関与してしまうと、変更に弱くなる。
⚠ 密結合が引き起こす問題
① 表示形式の変更がユースケースに影響する
APIとしてJSONを返す設計にしていたが、ある日「CLI出力も対応してほしい」となったとする。
このとき、ユースケースが JSON 固定で出力していた場合、次のような事態になる:
- JSON部分のロジックを書き換える必要がある
- 本来変えるべきでないユースケースの中身が変更されてしまう
- テストの再設計・再実行が必要になる
② テストしづらくなる
ユースケースのテストは「ロジックが正しいか」に集中したい。
しかし表示形式も組み込まれていると、「表示フォーマットも合わせて正しいか」という複数の観点を同時に検証することになる。
→ テストコードが複雑になる
→ バグの原因が特定しにくくなる
③ 再利用しづらくなる
ユースケースが特定の表示形式に依存していると、以下のような再利用の場面で問題が起きる:
- Webアプリ用の表示
- CLIツールでの出力
- バッチ処理での内部利用
出力フォーマットが埋め込まれているため、ロジックを使い回すためには、余計な表示ロジックも引きずることになる。
✅ 解決策:表示はプレゼンターに任せる
ドメインロジックと表示形式は、責任が全く異なる。
層 | 役割 |
---|---|
ユースケース | 何をするか、どう処理するか |
プレゼンター | どう見せるか、どんな形式で出力するか |
このように責務を切り分けておくことで:
- 表示の変更がプレゼンター内で完結する
- ロジックが軽量かつ再利用しやすくなる
- テストも明確な単位で書けるようになる
🧭 まとめ
問題点 | 内容 |
---|---|
表示形式の変更が本来のロジックに波及する | |
テストの粒度が不明確になり、バグの原因が追いにくくなる | |
再利用が困難になり、機能追加時にコストがかかる |
密結合は一見「楽」に見えるが、後から必ずツケが回ってくる。
プレゼンターを用いた責務分離を意識することで、柔軟で保守性の高いコード設計が実現できる。