0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

第8章 密結合 ─ 絡まって解きほぐせない構造 ─

ソフトウェア設計において、モジュール間の依存関係の強さは「結合度」として表される。結合が強すぎると、一部を変更するだけで他の部分にまで影響が及び、保守性が著しく低下する。この章では、密結合の問題と、それを解消するための設計手法について学ぶ。

8.1 密結合と責務

密結合の典型的な例として、以下のようなクラス構造が挙げられる。

  • 一部のクラスに処理が集中している
  • 何も処理を持たないクラスが存在する
  • 他のクラスの一部のメソッドを無理やり流用している

これは単一責任の原則 (Single Responsibility Principle; SRP) に違反している状態であり、様々な問題を引き起こす。

単一責任の原則 (SRP)

SRP とは、「クラスが担う責任は、たったひとつに限定するべき」という原則である。この原則を守らないと、次のような問題が発生する。

  • 偶然同じ処理だからと使い回すと、意図しない責任の重複が発生する
  • データだけを持ち、処理を持たないクラスは、そもそも責務を果たしていない
  • なんでもやるクラスを作ると、コードの重複が増え、変更が困難になる

「Manager クラス」を安易に作らず、一つのことに集中する Value Object を設計することが重要だ。共通化の判断は慎重に行うべきであり、異なる概念を無理に DRY (Don't Repeat Yourself) にしないよう注意する。

実際の開発でも、共通化したつもりが後々異なる概念へと分岐し、結果的に無理な条件分岐を増やしてしまうケースは多い。仕様変更の際には、過去に共通化した部分が本当に正しいのかを再評価し、場合によっては「共通化を解く」ことも視野に入れるべきだ。

8.2 密結合の各種事例と対処方法

継承による密結合

継承 (is-a 関係) は便利な機能だが、強い依存関係を生み出すため、推奨されない。

  • サブクラスはスーパークラスの構造に依存し続ける
  • スーパークラスの変更によって、サブクラスの動作が壊れやすい
  • 共通ロジックの置き場としてスーパークラスを利用すると、仕様変更の際に不自然な構造になりがち

そのため、継承よりも コンポジション (has-a 関係) を優先するべきである。スーパークラスがサブクラスの存在を意識せずに済む設計のほうが、影響範囲を限定できる。

開発の現場でも、継承を使った設計が後に足枷になることは多い。共通ロジックを持たせたいときは、まずは 値オブジェクトやコンポジション を検討し、それでも難しい場合に継承を考えるようにするべきだろう。

クラス分割による密結合の解消

一つのクラスが複数の異なる責務を持っている場合、そのクラスは分割すべきである。特に、

  • メソッドが互いに無関係なインスタンス変数を使用している
  • private メソッドが異常に多い

このような状況では、責務の分離を行い、それぞれの関心事を独立したクラスにするのが望ましい。

現場では、つい private メソッドを増やしてしまいがちだが、それは往々にして「クラスが本来持つべきでない責務を抱え込んでいる」証拠である。Controller クラスなどは特に責務が集中しやすいため、意識的に整理することが重要だ。

アクセス修飾子の適切な使用

何でも public にしてしまうと、影響範囲が広がり、密結合を助長する。Java では package private (デフォルトのアクセス修飾子) によってパッケージ内の依存を制御できるが、PHP ではこの仕組みがないため、特に注意が必要だ。

また、public メソッドを増やしすぎると、外部のクラスからの過剰な依存を生みやすくなる。内部で完結すべきロジックは、適切にカプセル化するべきだ。

高凝集の誤解と密結合

高凝集を意識するあまり、異なる概念のロジックを一箇所にまとめてしまうことがある。結果として、コードの可読性が低下し、修正が困難になる。

  • 概念が異なるものは別のクラスにする
  • ある概念の値を使って別の概念の値を算出する場合は、適切なコンストラクタを用意する

このような原則を意識し、適切なクラス設計を心がけることが大切だ。

8.3 密結合の具体例

密結合が発生しやすい典型的なケースを紹介する。

  • スマート UI:UI 層に計算や分岐ロジックが実装されている
  • 巨大データクラス:すべてのユースケースで扱うデータクラスを定義し、結果的にグローバル変数のように扱われる
  • トランザクションスクリプト:長大なメソッドの中で手続き的な処理がダラダラと続く
  • 神クラス:責務の集約が進みすぎて、あらゆる処理を担う巨大クラスが誕生する

これらを防ぐには、クラスを適切に分割し、単一責任を守ること が最も重要である。一般的に、適切に分割されたクラスのサイズは 100~200 行程度になる。

まとめ

密結合は、ソフトウェアの柔軟性を大きく損なう要因となる。本章で述べたように、継承を避けてコンポジションを使う、単一責任を守る、適切なクラス分割を行う ことで、密結合の問題を解消できる。

実務では、つい短期的な実装のしやすさを優先してしまいがちだが、その積み重ねが将来の技術的負債につながる。本章で学んだ原則を意識しながら、日々の設計を見直していくことが重要だ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?