「Clean Architecture 達人に学ぶソフトウェアの構造と設計」[2018, Robert C.Martin]を読みました.
感想
設計の本の名著の一つです.
アーキテクチャによって,プロジェクトが肥大化しても,運用コストを抑えることができることを筆者は述べており,
アーキテクチャのルールはどれも同じである ソフトウェアアーキテクチャのルールはその他すべての変数から独立している 時代が進んでもやることはかわっていない.だからアーキテクチャの有効性もかわていない 時代を超越した不変のルールたち.それこそが本書のすべて
という条文から本書は始まります.
「Clean Architecture」というタイトルから,手を動かしながら,学ぶ本だと思っていましたが.筆者の体験談から裏打ちされる,設計のあり方について述べていきます.
結構設計になれていないと難解な本だと思いました.(自分は難しくて途中から斜め読みしていました.)
実際に設計の面においてつまづいたりや改善したりした経験がなければ難しい内容が多かったです.
それでも,有名な円の図(内部は外部のことをしらない,依存していない)や,依存関係が単一方向になるようにする原則は,今後の多くの場合において役立ちそうなので,つかっていきたいと思います.
概要
SOLID 原則
SOLID 原則の目的は,以下のような性質を持つ中間レベルのソフトウェア構造を作ること
- 変更に強いこと
- 理解しやすいこと
- コンポーネントの基盤として,多くのソフトウェアシステムで利用できること
SOLID 原則一覧
- 単一責任の原則(SRP: Single Responsibility Principle)
- ソフトウェアシステムの構造がそれを使う組織の社会的構造に大きな影響をうけるようにする
- オープン・クローズドの原則(OCP: Open-Cloesed Principle)
- ソフトウェアを変更しやすくするために,既存のコードの変更よりも新しいコードの追加によって,システムの振る舞いを変更できるようにする.
- リスコフの置換原則(LSP: Liskov Substituion Principle)
- 個々のパーツが交換可能になる
- インターフェース分離の原則(ISP: Interface Segregation Principle)
- 使っていないものへの依存を回避すべきだという原則
- 依存関係逆転の原則(DIP: Dependency Inversion Principle)
- 上位レベルの方針の実装コードは,下位レベルの詳細の実装コードに依存すべきではなく,逆に詳細側が方針に依存するべきだという原則
コンポーネントの原則
コンポーネントとは,デプロイの単位.システムの一部としてデプロイできる,最小限のまとまり.
コンポーネント凝集時の原則
- 再利用・リリース等価の原則(REP)
- 再利用性のためのグループ化
- 閉鎖性共通の原則(CCP)
- 保守性のためのグループ化
- 全再利用の原則(CRP)
- 不要なリリース作業を減らすための分割
この3つはトレードオフの関係になっている.
凝集性は「ひとつのモジュールはひとつだけの機能を持っている」という属性ではなくなっている.
最適なバランスを考える必要がある.
「二日酔い症候群」(非循環依存関係の原則(ADP))と呼ばれる,他人がデプロイしたために次の日には動かなくなる現象がある.
アーキテクチャ
ソフトウェアアーキテクトはプログラマである.プログラムを続けておかなければいけない.
コードを書かないというのはデマである.
アーキテクチャの形状の目的は,そこに含まれるソフトウェアシステムの開発・デプロイ・運用・保守を用意にすること.
それらを用意にするための戦略は,できるだけ長い期間,できるだけ多く選択肢を残すこと
- 開発
- 開発が難しいソフトウェアシステムは,ライフタイムが長くて健全である可能性が低い.だからこそ,システムのアーキテクチャによって,開発チームが開発しやすくなるようなシステムにするべき
- デプロイ
- システムを単一のアクションで簡単にデプロイできるようにする
- 運用
- アーキテクチャが運用方法を明らかにする
- 保守
選択肢を残しておく
「残すべき選択肢」とは,重要ではない詳細
アーキテクトの目的は,方針とは無関係に詳細を決めながら,方針をシステムの最も重要な要素と認識するシステムの形状を作ること
優れたアーキテクチャは以下のことをサポートする
- システムのユースケース
- システムの運用
- システムの開発
- システムのデプロイ
ソフトウェアアーキテクチャとは境界線を引く技芸である.(著者はバウンダリーと呼ぶ)
ソフトウェアの要素を分離し,お互いのことがわからないように制限するものである.
初期に境界線を引くのは,決定をできるだけ遅らせるためである.
結合は,アーキテクトによる,システムを構築し維持するためのパワーを奪う. 早すぎる結合は,フレームワーク,データベース,ウェブサーバー,ユーティリティライブラリ,DI などのビジネス要件に関係ない決定のことを言う
過去のアーキテクチャは,「関心事の分離」という同じ目的を持っている
それらのアーキテクチャは,以下の特性を持つシステムを生み出す
- フレームワーク非依存
- テスト可能
- UI 非依存
- データベース非依存
- 外部エージェント非依存
アーキテクチャを動作させる最も重要なルールは依存性のルール
ソースコードの依存性は,内側(上位レベルの方針)だけに向かっていなければならい
- エンティティは,企業全体の最重要ビジネスルールをカプセル化したもの
- 外部で何か変化がおきても,それが変化する可能性は低い
- ユースケースは,アプリケーション固有のビジネスルールが含まれている
- レイヤーの変更がエンティティに影響を与えることはない
- インターフェースアダプター.ユースケースに便利なフォーマットから,データベースやウェブなどの外部エージェントに便利なフォーマットにデータを変換するアダプター
- エンティティとユースケースは,これを何もしらない
- フレームワークとドライバ
- データベースやウェブフレームワークなど
詳細
データの構造であるデータモデルは,アーキテクチャ的には重要である.
データを移動させる技術やシステムは,アーキテクチャ的には重要ではない.
データこそが重要でありデータベースは詳細である.
フレームワークのリスク
- フレームワークのアーキテクチャに難があることが少ない宮内.一般に,フレームワークは依存性のルールに違反する傾向がある.
- アプリケーションを作り始めた頃は,フレームワークが助けになるが,プロダクトが成長するにつれて,フレームワークの提供する機能では手に負えなくなってくる
- フレームワークの進化する方向が,望む道からずれるかもしれない.
- 優れたフレームワークを見つけたときに,乗り換えたくなる
解決策は,フレームワークと結婚してはいけない