Clean Architecture
Clean Architecture
依存関係逆転を利用することで、オブジェクト指向で記述されたシステムでは、すべてのソースコードの依存関係の方向を"絶対的に制御"出来る。これはパワーだ!
オブジェクト指向とは、"ポリモーフィズムを使用することで、システムのすべてのソースコードの依存関係を絶対的に制御する能力"である。
"関数型言語の変数は変化しない" なぜこれが重要か?競合、デッドロック、並行更新の問題の原因すべてが可変変数にあるからだ。
イベントソーシングとは、状態ではなく、取引(トランザクション)を保存する戦略。十分な処理能力と記憶容量があれば、状態を記録知る必要はなく、取引を計算すればよい。
SOLID原則
単一責任の原則(SRP Single Resposibility Principle)
モジュールはたったひとつのアクターに対して責務を負うべきである。
オープン・クローズドの原則(Open-Closed Principle)
"ソフトウェアの構成要素は拡張に対しては開いていて、修正に対しては閉じていなければならない" 既存の成果物を変更せずに拡張出来るようにすべき
LSP(リスコフの置換原則)
インターフェースに対する実装型を置き換えても振る舞いがかわらないこと。インターフェースと実装についての設計原則。RectangleをSquire で実装したとき、辺の長さを独立して変更できなく例は、この原則に違反している
ISP(インターフェース分離の原則)
DIP(依存関係逆転の原則):ソースコードが抽象だけを参照している依存関係が最も柔軟。具象に依存すべきでない。ただ絶対のルールとするのは非現実的。変化しないと見なせる具象は許容。
インターフェースの変更をできるだけおさえるのは、ソフトウェア設計の基本。
- 変化しやすい具象を参照しない→Abstract Factoryパターンを使うしかない。
- 変化しやすい具象を継承しない
- 具象関数をオーバーライドしない→元の関数を抽象にし、複数の実装を用意
- 変化しやすい具象を名指しで指定しない
コンポーネント
コンポーネントプラグインアーキテクチャ
コンポーネントとは、最小限のデプロイの単位。jar,DLLなど。これまでの50年、大変な労力をかけて、動的にリンクされたファイルをアプリケーションの実行時にプラグインできるようになった。
コンポーネントの凝集性
再利用・リリース等価の原則(REP)
リリース番号がなければ互換性を確認できない。コンポーネントには一貫するテーマや目的がありそれを共有するモジュールを集めなければいけない。そしてまとめてリリース可能でなければいけない。
閉鎖性共通の原則(CPP)
コンポーネントを変更する理由が複数あるべきではない。多くのアプリケーションにおいて、再利用性よりも保守性の方が重要。同じタイミングで変更されることが多いクラスは一つにまとめておく。
全再利用の原則(CRP)
コンポーネントのユーザーに使わないものへの依存を強要してはならない。一つのコンポーネントにまとめるクラスは切り離せないものばかりにしておく。 密結合していないクラスを同じコンポーネントにまとめるべきではない。
3つの原則には相反するところがある。バランスをうまくとるのがアーキテクトのうでの見せ所。開発チームの現在の懸念事項に見あったおとしどころを見つける。時間がたてば懸念事項も変化する。
コンポーネントの結合
非循環依存関係の原則(ADP)
開発環境をリリース可能なコンポーネントに分割し担当を割り当てる。機能させるには、依存構造をきちんと管理する必要がある循環依存はあってはならない。有向非循環グラフとなる。
トップダウンの設計
これまでの議論から、コンポーネントの構造をトップダウンで設計するのは不可能 コンポーネント図に機能を書くことはほとんどない。ビルド可能性や保守性を見る地図のようなもの。プロジェクト開始時にコンポーネント図は作らない。システム論理設計にあわせて育てていくもの
安定依存の原則(SDP)
安定度の高い方向に依存すること。多数のコンポーネントから依存されている場合、変更において多くの調整が必要となるため、非常に安定しているといえる。
安定度・抽象度等価の原則(SAP)
安定度の高いコンポーネントは抽象度も高くあるべき。抽象度が高くなる方向へ依存すべき。
安定度が最大の具象クラスは、苦悩ゾーンに属しており、柔軟性に欠けるため望ましくない。ただし、Stringなど変動性が低ければ害はない。 最大限に抽象化されているが、依存されていないコンポーネントは無駄ゾーンに属する。 変動性が高いコンポーネントをこれらに属させるのを避ける。
アーキテクチャ
ソフトウェアアーキテクトはプログラマだ。プログラマを続けていなければならない。ソフトウェアアーキテクトはコードを書かず、より高い問題にフォーカスするものなどというウソを信じてはだめだ。
アーキテクチャは構築した人が、システムをコンポーネントに分割、配置して相互に通信できるように与えた形状。目的は、開発、デプロイ、運用、保守を容易にすること。戦略はできるだけ長い期間、できるだけ多くの選択肢を残すこと。
アーキテクチャの主目的はシステムのライフタイムサイクルのサポート、ライフタイムコストを最小限に抑え、プログラマの生産性を最大化する。
ソフトウェアをソフトに保つには、長い期間できるだけ多くの重要でない詳細の選択肢を残す。例えば開発の初期で、DBMS、ウェブサーバー、RESTの採用、DIフレームワークの導入を決定する必要はない。 決定を遅延できれば、適切に作るための情報が多く手に入る。
独立性
ユースケース:アーキテクチャは、システムの意図をサポートしなければいけない。
運用
アーキテクチャは運用において本質的な役割を果たす。
開発
アーキテクチャは開発環境のサポートにおいて非常に重要な役割を果たす。システムを設計する組織は、組織のコミュニケーション構造をコピーした構造の設計を生み出すという、コンウェイの法則が作用する。 =====デプロイ=====アーキテクチャは、デプロイの手軽さの決定にも大きな役割を果たす。即時デプロイを目指すべき
選択肢を残しておく 現実世界では目指す目標は不明瞭で一貫性がない。優れたアーキテクチャがあれば、選択肢を残すことでシステム変更が容易になる。 レイヤーの切り離し アーキテクトは、システムの意図を考慮しながら、異なる理由で変更されるものを分離し、同じ理由で変更されるものをまとめることができる。システムは切り離された水平レイヤー(UI、ビジネスルール、データベースなど)で分離されている。
バウンダリー
境界線を引く ソフトウェアを分離し境界線を引く(バウンダリー)ことでお互いのことがわからないように制限する技芸がソフトウェアアーキテクチャである。び 初期に境界線を引くのは、決定によりビジネスロジックが汚染されないよう、決定を遅らせるため。ビジネス要件に関係ない事項(FW,DB,DI...)の、早すぎる決定と結合は、開発・維持工数を増大させる。
境界線は重要なものとそうでないものの間に引く GUI、ビジネスルール、データベースはそれぞれにとって重要ではないので、間に境界線を引く。 システムをプラグインアーキテクチャにしておくと、変更の影響を伝播させないファイアーウォールを構築できる。
境界の解剖学
© 2006 矢木浩人