読書「Clean Code」10章

本を読んで勉強したことの定着のために、ブログ記事にしていくことにした。記事でなくすべてをまとめたページにまとめようと思ったが、編集しかけで破綻しがちなので、小さいアップデートを積み上げられるようこの形にしてみる。

今回は Robert C. Martin著 Clean Codeの10章を読みながらのメモである。

覚えておきたいポイントとしては下記。よく出てくるキーワードばかりだが

  • 単一責務の原則 (Single Responsibility Principle, SRP)
    • 「責務」== 変更の原因となるもの
    • クラスが増えることを嫌い無視されがちだが、小さなクラスで全体をわかりやすく構成すべきである
  • 凝集性
    • 大量の小さなクラスができる
  • 開放/閉鎖の原則 (Open Closed Principle, OCP)
    • 新規機能が既存システムの拡張のみで実現され、既存コードの変更が皆無であることが理想
  • 依存性逆転の原則 (Dependency Inversion Principle)
    • インターフェイスで分離することでテストしやすく、柔軟性、再利用性をたかめる

10章 「クラス」

クラスの構成

カプセル化

  • テスト可能にするためにprotectedとする場合もある
  • 筆者らはテストを優先する
  • まずはカプセル化を考え、緩めるのは常に最後の手段

クラスは小さくしなければならない

単一責務の原則

Single Responsibilty Principle, SRP

  • クラス、モジュールは変更の原因となるものが1つでなければならない
  • 理解が容易で守るのが簡単な概念であるが、最も無視されがち
  • 多くのエンジニアは、小さなクラスがあふれかえることで全体像を見失うことを危惧
  • しかし、小さなクラスの集まりとして構成されたシステムというのは、大きな少数のクラスで構成されたシステムよりも可動部分が少ない
  • 大きなシステムの複雑さに対処するのに必要なのは、開発者がいつでも直接理解しなければならない箇所を容易に探し出せるように全体を構成するということ。大きなクラスではできない。

凝集性

  • 関数を小さくし、引数リストを短くするという鉄則を守ると、あるメソッド群で使用されるインスタンス変数の急増につながることがある
  • このような場合には、ほとんどの場合、その大きめのクラスから別のクラスを最低1つ分離することが可能であることを意味している

凝集性に気を配ると、大量の小さなクラスが生まれる

CleanCode/src/clean/code/chapter10/original/PrintPrimes.java at master · ludwiggj/CleanCode
Code samples taken from CleanCode book. Contribute to ludwiggj/CleanCode development by creating an account on GitHub.

これが、こうなる

https://github.com/ludwiggj/CleanCode/blob/master/src/clean/code/chapter10/refactored/PrimePrinter.java
https://github.com/ludwiggj/CleanCode/blob/master/src/clean/code/chapter10/refactored/PrimeGenerator.java
https://github.com/ludwiggj/CleanCode/blob/master/src/clean/code/chapter10/refactored/RowColumnPagePrinter.java

長くなる理由

  • 表現豊かな変数名を使用していること
  • コードへの解説を追加するために、関数とクラスの宣言を利用していること
  • ソースが見やすいようスペースの追加と書式化の技法を用いていること
  • メインプログラム
    • 実行環境を扱うことが責務
  • RowColumnPagePrinter
    • 数のリストを定められた表形式のフォーマットとしてページに出力するための知識が集約
  • PrimeGenerator
    • 素数の生成を司る
    • オブジェクトの生成が不要なことがわかる

これらの変更は、最初のプログラムの挙動を確認するテストスイートを書くことで可能となり、これにより同時に無数の小さいな変更を入れることが可能となった。

変更のために最適化する

  • 洗練されたシステムでは、クラスは、変更に対するリスクが最小限となるよう構成される

SQL文字列を生成するクラスの例

CleanCode/src/clean/code/chapter10/original/Sql.java at master · ludwiggj/CleanCode
Code samples taken from CleanCode book. Contribute to ludwiggj/CleanCode development by creating an account on GitHub.
  • 変更の理由が2つ存在し、SRPに違反している
  • 新しいタイプのSQL文を追加したい場合
  • 1つのSQL文タイプの詳細を変える場合
CleanCode/src/clean/code/chapter10/refactored/Sql.java at master · ludwiggj/CleanCode
Code samples taken from CleanCode book. Contribute to ludwiggj/CleanCode development by creating an account on GitHub.

リファクタ後は、SRPに従い、OCPにも従っている。

開放/閉鎖原則 (Open Closed Principle, OCP)

  • クラスは拡張に対して開かれており、変更に対して閉じていなければならない

新しいSqlクラスは、サブクラス作成による新たな機能の追加に対して開かれているが、既存のクラスを閉じたまま追加することができる。

このように、新規機能が既存システムの拡張のみで実現され、既存コードの変更が皆無であることが理想。

変更から切り離す

直接実装クラスに依存させず、インターフェイスを介す例。システムがテスト可能なように切り離されていれば、柔軟性が高まり、再利用がより簡単にできる。

このように結合を最小化することで、もう一つのクラス設計原則である、依存関係逆転の原則に沿ったものとなる

依存関係逆転の原則 (Dependency Inversion Principle, DIP)

  • クラスは抽象層にのみ依存すべきで、詳細な具象層に依存すべきでない

コメント

タイトルとURLをコピーしました