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

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

Builderscon Tokyo 2019 の発表資料です。

0b40b09ee30366ddfe68070d94d7ee3f?s=128

Akira Suenami

August 30, 2019
Tweet

Transcript

  1. 2.

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

    Rails, React, 最近 Java とかも 少々 • 好きな RDBMS: PostgreSQL • 好きな制約: チェック制約 • 好きな焼肉の部位: ハラミ • 好きな(ry
  2. 7.

    SoRとSoE • SoR: System of Record ◦ その名の通り、「記録」のためのシステム。 ◦ 入力の事前チェックの堅牢性、データ整合性の担保などが求

    められる。 • SoE: System of Engagement ◦ 利用者との関係を構築するためのシステム。 ◦ 今どきの言葉を使うとよい UX を提供するためのシステム、と 言い換えてもよい。
  3. 8.

    SoRとSoEの対比 SoR SoE 基本的な設計観点 データ整合性 柔軟性、性能 データストア トランザクショナルな DB 多くの場合、RDB

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

    今回扱う事例: 2-sided platform • モール型 E-Commerce サービスを考える • システム利用者 ◦

    購買者ユーザ ◦ 店舗ユーザ モール型 EC プラットフォーム 購入者 店舗
  5. 29.

    単一責務の原則(SRP) • SOLID 原則の一つで「クラスの変更理由はひとつであるべきであ る」とする設計原則。 • アンクル・ボブは Clean Architecture においてこの「変更理由」

    をさらに「アクター」と言い換えた。 • つまり、あるクラスやモジュールの変更は単一のアクターの変更 要求によるものであるべきである。 • DBA や経営者もアクターの例として挙げられており、利用者だけ でなく、より広範な利害関係者を指している。
  6. 33.

    複数のアクターの要求がDBに直撃する 購入者 出荷担当者 いつ届くの? キャンセルしたい 商品を間違ったので 変更したい 出荷しないと! 在庫が残り少ないので仕 入れ指示をしたい

    キャンセルされたので出 荷を止めます 「商品」「購入」などは一見ユビキタス言語かのように思われる が、多くの場合、次第に乖離し始める。 共通DB ふ、ふええ…
  7. 37.
  8. 38.

    中央に事業者向けのモデルがあると考える 購買者向け システム 購入者 店舗 店舗向け システム 事業者の モデル •

    DB を直接共有しないため、利用者アクターのユースケースに依 存しない不変条件を維持することができる。 • システム全体が、事業者、購買者、店舗をそれぞれの要求元とす るサブシステムに分割された。
  9. 46.

    ドメインとプレゼンテーションの関係 • ドメインとプレゼンテーションの依存関係は、一般にプレゼンテー ションからドメインへの単方向依存である。 • DDD 本ではコンテキストマップのパターンがいくつか紹介されて いるが、ドメインとプレゼンテーションのこの関係は「顧客/供給 者」パターンに最も近い。 •

    「顧客」である利用者アクターのモデルから「供給者」たる事業者 アクターのモデルに適切に振る舞いを移譲することによって、利 用者アクターのモデルはプレゼンテーション優位の状態にでき る。 • プレゼンテーション優位なアプリケーションは適切なデータモデル (ドキュメントストア、KVSなど)を選定することによって入出力駆 動での開発を進めやすくなる。
  10. 52.

    CQRSとの関係 • SoR/SoE という分類と Command と Query の非対称性に着目し た分離(=CQRS)は共通している部分が多く、得られる恩恵も近 い。

    • Command のモデル(≒ドメインモデル)から Query のモデルへ の変換の責務をどこが担うかという違いはあるような気がする?
  11. 53.

    Command/QueryとSoR/SoE SoR SoE Command いわゆる DDD というものが最 も活躍する領域となる。 入力値のみから可能なバリデーショ ンを行い、具体的な振る舞いをSoRに

    移譲する。 現在の状態に依存するバリデーショ ンが必要な場合は、それもSoRへ移 譲する。 Query リソース指向、あるいはドメイン ロジック由来の集約を単位とす るデータ構造での参照のみで きる。 RDBのマテリアライズドビューやサマ リーテーブル、ドキュメントストア、 KVS、検索インデックスなどの具体的 実装技術への依存を受け入れること によって性能、柔軟性、開発速度など を向上させることができる。
  12. 55.

    第二部まとめ • プレゼンテーションモデル優位の場合は設計を入出力に駆動さ せやすく、ドメインロジックを必要としないことが多い。 ◦ ペリフェリックパターンは、 Clean Architecture においてはア ンチパターンとして紹介されているが、具体的実装技術に駆

    動させやすいアプリケーションにおいてはむしろ立派な実装パ ターンと言えるのではないだろうか。 ◦ 実際、Greg Young の主張する CQRS パターンはそういう設 計・実装パターンである。
  13. 60.

    [再掲] Command/QueryとSoR/SoE SoR SoE Command いわゆる DDD というものが最 も活躍する領域となる。 入力値のみから可能なバリデーショ

    ンを行い、具体的な振る舞いをSoRに 移譲する。 現在の状態に依存するバリデーショ ンが必要な場合は、それもSoRへ移 譲する。 Query リソース指向、あるいはドメイン ロジック由来の集約を単位とす るデータ構造での参照のみで きる。 RDBのマテリアライズドビューやサマ リーテーブル、ドキュメントストア、 KVS、検索インデックスなどの具体的 実装技術への依存を受け入れること によって性能、柔軟性、開発速度など を向上させることができる。
  14. 61.

    バリデーション • バリデーションと一般に呼ばれるものにも種類がある。 ◦ 入力値のチェック(長さや範囲、正規表現マッチなど) ◦ その事業において必要な不変条件 ◦ Ruby の

    ActiveRecord 実装が(ry • 構造的に自明だが、前者は後者の制約より同等かそれより厳しく なければならない。 • 現在状態に依存せず、値のみで可能な入力チェックは SoE で可 能であり、そのほうが利用者に対してよい UX を提供できる可能 性が高い。 ◦ JavaScript によるリアルタイムバリデーションなど
  15. 63.

    バリデーション • バリデーションに関して重複を排除したいと考えた場合、基本的 に誤った共通化の可能性を考えたほうがよい。 ◦ そういう意味では SoR と SoE が物理的に分割されているほう

    がよいケースもある。 ◦ サーバーサイドと同じバリデーションを JavaScript でもやるこ とに違和感を感じる人は多くないと思う。 • SoR でドメインモデルを構築している前提であれば、不変条件は 独自型(ValueObject, etc)になり、コンパイラの恩恵も受けられ る。
  16. 64.
  17. 68.

    [再掲] Command/QueryとSoR/SoE SoR SoE Command いわゆる DDD というものが最 も活躍する領域となる。 入力値のみから可能なバリデーショ

    ンを行い、具体的な振る舞いをSoRに 移譲する。 現在の状態に依存するバリデーショ ンが必要な場合は、それもSoRへ移 譲する。 Query リソース指向、あるいはドメイン ロジック由来の集約を単位とす るデータ構造での参照のみで きる。 RDBのマテリアライズドビューやサマ リーテーブル、ドキュメントストア、 KVS、検索インデックスなどの具体的 実装技術への依存を受け入れること によって性能、柔軟性、開発速度など を向上させることができる。
  18. 70.
  19. 71.

    採番 • コマンドを結果整合性に寄せた場合、SoE はその完了を知ること ができなくなる。現実的には、ポーリングか Pub/Sub、あるいは 何らかの画面レンダリングをフックに実データを問い合わせる形 になるが、そのときのキーはリクエスト完了時には確定している 必要がある。 •

    実装パターンはいくつかある。 ◦ 採番のみを行うエンドポイントを SoR が提供する。 ◦ コマンドリクエスト完了時に同期的にキーを返す。 ◦ UUID など、SoE 側で採番可能な採番体系を選択する。
  20. 79.

    キャッシュ • キャッシュは基本的に SoE の関心時だと心得る。 • SoR 側の構造に引きずられないように、あくまで利用者の UX を

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