田中ひさてるさんの『ちょうぜつソフトウェア設計入門――PHPで理解するオブジェクト指向の活用』が話題になっていたので読んでみた。

全体を通して平易な日本語で書かれていたのとコード例が豊富だったので理解しやすくてよかった。

以下学びを簡単にまとめていく。

第2章 パッケージ原則

より変更に強いパッケージ設計にするために注意すべき点として

  • パッケージの凝集性を高める
  • より安定度が高い(=抽象度が高い)パッケージに依存する

などがある。

また、凝集性の低さを表すシグナルとしてそのパッケージが変更される理由が複数あること1つの変更の際に変更対象となるパッケージが複数あること(それぞれ同じ?)が挙げられる。

「抽象」については以下のように説明されていた。

  • 抽象クラスやインターフェイスなど実装詳細を自身から排除したもの
  • 上記のような詳細を持たないものだけに依存するロジック
  • 固有の業務にも特定技術にも関係しない時刻や配列などの汎用概念とその操作
  • プログラミング言語そのものや言語標準ライブラリと同等レベルの業界標準

第3章 オブジェクト指向

いい抽象を見つけるには

具体的な例を分析してそれらから抽象を見つけることで期待値の高い抽象を発見できる。

逆に先にひとりよがりの哲学をこねくり回して現実をかえりみない抽象化を先行させた場合は、役に立たない概念に縛られる無駄が起きやすくなる。(ペットショップのシステムなのに「Catには野良猫もいるかもしれない。必ずしもPetではないかも……」みたいなことを考えてしまうのは明らかに無駄)(抽象化においてもYAGNIが重要っぽい)

無限の可能性に向かって発散してしまわず、いかに可能性を削ぎ落として最小サイズで実際に起こりうるバリエーションをカバーできるかが汎化のポイント。

そういう意味でもドメインやビジネスの状況を理解しておくことはプロダクトの将来を考慮しながら設計するために必要なんだろうなと思った。

「多」態性がなくても役立つ

抽象と具象は必ずしも1対多の関係である必要はない。

具象と抽象に分けておくことで先に大枠を安定させることができるため、設計の見通しがつきやすくなる。

また、具象の数が複数になったときに対応しやすいというメリットもある。

これまで「抽象と具象が1対1対応なケースはわざわざDIする必要はないのでは」と思っていたが上記のメリットがあるので積極的にDIしていこうと思った。

第5章 オブジェクト指向原則 SOLID

5-2 単一責任原則(Single Responsibility Principle(SRP))

クラスと責務は1対1対応すべき、という指針。

単一の責務のみつけかた

クラスの利用者がどんなときに別のクラスや新しいバージョンに交換したいと思うかを想像する。

実際に起こりそうな交換要求への想像が責務(= クラスのカバー範囲)を見極めるヒントになる。

たとえば記事クラスが存在し記事の入稿および購読というユースケースがある例では以下のように考えることができる。

ニュース記事を書く人の事情が変わったけれど、購読ユーザーには従来どおりのサービスを提供したい。逆に、入稿はそのまま、購読ユーザーへのサービスを拡張したい。そんなニーズが起きるのは容易に想像できます。入稿と購読のそれぞれを互いに影響を与えない独立したクラスとしておき、いつでも気兼ねなく別の実装に交換できる単位としておく方が、後で便利に決まっています。なので、ニュース記事管理の場合は、「入稿」と「購読」が、それぞれひとつの責務になります。

5-3 開放閉鎖原則(Open Close Principle)

拡張に対してオープン、変更にたいしてクローズドであるべき、という指針。

これは書籍内で紹介されていたコード例がわかりやすかった。

あとはどこが変化する仕様なのかを考えるために一度要件を抽象化してみる方法が紹介されていた。こちらもコード例が示されていたのでイメージが湧きやすかった。

第7章 依存性注入

オブジェクトが使う機能の実体を得る際その解決を自力で行わず、常に外部から与えるようにすべき、という設計方針。

依存性注入を行うメリットの1つは生成の責務と使用の責務を分けられる点がある。

また、テスト容易性とDIについては以下のような記述があった。

単体テストしやすいクラスであることと、DI可能なクラスであるということには、正の相関があります。DIを単に「単体テストのためにやること」といった目的観で考えるのは視野狭窄ではあるのですが、単体テストがアーキテクチャへの気づきの手段として、とても有用なのは間違いありません。

テストが書きずらかったら設計を疑ってみるのも1つの手かもしれない。

まとめ

よく聞くSOLID原則もやっとちゃんと理解できたし依存性注入に対する理解も深まったので今後に活かしていきたい。