「ソフトウェアアーキテクチャの基礎」読書メモ
はじめに
「ソフトウェアアーキテクチャの基礎」の読書メモ等を残していく
1日1章ずつ
1章
メモ
-
ソフトウェアアーキテクチャ = 「システムの構造」+ 「アーキテクチャ特性」 + 「アーキテクチャ決定」+ 「設計指針」
- 「システムの構造」
- アーキテクチャスタイルの種類のこと
- マイクロサービスアーキテクチャ、レイヤードアーキテクチャ、マイクロカーネルアーキテクチャなどといったものはシステムの構造に属する
- 「アーキテクチャ特性」
- システムがサポートするべき〜ilityを表す
- 可用性(Availability)、信頼性(Reliability)、耐障害性(Fault tolerance)など
- 「アーキテクチャ決定」
- システム構築の際のルール
- 何が許されて何が許されないかを定め開発チームの指針とする
- 例)プレゼンテーション層からデータベース層にはアクセスできない。〇〇層からのみアクセスできる
- 「設計指針」
- ガイドラインであり、「アーキテクチャ決定」ほど厳格なルールではない
- あくまでも技術選定などの際のガイドラインとなるようにする
- 「システムの構造」
-
アーキテクトの仕事は色々あるが、常にその時その時に最適なアーキテクチャとなるか分析し続けるのが必要
-
ソフトウェアアーキテクチャの法則
- ソフトウェアアーキテクチャはトレードオフがすべて
- howよりwhyが大事
追加で調べたこと
「システムの構造」の1つであるマイクロカーネルアーキテクチャってなんだっけ?
→ 別名プラグインアーキテクチャ。システムを動かすために必要な最低限のコア部分とそれ自体が独立したプラグインの2段でシステムを構築する。ドメインを持ったプラグインの拡充により、変更に耐えつつテストしやすくいい感じにシステムを拡張できる。
参考)https://minegishirei.hatenablog.com/entry/2023/01/28/110836
第2章
メモ
- アーキテクトは技術の深さよりも技術の幅のほうが大事
- アーキテクトはビジネスドライバー、環境など取り巻くものを考慮しつつトレードオフを分析する
- アーキテクトは、クリティカルパスにならないようなコーディングタスクをするべき。レビューも良し。開発がアーキテクチャに準拠しているかを追える。
第3章
メモ
モジュール
- より複雑な構造を構築するために使用できる、標準化された部品 / 独立した単位の各集合
- 関連するコードのグループ化
- 各言語ごとにモジュールを表現するための仕組みがある(パッケージ、クラス、関数など)
モジュール性の計測
凝集度
- 関連する要素がどれだけ1つのモジュールにまとまってるか。モジュール内の要素同士の関連度
- 高いほうが基本的にいい
- 詳しくは以下記事
結合度
- あるモジュールがどれだけ他のモジュールとくっついてるか
- 低結合が基本的には良い
- 詳しくは以下記事
コナーセンス
- 求心性と遠心性の結合メトリクスの改良
- システム全体の整合性を保つため、あるコンポーネントの変更が別のコンポーネントの変更を必要とする場合、それらのコンポーネントはコナーセント(接続)されている
- 静的コナーセンス
- コードレベルでの結合のこと
- 動的なコナーセンス
- 実行時の呼び出しを分析するもの
- 動的コナーセンスよりも静的コナーセンスのほうがよい。コナーセンスの強さを弱くするようにリファクタする
- 詳しくは以下記事
第4章
メモ
アーキテクチャ特性が満たす基準
- ドメインに依らない、設計で考慮しないといけないことを明らかにするもの
- アプリケーションが成功するために必要な運用と設計の基準を明らかにする
- 設計の構造に影響を与えるもの
- 「このアーキテクチャ特性を満たすには特別な設計上の配慮はいるだろうか?」
- アプリケーションの成功に必要不可欠なもの
- いっぱいアーキテクチャ特性をサポートすると負債になりかねないので、必要なものだけpickするべき
仕様書に書かれる「明確なアーキテクチャ特性」と、「セキュリティ」とか「可用性」とか「信頼性」みたいに「暗黙的なアーキテクチャ特性」がある
アーキテクチャ特性をいくつかリストアップ
アーキテクチャ特性は、ソフトウェアのエコシステムの移り変わりと共に変わるので、普遍的な標準はないので、各々の解釈に任せられる。
とはいえ、ある程度の分類わけは可能
アーキテクチャの運用特性
ソフトウェアの運用上での考慮事項
- 可用性
- 継続性
- パフォーマンス
- 回復性
- どれくらい持続的か(障害時にどのくらいすぐに復旧できるか)
- バックアップ戦略に影響
- どれくらい持続的か(障害時にどのくらいすぐに復旧できるか)
- 信頼性
- フェイルセーフである必要あるか
- 堅牢性
- インターネットとの接続きれたり停電おきても大丈夫?
- スケーラビリティ
アーキテクチャの構造的特性
コードの構造上の考慮事項
- 構成容易性
- ユーザーがソフトウェアの設定簡単に変えられるか
- 拡張性
- プラグインでの機能追加をどのくらい重視するか
- インストール容易性
- 再利用性
- ローカライゼーション
- メンテ容易性
- 可搬性
- 複数のプラットフォームで動作する必要あるのか
- アップグレード容易性
アーキテクチャの横断的特性
運用特性とか構造的特性に分類できないけど大事な特性
- アクセシビリティ
- すべてのユーザーにとって使いやすいか
- 長期保存性
- データは一定期間後にアーカイブor削除される必要あるのか
- 認証
- 認可
- 合法性
- プライバシー
- 従業員や開発者からもちゃんとデータを暗号化なりで隠せるか
- セキュリティ
- サポート容易性
- アプリケーションにはどのくらい技術サポートがいるのか
- システムのデバッグとかのためにどのくらいログ必要か
- ユーザービリティ
- ユーザーが目標達成するために必要なトレーニングのレベル
結局のところ、不明瞭だったり意味的に一部ダブってたりする部分もあったりする。明確な基準がないため。
また、アーキテクチャ特性は相互に影響を与えあう(=トレードオフ)
- 例)セキュリティを重視すると、パフォーマンスが落ちるとか
多くのアーキテクチャ特性を満たす最強のアーキテクチャを目指すと扱いにくくなるので、「少なくとも最悪ではないアーキテクチャ」を目指すべき
第5章
メモ
- アーキテクトはドメインの関心事を、アーキテクチャ特性(ility)に変換する必要がある
-
すべてのアーキテクチャ特性を満たす汎用アーキテクチャはアンチパターンで、シンプルに保つべき
- そもそも各特性はトレードオフなので、全部満たすのはきついし、色々満たそうとするとひたすらにシステムが複雑になる
- 複数のアーキテクチャ特性への影響を考えながら、どのアーキテクチャ特性にフォーカスするかを決めていく
- そもそも各特性はトレードオフなので、全部満たすのはきついし、色々満たそうとするとひたすらにシステムが複雑になる
- アーキテクトはドメインのステークホルダーと意見交換をしながらアーキテクチャ特性を決めるべき
- それぞれが取り扱う言葉は違うので、必ずしも1:1でアーキテクチャ特性とドメインの関心ごとがマッピングできるわけではない
- なので、ドメインの関心ごとを満たすために必要なアーキテクチャ特性が何なのかを考えるときに、1つにフォーカスしすぎてはいけない
- それぞれが取り扱う言葉は違うので、必ずしも1:1でアーキテクチャ特性とドメインの関心ごとがマッピングできるわけではない
- アーキテクトが考慮しないといけないことの多くは、要件に明文化されておらず、問題領域の中の暗黙の知識で表現されることが多い
- そして、重要なアーキテクチャ特性を抽出する際に、結果として重視されるのは暗黙的な特性に基づくアーキテクチャ特性(可用性とか信頼性)であることが多い。
- 設計とアーキテクチャのトレードオフ
- アーキテクチャとは何らかの構造要素を示し、設計はアーキテクチャの中に存在する
- アーキテクチャ(= アーキテクチャ特性)として重視して担保するか、設計で担保するか。
- アーキテクチャがよりマクロ的な構造スタイルのイメージ、設計はより実装に近いレベルのスタイルと解釈した
- 例えば、なにかをカスタマイズできるシステムである必要がありとする。カスタマイズ性をアーキテクチャ特性として重視するとして、アーキテクチャレベルで、例えばマイクロカーネルアーキテクチャを採用し満たすこともあれば、アーキテクチャ特性としてのカスタマイズ性は重視せず別のアーキテクチャ特性をサポートするためのアーキテクチャを選び、設計にてテンプレートメソッドを使ってカスタマイズを実現するということもありうる。
- 開発者とかアーキテクトが一緒になってここらへんは決める必要がある
- そうしないと「象牙の塔のアーキテクトアンチパターン」に陥る
- アーキテクチャがよりマクロ的な構造スタイルのイメージ、設計はより実装に近いレベルのスタイルと解釈した
- 繰り返しになるが、最高のアーキテクチャなど存在せず、少なくとも最悪ではないトレードオフの集合がる
第6章
メモ
アーキテクト特性の計測
- 客観的な定義(組織全体として合意したもの)を持つことが大事
運用面の計測
- チームに適した計測を実施する
- 統計モデルを構築し、それに基づいて計測することもある
構造面の計測
- 内部コード品質のための包括的なメトリクスはない。
- とはいえ いくつか計測可能なものはある。
- 循環的複雑度
- コードの複雑度
- 循環的複雑度
統制
循環依存を避けるべき
- アーキテクトはモジュール性を維持し、循環依存を避けるために適応度関数を定義し、統制する。適応度関数を自動テストを使って実装することで、モジュール性を維持する
第7章
メモ
現代のシステムでは、システムレベルではなくアーキテクチャ量子レベルでアーキテクチャ特性を決める
アーキテクチャ量子が違う → アーキテクチャ特性が違うなら、モノリスではなく分散アーキテクチャを取ったほうがいい、というかそうするしかない
- モノリスだとアーキテクチャ特性を分けられない
アーキテクチャ量子
-
高度な機能的凝集性と同期的なコナーセンスを持つ、独立してデプロイ可能なアーティファクト
- 独立してデプロイ可能
- アプリケーションが独立して動くために必要なすべてのコンポーネントがアーキテクチャ量子には含まれる
- アプリケーションが動くためにDBが必要なら、DBもアーキテクチャ量子に含まれる
- アプリケーションが独立して動くために必要なすべてのコンポーネントがアーキテクチャ量子には含まれる
- 高度な機能的凝集性
- 含まれるコードがどれだけ目的に対して統一されているか
- アーキテクチャ量子は高い機能的凝集性をもち、何らかの目的を遂行する
- 同期的なコナーセンス
- コナーセンス
- システム全体の整合性を保つため、あるコンポーネントの変更が別のコンポーネントの変更を必要とする場合、それらのコンポーネントはコナーセント(接続)されている
- 第三章でもやったやつ
- アーキテクチャ量子を構成するサービス間の同期通信は、動的なコナーセンスを生み出す
- 動的なコナーセンスがあるもの同士は、運用特性が同じじゃないといけない。例えば片方がスケーラビリティ強すぎると、もう片方が追いつかず、信頼性に影響でたりする
- システム全体の整合性を保つため、あるコンポーネントの変更が別のコンポーネントの変更を必要とする場合、それらのコンポーネントはコナーセント(接続)されている
- コナーセンス
- 独立してデプロイ可能
第8章
メモ
- モジュール
- 関連するコードの集まり(論理的)
- コンポーネント
- モジュールが物理的にパッケージ化されたもの
- しばしば入れ子になる
- クラスや関数をラップしたもの
- ライブラリ
- 最も単純なコンポーネント
- 関連クラスや関数をラップしたもの
- コンパイル時の依存関係になり、呼び出しコードと同じアドレス空間で実行される
- モジュールが物理的にパッケージ化されたもの
アーキテクチャの最上位分割
- アーキテクチャパターンは「どのような種類の最上位分割をサポートしているか」という違いがある
最上位分割は、技術による分割
例)
- レイヤードアーキテクチャ
- プレゼンテーション、ビジネスルール、サービス、永続化のような技術の層
メリット
- コードの分類に応じて明確に分離している
- レイヤードアーキテクチャにいい感じに適合する
デメリット
- グローバルな結合度が高い
- 共通で使うようなものに変更を加えたときの影響範囲が大きい
- 複数のレイヤーでドメインの複製
- データレベルの結合度が高くなる
最上位分割は、ドメインによる分割
例)
- モジュラーモノリス
- 各モジュール内はもしかしたら、技術的なレイヤーを設けてることもあるかもしれないが、あくまでも最上位分割はドメイン
- マイクロサービスアーキテクチャ
メリット
- 実装の詳細ではなくビジネスに近い形でモデル化
- モジュラーモノリスとかマイクロサービスに適合する
- 分散アーキテクチャへの移行が楽
デメリット
- 特定の処理コードが複数箇所に現れる
コンポーネントの識別
コンポーネントとはイテレーティブに改善していくもの
初期コンポーネントを識別
- とりあえず最上位コンポーネントを定義し、ドメイン機能をマッピングしていく。この段階では良い設計じゃなくてOK(イテレーティブに改善していくので)
↓
コンポーネントと要件を照らし合わせて、コンポーネントの追加/統合/分割をする。
↓
コンポーネントの再構成
- 要件の中で明らかになったロールや責務にも目を向けてコンポーネントの粒度を一致させる
- アーキテクチャ特性がコンポーネントの分割や粒度にどんな影響を与えるかを確認
コンポーネント設計
エンティティの罠
- いくつかのエンティティを取り出して、そこにCRUDをくっつけただけの構成はアーキテクチャではなく、ORMなので、フレームワークでDBから自動生成したの使っとけばOK
- Railsのスキャフォールドとかで足りる
コンポーネントの見つけ方
-
アクター / アクションアプローチ
- アプリケーション上のアクターがどんなアクションするかで、コンポーネントを作る
- これで基本良さそう
- イベントストーミング
- マイクロサービス向け
- システムで発生するイベントと、そのメッセージハンドラを中身にコンポーネントを構成
- メッセージベースのシステム
- ワークフローアプローチ
- ロール* ワークフロー単位でコンポーネントを構成
- ただし、メッセージベースではない
追加で調べたこと
第9章
メモ
モノリシックアーキテクチャ
- 単一のデプロイメントユニット
種類 - レイヤードアーキテクチャ
- パイプラインアーキテクチャ
- マイクロカーネルアーキテクチャ
分散アーキテクチャ
- 分散したデプロイメントユニット
種類 - サービスベースアーキテクチャ
- イベント駆動アーキテクチャ
- マイクロサービスアーキテクチャ
メリット
- パフォーマンス、スケーラビリティ、可用性が高い
デメリット
- ネットワークが信頼できない
- 各サーバー自体には問題なくても、ネットワークがダメで信頼性がさがることがある
- レイテンシが無視できない
- モノリシックアーキテクチャ内のコンポーネント間通信だったらほぼ時間かからないが、分散アーキテクチャのノード間の通信はネットワークがからむので、レイテンシは無視できないよねと。
- 帯域幅の制限
- GraphQLとか、専用のRESTful APIを都度つくるとかしないと、オーバーフェッチングによりノード間のネットワークの帯域幅を圧迫する。
- しっかり最低限のデータ量の通信にするべき
- GraphQLとか、専用のRESTful APIを都度つくるとかしないと、オーバーフェッチングによりノード間のネットワークの帯域幅を圧迫する。
- しっかり防御しないとネットワークには不正リクエストが到達しうる
- ネットワークトポロジーが変化することがある
- ネットワークを構成するノード(ルーターとか)が変化しうる
- 分散してるぶん、管理者が多い
- ノード間の通信にも金がかかる
- ネットワークは均一ではない
- 色んな事業者が関わってるので
- ログがまとまらない
- ログの吐き出し先が1つになっても分散サービスではデバッグは普通にしんどい
- 分散トランザクション
- 結果整合性になってしまう
- 一定時間経った時点での整合性を担保とする
- つまり即時には整合性は取れない
- https://xtech.nikkei.com/atcl/nxt/column/18/01369/072700003/
- 結果整合性になってしまう
- サービス間で仕様や規格の合意を取ること
第10章
メモ
レイヤードアーキテクチャ
特徴
- アプリケーション内で特定の役割を果たすレイヤーから成る
- 大抵の場合、プレゼンテーション層、ビジネス層、永続化層、データベース層の4つからなる
- プロダクトの規模によって層の数は変わる
- 経験的にも永続化層は特に大事だなと思う
- 大抵の場合、プレゼンテーション層、ビジネス層、永続化層、データベース層の4つからなる
- 1つあたりのデプロイメントにどのレイヤーを含ませるかで、複数のトポロジーが存在する
- データベース層を外部に移すか、全部組み込みみたいに1つのデプロイメントに混ぜるかみたいな。
- ドメインによる分割ではなく、技術による分割である
- ので、ドメインは複数の層にまたがってしまう
- DDDとは相性が悪い
- 関心事の分離
- 1つ1つのレイヤーは、そのレイヤーに関係するロジックのみ扱う
- 開発者は全体的なアジリティが低下することの対価として、そのレイヤーの開発に技術的に集中できる
- 1つ1つのレイヤーは、そのレイヤーに関係するロジックのみ扱う
- 閉鎖レイヤー
- その層を経由しないとそれより下の層へはアクセスできない
- 層の分離への貢献
- そのレイヤーへの変更がほかのレイヤーに影響しない
- 開放レイヤー
- その層をスキップしてその層より下の層へアクセスしてもOK
- 直上の層がその層をスキップするか否かを選べる
- アンチパターン: アーキテクチャシンクホール
- レイヤーで特に何もせず次のレイヤーにリクエストをパススルーすること。
- デメリット
- 特に何もしないのでただメモリを消費してしまう
- 対策
- 間のレイヤーを開放レイヤーにする
- ただし、これはアーキテクチャが変更に弱くなることとのトレードオフ
- アーキテクチャシンクホールが全体の20%以下くらいにおさまってれば問題ない
- 間のレイヤーを開放レイヤーにする
レイヤードアーキテクチャをいつ採用するべきか
-
小規模なアプリケーションのとき
- 大規模になったらテストや保守、デプロイがしんどくなるので他のスタイルを検討するべき
- どのアーキテクチャスタイルを取ればいいかわからないとき
アーキテクチャ特性はどうか
- ただのモノリシックなのでシンプルでわかりやすくコストが低いが、規模がでかくなると辛い
- テスト容易性とデプロイ容易性が低い
- ちょびっとの変更で全体のデプロイが必要(= アーキテクチャ量子が1)
- レイヤーをモック化できるとはいえ、ちょびっとの変更でテストを全体回さないといけないので大規模になるとしんどい
- 信頼性は普通
- 分散アーキテクチャのようなネットワーク通信がないので、通信に起因する問題がおきない
- パフォーマンスやスケーラビリティは低い
- マルチスレッド処理化などで開発者が頑張らないと特定の機能をスケールできないし、結局アーキテクチャ量子が1なので限界はくる
- 耐障害性がない
- モノリスなので、何かのリソースが足りなくなったらアプリケーション全体が止まる
第11章
メモ
パイプラインアーキテクチャ
特徴
- パイプとフィルターからトポロジーがなりたつ
フィルター | フィルター | フィルター | フィルター | フィルター
- つまりドメインで分割されてないので技術による分割である
- パイプ
- フィルター間を一方向P2Pで通信するための通信チャネル
- フィルター
- ステートレスで、他のフィルターとは独立して1つのタスクを行う
- 複数の処理をしたいときは複数のフィルターを使うことになる
- 種類
- プロデューサー
- 処理の開始地点であり出力だけを行う
- トランスフォーマー
- データの変換
- テスター
- データのバリデーション、テスト
- コンシューマー
- 最終結果に対して何かする(DB保存するとか画面表示するとか)
- プロデューサー
- ETLツールなどに使われる
- 確かにEalstic StackのLogstashとかも確かパイプラインアーキテクチャのような感じだった気が
パイプラインアーキテクチャをいつ採用するべきか
- 一方通行の処理を行うタスク(アプリケーション)で使える
アーキテクチャ特性はどうか
- シンプルでわかりやすくコストが低い
- モノリシック
- アーキテクチャ量子は1
- 結局どこまでいってもモノリシックなので、レイヤードアーキテクチャ同様の辛みがでてくる
- テスト容易性とデプロイ容易性が低い
- フィルターをしっかりわければモジュール性が高くなり、テストしやすくはなる
- 分散アーキテクチャとは異なり、ネットワーク起因の信頼性低下はない
- パフォーマンスやスケーラビリティは低い
- 耐障害性はない
- テスト容易性とデプロイ容易性が低い
第12章
メモ
マイクロカーネルアーキテクチャ
特徴
- 別名) プラグインアーキテクチャ
- コアシステムとプラグインの2つのコンポーネントから成り立つ
- コアシステムをシンプルに、拡張はプラグインとして実装することでモジュール性を保ちつつ、いい感じに拡張できる
- そのために、DBはコアシステムにもつ。プラグインはコアシステムから値をやりとりする or 独自のDBを持つ
- コアシステムは規模に応じてレイヤードアーキテクチャやモジュラーモノリスにできる
- コアシステムをさらにプラグインアーキテクチャにすることもできる(マイクロカーネルアーキテクチャ in コアシステム)
- コアシステムとプラグインのつなげ方
- プラグインのP2Pエントリーポイント関数をコアシステムから呼び出す
- モノリスで完結する
- RESTやメッセージング
- プラグインを別サーバーでデプロイしないといけない
- そのかわり非同期でプラグインを呼び出せる(ただしこれをやるとモノリスじゃなくて分散アーキテクチャになる)
- 分散アーキテクチャの辛みがでるので、慎重に。
- プラグインのP2Pエントリーポイント関数をコアシステムから呼び出す
- プラグインの実装方法
- ライブラリ化
- 同一コードベース内でネームスペース分ける
app.plugin.domainname,hoge
- レジストリ
- コアシステムが利用可能なプラグインや入手法を知る仕組み
- 個々のプラグインのP2Pエントリーポイント関数やRESTのエントリーを登録
- コントラクト
- コアシステムがプラグインに対して要求するやり取りの規格
- インターフェースとかJSONで定義できる
マイクロカーネルアーキテクチャをいつ採用するべきか
- エディタとかブラウザみたいな、コア機能に対してプラグインをいっぱい入れる系のソフトウェア
- 共通コア機能に対して、複雑なロジックをもった似たような雰囲気のコンポーネントがいっぱいできうるとき、マイクロカーネルアーキテクチャにしとくと、コンポーネントのロジック同士が影響を与えるのを防げる
アーキテクチャ特性はどうか
- モノリシックの特徴はでる
- シンプルでコストが低い
- スケーラビリティとか耐障害性が弱い
-
ドメインと技術の両軸でモジュール分割される
- 多分、プラグインはドメインで分けられるが、コアシステムもプラグインもそれぞれは技術での分割とかされるからだと思う
- テストとかデプロイ容易性、モジュール性、拡張性まあまあいい
- プラグインがいい感じに分割してくれるので。
- パフォーマンスもいい
- コアシステムは薄くなるので。
第12章
メモ
サービスベースアーキテクチャ
特徴
-
分散型アーキテクチャであり、マクロ的に見るとレイヤードアーキテクチャ。ただし、荒いドメインを軸にドメインでもわける
- ユーザーインターフェース、サービス(ドメインサービス)、DBがインスタンス分かれてて、各インスタンスはRESTだったり、 gRPCだったりでコミュニケーションをとる
- インスタンスが分かれていて、各インスタンスごとにスケールできる。なので、LBをインスタンス間に噛ませてhealthyなインスタンスにいい感じにリクエストが飛ぶようにさせる必要がある
- DBインスタンスは1つを共有することが多い
- トポロジー
- ユーザーインターフェースをドメインサービス単位で分けたりしてもOK
- しっかり分離されてさえいれば、DBみドメインサービスごとに分けたりしてもOK
- もちろん共有もOK
- ユーザーインターフェースとドメインサービスの間にAPI層を設けて、リバースプロキシやゲートウェイを設置もできる。共通処理(メトリクス計測や監査要件など)を挟める
- ドメインサービス自体は粒度が荒いドメインサービスなので、それ自体も何かしらアーキテクチャスタイル決めないといけない
- サブドメインによるモジュラモノリスか、レイヤードアーキテクチャ
- いずれにせよ、APIファサード層(要はコントローラー)を最初にもうけて、配下のビジネスロジックをコントロールしないといけない
- マイクロサービスアーキテクチャとは異なり、自インスタンス内で完結する
- マイクロサービスアーキテクチャが分散アーキテクチャ(結果整合性)にせざるを得ないのに対し、サービスはモノリシックだからちゃんとDBレベルのACIDトランザクションができる
- DBの分割
- DBわけないとドメインサービス全部に影響を与えてしまうので、論理的にDBとORMを分けると良い。そうすると、DBへの変更の影響を最小限にできる
- 共有するテーブルだけ共有データベースに置く
サービスベースアーキテクチャをいつ使うべきか
- 万能でデメリットの少ないアーキテクチャなので、作るプロダクトが小さすぎなければ採用して良さそう
- 小さかったらモジュラモノリスとか、レイヤードアーキテクチャで良さそう
- ドメインによってドメインサービスをわけてそれぞれデプロイするし、DBとかユーザーインターフェイスもそれに合わせて柔軟に切り分けられるので、拡張しやすい
- ドメインサービスの粒度が荒いのが良い
- 1つ1つのドメインサービスがそこそこの大きさになるので、何か処理の中でトランザクション処理を入れたい時に、他のドメインサービスまで駆り出してくる必要が少ない(=分散トランザクションしなくていい)。むしろ、ACIDトランザクションを使えることが多いのでデータの整合性を保ちやすい。
- 他サービスを巻き込んだオーケストレーションが要らないことが多い
アーキテクチャ特性はどうか
- 荒いドメイン単位でサービスだったりユーザーインターフェイスだったりを分けたりするので、スケーラビリティ、モジュール性、耐障害性、デプロイ容易性、テスト容易性などなど、全体的に良い。サービスとかが大きくなりすぎないから。
- あと、荒いドメインで分ける = 近しいコードは同じサービスにあるので、他分散アーキテクチャと異なり、ネットワーク通信も絡まない。
第13章
メモ
イベント駆動アーキテクチャ
- 非同期にイベントを受信して、分散コンポーネントで処理する。
- イベントベースモデル ↔︎ リクエストベースモデル
- リクエストベースモデルというのは、普段よくあるやつ リクエストを起点に処理する
- イベントベースモデル
- 特定の状況で発生するイベントに基づいて処理を発火する
トポロジーは2つある
ブローカートポロジー
4つのアーキテクチャコンポーネントからなる
- 開始イベント
- イベントブローカー
- イベントプロセッサー
- 処理イベント
要は、Push型サブスクリプションをつかうCloud Pub/Subのアーキテクチャによるピタゴラスイッチ。
開始イベント → 起点のイベント。メッセージのPublishをするイメージ
イベントブローカー → イベントの仲介人。topic+ Push型サブスクリプションのイメージ
イベントプロセッサー → イベントを受け取って処理する。サブスクライブしているサーバーのイメージ
処理イベント → イベントプロセッサーが処理を終えた後に発行するイベントのこと
このトポロジーのメリット
- 拡張性が高い
- 処理イベントを発火は基本的にしておいて、もし拡張したくなったらその処理イベントをリッスンするコンポーネントを追加すればよい。簡単に拡張ができる。とりあえずイベントを発火させとけばいい。
このトポロジーのデメリット
- 回復性がない
- 途中でなんかエラーおきても、開始イベントを再送できないので、復帰できない。
- 開始イベント後のピタゴラスイッチで、どこで処理が終わったかに関心がない(検知できない)アーキテクチャ
- なので、データ不整合も発生する