📝

技術書読書ログ「ちょうぜつソフトウェア設計入門」

2023/02/18に公開

個人的に重要だと思ったところ

サマリ

  • クリーンアーキテクチャは、変更に強いソフトウェアを作るための、層の分け方のアイディア・考え方を教えてくれるもの
  • オブジェクト指向は開発しやすいソフトウェアづくりに役立てることに値打ちがあり、クリーンアーキテクチャを実践するのにも有用な道具

クリーンアーキテクチャ

アーキテクチャの設計は動作ではなくひとのためのもの。ソフトウェアを開発するパフォーマンスを向上させたり、自分や仲間がちゃんと動くプログラムを書き続けるのに役立つもの。

  • ソフトウェア開発のパフォーマンスを向上させ、開発し続けるのに重要になってくるのが変化への対応のしやすさ
  • 変化に対応しやするには「できるだけ変更頻度の高い事情に依存しない」という安定度が重要
  • クリーンアーキテクチャはその安定度の重要性に着目した、ソフトウェアの層の分け方のアイディア・考え方
    • フレームワークでもなければ盲目的に従えばいい設計の答えでもない
    • 具体的にどこに何を配置するかは、それぞれのソフトウェアごとに考えて決めていく必要がある

代表的な層の分け方(必ずこの通りにするものではない)

  • ドメイン : 現実の事実を写し出したもの
    • 標準ライブラリ以外に依存しない
    • ユーザーの要望で変わるものはここに含めず、アプリケーションのもっとも本質的で不変なモノ・コトだけ
  • ユースケース : 人(ユーザー)が行いたい操作を表現したもの
    • ユーザーの要望で変更されるが、技術的な理由で変更されることはない
    • アプリケーションの仕様(ユースケース)と本質(ドメイン)を分離する
  • インタフェースアダプター : いわゆるコントローラ
    • ユースケースを参照して、入力から出力までのコンピュータの制御の流れを、技術的な概念コードで表現
    • ユースケースの表現に適したデータや語彙を、コンピューターが扱うのに適した形に言い換える
  • インフラストラクチャ : 自身のソフトウェアと外部のソフトウェアの両方に依存する橋渡しの部分
    • 実際の入出力の詳細や画面との繋ぎ込み等の、具体的で詳細な技術的問題の解決
    • 横の繋がりがなく、独立したモジュール群にする

クリーンアーキテクチャの中心にあるドメインモデルは、アプリケーション固有であると同時に再利用性も高く、同じプロジェクト内で再利用できるもの

  • 再利用性を高めるのに重要な大原則が、再利用・リリース等価の原則(REP:Reuse-Release Equivalent Principle)
    • リリースされたものだけを再利用し、再利用させたければリリースする(開発中のものは再利用しない)
    • 再利用・リリース等価の原則」を満たすヒントになる原則が「全再利用の原則」と「閉鎖性共通の原則」
  • 「全再利用の原則」(CRP:Common Reuse Principle)
    • パッケージ内に含まれるものは全て一度に再利用されるようにして、パッケージに変更があったら、その利用者は、全て利用するか、全く利用しないか、のどちらかを選ぶしかできなくする
  • 「閉鎖性共通の原則」(CCP:Common Closure Principle)
    • 一度に再利用されるものはひとつのパッケージにまとまっていて、変更が必要な時は1つのパッケージだけを交換すれば済む形にする

複数パッケージを扱う際のTIPS

  • 循環依存は避け、どうしても循環の依存が必要な場合は同じパッケージ内に閉じ込める(ADP)
  • パッケージの安定度と抽象度は相関関係がある(SAP)
    • ここでの抽象度は抽象クラスのことだけを意味せず、以下も含まれる
      • 詳細を持たないものだけに依存するロジック
      • 固有の業務にも特定技術にも関係しない時刻や配列などの汎用概念とその操作
      • プログラミング言語そのものや言語標準ライブラリと、それらと同等の業界標準

オブジェクト指向

抽象(安定度)を意識したプログラミングを実践するのに役立つのがオブジェクト指向。より良いパッケージング、ひいてはより開発しやすいソフトウェアづくりに役立てることに値打ちがある道具。単独で価値を持つパラダイムではない。

基礎となる考え方は以下

  • カプセル化
    • 関心を分離する境界線として非常に重要
    • デメテルの法則は、カプセルから知識を掘り出さないことが本質、メソッドチェーンが一概に悪というわけではない
  • 多態性(ポリモーフィズム)
    • 代表格はプラグイン
    • 多態性と型システムは独立した概念で、多態性は本質的に型の存在には依存しない
  • 継承
    • 一概に悪ではなく、基底クラスのほうに汎用的な意味づけをする目的で使うのであれば問題ない
    • 差分プログラミングだけを目的として使うのは良くない、それをしたいならtraitのような機能を使った方がいい

オブジェクト指向に関するTIPS

  • 派生クラスは基底クラスにはない事前条件を加えてはいけないし、基底クラスが持っていた事後条件を追加するのもNG(LSP)
  • 具象一つに複数の抽象になることもある、データの実体と概念を1対1で考えてはいけない、実体と利用とで関心をわけて考える(ISP)
  • インタフェースはパッケージ間の接合部として用意するのが有効
    • DIPができるようになるので、たとえその具象が1つしかなくても意味がある
    • パッケージ内のやりとりに関してはわざわざインタフェースを分ける必要はない

その他

  • TDDは振る舞いをテストする以上に、設計のメカニズムを自信を持って作っていくのに役立つ設計の技法
    • クラスとテストケースが一対一に対応するのが良い設計の指針
    • 単一パッケージ内のクラス間の依存は直接依存でテストし、異なるパッケージのクラスと使う時はモックやスタブを使うといい
  • DIの目的は使用と生成の分離であって、「単体テストを書きやすくする」は自体が目的ではない
    • 使用と生成の分離には、シンプル、拡張性、独立性、柔軟性、など様々なメリットがある
  • DDDはあくまでプロセス手法
    • テスト・実装・設計・分析・要件定義の活動をすべて同じフェーズで行ってドメインモデルを洗練させる
    • ユーザーには、作って欲しいものを直接聞くわけではなく、問題をあるがまま話してもらい、どのように解決するか開発者が決める

感想

クリーンアーキテクチャや各原則の説明が、今まで見た本や記事の中で一番分かりやすくて腹落ちするところが多かった。特に今までクリーンアーキテクチャのドメイン(エンティティ)とユースケースの違いが良く分かっていなかったのが、ユーザーの要望で変わるものかどうかという説明で「そういうことか」と思えたし、確かに仕様的なことも含めないんであれば最内は安定するよなと納得いった。となるとDDDでいうところのドメインはクリーンアーキテクチャでのドメイン(エンティティ)とユースケースを一緒にしているのかな。

TDDの章も面白かった。頭の中にある設計を試してみたり、洗練させるために使っていて、今まで自分が参考にしてきた本や記事にはない考え方なのが興味深かった。

理解しやすく読みやすい内容の割に仕事でも試したい知識やTIPSも多くあり、そして読み物としても面白く、総じて良い本でした。

Discussion