<輪読会> オブジェクト指向実践ガイド -第2章 単一責任のクラスを設計する-

輪読会メンバー

  • Izumi Haruya

github.com

  • Sekine Yutaro

github.com

第2章 単一責任のクラスを設計する

単一責任のクラスをどのように扱うべきか

  1. クラスが「シンプルであれと主張すること」が大切である
  2. クラスは「いますぐに」求められる動作を行い、後にも簡単に変更できるモデル化をする

    前者は簡単、ただ後者を考慮すると難しい

2.1 クラスに属するものを決める

  • 問題は技術的な知識(コード)より構造(クラスに属するものの配置)が大切

メソッドをグループに分けクラスにまとめる

  • クラスの設計が大切である
  • メソッドが増えていくとグループ分けしてクラスにまとめる

ここのメソッドは機能(Function)みたいな意味合いである

設計とはアプリケーションの可変性を保つために技巧を凝らすことであり、完璧を目指すための行為ではありません。 Sandi Metz. オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 (Japanese Edition) (Kindle の位置No.834-835). Kindle 版.

変更がかんたんなようにコードを組成する

変更が簡単とは

  • 変更は副作用をもたらさない
  • 要件の変更が小さければ、コードの変更も相応して小さい
  • 既存のコードはかんたんに再利用できる
  • 最もかんたんな変更方法はコードの追加である。ただし追加するコードはそれ自体変更が容易なものとする

書くコードに必要な性質(TRUE)

  • 見通しが良い(Transparent):変更するコードにおいても、そのコードに依存する別の場所のコードにおいても、変更がもたらす影響が明白である
  • 合理的(Reasonable):どんな変更であっても、かかるコストは変更がもたらす利益にふさわしい
  • 利用性が高い(Usable):新しい環境、予期していなかった環境でも再利用できる
  • 模範的(Exemplary):コードに変更を加える人が、上記の品質を自然と保つようなコードになっている

クラスが明確に定義された単一の責任を持つように徹底させる

2.2 単一の責任を持つクラスをつくる

なぜ単一責任が重要なのか

  • 変更が簡単なアプリは、再利用が簡単なクラスから構成される。
    • 着脱可能なユニット
  • メソッドを分けようと思ったら、クラスごとに分離する方が良い
    • 同じクラス内でメソッドを膨らませるのは良くない

クラスが単一責任かどうかを見極める

以下のような方法がある。

  • あたかもそれに知覚があるかのように仮定して問いただすこと

    • クラス(主語)でメソッド(機能)が成り立っているか質問する

    最小で有用なことは良いクラスである。

  • 1文でクラスを説明してみること

以前の話を思い出せば、クラスはできる限り最小で有用なことをすべきでした。それはかんたんに説明できるものであるべきです。考えつく限り短い説明に「それと」が含まれていれば、おそらくクラスは2つ以上の責任を負っています。「または」が含まれるようであれば、クラスの責任は2つ以上あるだけでなく、互いにあまり関連もしない責任を負っていることがわかるでしょう。

上記のような方法を表す言葉として「凝縮度」

凝縮は、1個のメソッドにどれだけ詰まっているかという認識である。

責任駆動設計(RDD:ResponsibilityDrivenDesign)という概念に由来します。彼らによれば「クラスはその目的を果たすための(複数の)責任を持つ」のです。

理解としては以下のようなイメージです。

責任駆動設計 > 単一責任の原則

クラスがすることはすべて、そのクラスの目的に強く関連することを求めることとは、以下の2つのどちらかに当てはまっていること

  • あたかもそれに知覚があるかのように仮定して問いただすこと
  • 1文でクラスを説明してみること

設計を決定するときを見極める

  • アプリケーションについての情報をより多く持つことが大事である。

    アプリケーションの情報はどんどん更新されていくため、どんなに精通してても初期開発時が一番情報が少ない

  • 情報が増えていく中で、新しい依存関係は優れた設計に必要な情報を与えてくれる

    (コストを鑑みて)タイムリーな修正が大事

2.3 変更を歓迎するコードを書く

どんな変更が発生することが起きるか予測することができないのでコードの拡張性を保つコードを意識する。

データではなく、振る舞いに依存する

  1. DRYに書くこと
  2. データのアクセス方法を考慮する必要がある
    • インスタンス変数の隠蔽

      • 1つ目は可視性に関すること
      • 2つ目は全てのインスタンス変数をメソッドに包んでしまうこと

      パブリックとプライベートについて

      • パブリックなものにすると他にも影響を与える可能性がある
      • オブジェクトはオブジェクトで見えるようにした方が良い
    • データ構造の隠蔽

      • 複雑な構造のデータに関係性を持たせない
      • 複雑な構造は分離する方が良い

あらゆる箇所を単一責任にする

  • メソッドから余計な責任を抽出する 役割が何であるか質問をし、また1文で責任を説明できるようにする(クラスと同じ)

    • 設計の変更
    • パフォーマンスの向上

    設計が明確でないから小分けにしておくことは大切である

    • 隠蔽されていた性質を明らかにする
    • コメントをする必要がない
    • 再利用を促進する
    • 他のクラスへの移動が簡単
  • クラスの余計な責任を隔離する

    • メソッドを単一責任にすれば、クラスのスコープはより明確になる
    • 設計上の選択をある/ないの二択にしてしまうのは短絡的

    二択化しないことで以下のようなことがわかる

    • 必要な理由が見えてくる。
    • その時点でやる理由が曖昧ならやる必要はないけど、覚えてはおけ
    • 大事なクラスに集中する

2.5 まとめ

まとめは本文参照です。

変更可能でメンテナンス性の高いオブジェクト指向ソフトウェアへの道のりは、単一責任のクラスからはじまります。1つのことに専念するクラスは、その1つのことをアプリケーションのほかの部位から「隔離」します。この隔離によって、悪影響を及ぼすことのない変更と、重複のない再利用が可能となるのです。 Sandi Metz. オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 (Japanese Edition) (Kindle の位置No.1318-1321). Kindle 版.

参考書籍

オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 | Sandi Metz, 髙山泰基 | 工学 | Kindleストア | Amazon