Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ビジネスの構造を扱うアーキテクチャとユーザとの接点を扱うアーキテクチャ #builderscon

ビジネスの構造を扱うアーキテクチャとユーザとの接点を扱うアーキテクチャ #builderscon

Builderscon Tokyo 2019 の発表資料です。

Akira Suenami

August 30, 2019
Tweet

More Decks by Akira Suenami

Other Decks in Technology

Transcript

  1. 自己紹介 • 末並 晃 @a_suenami • 生息している界隈: DDDとか、TDDとか、RDBとか • お仕事で使ってる技術スタック:

    Rails, React, 最近 Java とかも 少々 • 好きな RDBMS: PostgreSQL • 好きな制約: チェック制約 • 好きな焼肉の部位: ハラミ • 好きな(ry
  2. SoRとSoE • SoR: System of Record ◦ その名の通り、「記録」のためのシステム。 ◦ 入力の事前チェックの堅牢性、データ整合性の担保などが求

    められる。 • SoE: System of Engagement ◦ 利用者との関係を構築するためのシステム。 ◦ 今どきの言葉を使うとよい UX を提供するためのシステム、と 言い換えてもよい。
  3. SoRとSoEの対比 SoR SoE 基本的な設計観点 データ整合性 柔軟性、性能 データストア トランザクショナルな DB 多くの場合、RDB

    スケーラビリティがある高速なデータ ストア ドキュメント指向DB、KVS、全文検索 インデックスなど リリースサイクル SoEと比べると相対的に長い(諸説あ るかも) 高速なリリースサイクルが求められる 品質評価 トラディショナルなソフトウェアテスティ ング手法を適用しやすい トラディショナルな手法に加え、ユー ザーテスト、ユーザーインタビュー、 A/Bテストなど カナリアリリースも実トラフィックを利 用したテストと捉えることができる データ整合性 トランザクション整合性が必須 結果整合性でよい要件も多い 要するに? 堅牢なMutation 柔軟なQuery 設計を駆動する(しやすい)もの ドメインモデル、概念データモデル UI(ビジュアルデザイン、ユーザインタ ラクション)、キャッシュ
  4. 今回扱う事例: 2-sided platform • モール型 E-Commerce サービスを考える • システム利用者 ◦

    購買者ユーザ ◦ 店舗ユーザ モール型 EC プラットフォーム 購入者 店舗
  5. 単一責務の原則(SRP) • SOLID 原則の一つで「クラスの変更理由はひとつであるべきであ る」とする設計原則。 • アンクル・ボブは Clean Architecture においてこの「変更理由」

    をさらに「アクター」と言い換えた。 • つまり、あるクラスやモジュールの変更は単一のアクターの変更 要求によるものであるべきである。 • DBA や経営者もアクターの例として挙げられており、利用者だけ でなく、より広範な利害関係者を指している。
  6. 複数のアクターの要求がDBに直撃する 購入者 出荷担当者 いつ届くの? キャンセルしたい 商品を間違ったので 変更したい 出荷しないと! 在庫が残り少ないので仕 入れ指示をしたい

    キャンセルされたので出 荷を止めます 「商品」「購入」などは一見ユビキタス言語かのように思われる が、多くの場合、次第に乖離し始める。 共通DB ふ、ふええ…
  7. 中央に事業者向けのモデルがあると考える 購買者向け システム 購入者 店舗 店舗向け システム 事業者の モデル •

    DB を直接共有しないため、利用者アクターのユースケースに依 存しない不変条件を維持することができる。 • システム全体が、事業者、購買者、店舗をそれぞれの要求元とす るサブシステムに分割された。
  8. ドメインとプレゼンテーションの関係 • ドメインとプレゼンテーションの依存関係は、一般にプレゼンテー ションからドメインへの単方向依存である。 • DDD 本ではコンテキストマップのパターンがいくつか紹介されて いるが、ドメインとプレゼンテーションのこの関係は「顧客/供給 者」パターンに最も近い。 •

    「顧客」である利用者アクターのモデルから「供給者」たる事業者 アクターのモデルに適切に振る舞いを移譲することによって、利 用者アクターのモデルはプレゼンテーション優位の状態にでき る。 • プレゼンテーション優位なアプリケーションは適切なデータモデル (ドキュメントストア、KVSなど)を選定することによって入出力駆 動での開発を進めやすくなる。
  9. CQRSとの関係 • SoR/SoE という分類と Command と Query の非対称性に着目し た分離(=CQRS)は共通している部分が多く、得られる恩恵も近 い。

    • Command のモデル(≒ドメインモデル)から Query のモデルへ の変換の責務をどこが担うかという違いはあるような気がする?
  10. Command/QueryとSoR/SoE SoR SoE Command いわゆる DDD というものが最 も活躍する領域となる。 入力値のみから可能なバリデーショ ンを行い、具体的な振る舞いをSoRに

    移譲する。 現在の状態に依存するバリデーショ ンが必要な場合は、それもSoRへ移 譲する。 Query リソース指向、あるいはドメイン ロジック由来の集約を単位とす るデータ構造での参照のみで きる。 RDBのマテリアライズドビューやサマ リーテーブル、ドキュメントストア、 KVS、検索インデックスなどの具体的 実装技術への依存を受け入れること によって性能、柔軟性、開発速度など を向上させることができる。
  11. 第二部まとめ • プレゼンテーションモデル優位の場合は設計を入出力に駆動さ せやすく、ドメインロジックを必要としないことが多い。 ◦ ペリフェリックパターンは、 Clean Architecture においてはア ンチパターンとして紹介されているが、具体的実装技術に駆

    動させやすいアプリケーションにおいてはむしろ立派な実装パ ターンと言えるのではないだろうか。 ◦ 実際、Greg Young の主張する CQRS パターンはそういう設 計・実装パターンである。
  12. [再掲] Command/QueryとSoR/SoE SoR SoE Command いわゆる DDD というものが最 も活躍する領域となる。 入力値のみから可能なバリデーショ

    ンを行い、具体的な振る舞いをSoRに 移譲する。 現在の状態に依存するバリデーショ ンが必要な場合は、それもSoRへ移 譲する。 Query リソース指向、あるいはドメイン ロジック由来の集約を単位とす るデータ構造での参照のみで きる。 RDBのマテリアライズドビューやサマ リーテーブル、ドキュメントストア、 KVS、検索インデックスなどの具体的 実装技術への依存を受け入れること によって性能、柔軟性、開発速度など を向上させることができる。
  13. バリデーション • バリデーションと一般に呼ばれるものにも種類がある。 ◦ 入力値のチェック(長さや範囲、正規表現マッチなど) ◦ その事業において必要な不変条件 ◦ Ruby の

    ActiveRecord 実装が(ry • 構造的に自明だが、前者は後者の制約より同等かそれより厳しく なければならない。 • 現在状態に依存せず、値のみで可能な入力チェックは SoE で可 能であり、そのほうが利用者に対してよい UX を提供できる可能 性が高い。 ◦ JavaScript によるリアルタイムバリデーションなど
  14. バリデーション • バリデーションに関して重複を排除したいと考えた場合、基本的 に誤った共通化の可能性を考えたほうがよい。 ◦ そういう意味では SoR と SoE が物理的に分割されているほう

    がよいケースもある。 ◦ サーバーサイドと同じバリデーションを JavaScript でもやるこ とに違和感を感じる人は多くないと思う。 • SoR でドメインモデルを構築している前提であれば、不変条件は 独自型(ValueObject, etc)になり、コンパイラの恩恵も受けられ る。
  15. [再掲] Command/QueryとSoR/SoE SoR SoE Command いわゆる DDD というものが最 も活躍する領域となる。 入力値のみから可能なバリデーショ

    ンを行い、具体的な振る舞いをSoRに 移譲する。 現在の状態に依存するバリデーショ ンが必要な場合は、それもSoRへ移 譲する。 Query リソース指向、あるいはドメイン ロジック由来の集約を単位とす るデータ構造での参照のみで きる。 RDBのマテリアライズドビューやサマ リーテーブル、ドキュメントストア、 KVS、検索インデックスなどの具体的 実装技術への依存を受け入れること によって性能、柔軟性、開発速度など を向上させることができる。
  16. 採番 • コマンドを結果整合性に寄せた場合、SoE はその完了を知ること ができなくなる。現実的には、ポーリングか Pub/Sub、あるいは 何らかの画面レンダリングをフックに実データを問い合わせる形 になるが、そのときのキーはリクエスト完了時には確定している 必要がある。 •

    実装パターンはいくつかある。 ◦ 採番のみを行うエンドポイントを SoR が提供する。 ◦ コマンドリクエスト完了時に同期的にキーを返す。 ◦ UUID など、SoE 側で採番可能な採番体系を選択する。
  17. キャッシュ • キャッシュは基本的に SoE の関心時だと心得る。 • SoR 側の構造に引きずられないように、あくまで利用者の UX を

    ベースに考える。 ◦ ネイティブアプリや SPA (Single Page Application) のように サーバーサイド API とクライアントが分離されている場合はク ライアントがキャッシュしたい単位でエンドポイントや JSON 構 造を設計する。 ◦ 難しい場合は BFF (Backend For Frontend) の導入も検討す る。