[和訳]ドメイン駆動設計に向けて

Kevin Mas Ruiz    
Kevin Mas Ruiz氏は、バルセロナに拠点を置くドメイン駆動開発者であり、vlingo.ioのコントリビュータも努めています。
この記事は、2019年12月に公開された記事の翻訳転載です。著者の許可を得て配信しています。
To Domain Driven Design

あなたの会社はシステムとしてモノリスをベースに構築されています。このモノリスの内部はビジネス知識の宝庫であることから、モノリスは会社にとって、おそらくは最良の資産であるはずですが、モノリスには長年にわたり蓄積された技術的な負債と、部門間のコミュニケーションなくしてお互いを規則(コード)で縛るという穢れた一面があります。

そのモノリスなるものは、遅くて不透明で、エラーが発生しやすく、実証テストがなされていません。システムの開発者とオペレータチームは、新たなコードのリリースを嫌う傾向にあり従って行き着くところ、重いプロセスを定義するには、手動のテストプロセスに長時間を費やし、プロセスのリリースサイクルが長期化する羽目に陥っています。これが、新しいバージョンのリリースには安全を必要とする由縁であって、この作業の後戻りや、やり直しは難しいが故に、作業を中断する訳には行かないのです。

しかし、モノリスは依然として廃れることなく、依って会社収益の大部分を生み出していますが、社内のチームとしてのパフォーマンスも妨げられます。主要な収益源を改善し、且つ長期的な予測可能性とビジネスの進化のためにチームを最適化するにはどうすればよいでしょうか。ここで手っ取り早いのがDDD(ドメイン駆動設計)なのです。

しかし、(申し訳ないのですが 😊)DDDの話に入る前に、モノリスが未だ廃れずに機能し、依って膨大な量のトラフィックを提供している理由を理解する必要があります。モノリスは間違ったソフトウェア設計図ではなく、問題は大きな泥だんご(Big Balls of Mud)にあります。それでは、モノリスについて話を始めましょう。

コストで汎用性があります。モノリスが長続きしている理由は、モノリスで行われた決定は中期的に取り消しが可能であるためです。データとコードは 1 か所にあるため、リファクタ数が簡単で (お気に入りの IDE で行うことができます)、データ転送が安価にできます。たとえば、次のユースケースから始めましょう。

私たちはAmazonのようなオンラインショッピングプラットフォームであって、そこで書籍を販売しています。製品の販売開始の初期においては、それほど多くの注文はなく、壊れた注文を手動で修正可能なことから、倉庫内の帳簿の在庫は検証していません。最終的には、次のアーキテクチャ図が作成されます。

数ヶ月後、私たちのビジネスは成長し始め、毎分数件の注文が入るようになり、ブラックフライデーとクリスマスの間には注文のピーク迎えました。本が在庫切れになり、増え続ける注文の処理に対応できません。購入しようとする書籍がチェックアウトプロセス中に在庫されていることを検証する StockService を実装することにしました。

ご覧のとおり、新しいサービスとビジネスルールの追加は非常に安価でした。私たちは難しいことはせずに、モノリスに則したパターンに従ったのです。私たちがそうしたのは、以下の理由からでした。

・モノリス内ではデータが安価に移動できる。
・モノリス内での決定は、単一のプロセスに限定される
・モノリスには明示的で一般的なパターンがある。
・モノリスは、IDE の助けを借りてリファクタリングを可能とする。

だから、私たちがやっていることは、複雑設計決定によって技術的な負債を増大させる新機能を提供するのではなく、前進することなのです。これにより、小規模なチームは製品を高速に反復処理できますが、チームの数が増えると問題になります。何故ならばその理由は、ユーザーのニーズを満たすべく、さまざまなチームがさまざまなサービスのデータとロジックを必要として競合するということです。

ユーザーサービスではチーム A とチーム C が重複していることがわかります。この状況に該当する一般的な要因は、所有形態(onwnership)、協調形態(collaboration)、効果(effect)の 3 つのカテゴリに分かれています。

所有形態 協調形態 効果
ユーザーサービスを1チームで占有 その機能を必要とする場合は、占有チームに要求 案件のチーム間共有により、チームの活力が低下
ユーザーサービスを1チームで占有 他チームがその機能を必要とする場合は、PRを行う 機能を確認する他のチームに依存するため、PRを書き込むチームの速度を低下させる
ユーザーサービスを全チームで共有 新機能を実装するには、習慣的なコミュニケーションとコラボレーションが必要 案件のチーム間共有により、チームの活力が低下

この問題に対する簡単な解決策がないが故に、解決策としてははモノリスを分割することのみです。同じコードをさまざまなチームが持つことの複雑さを理解するには、2 つのスレッドがメモリ内の同じ数百の変数セットを使用する複雑さを参照してください。

そこで、数ヶ月間または数年間をかけて、モノリスをサービスに分割しました。モノリスを分割する最も一般的なアプローチは、データ境界を定義する方法です。たとえば、ユーザーに関連するすべてのデータは最終的に、ユーザーサービス、StockServiceにおける株式情報などになります。

このアプローチに関する問題は、次の点です。

・それはドメイン駆動設計のように見えるかもしれませんが、ビジネス知識ではなくデータに基づいているため、そうではありません
・それはマイクロサービス アーキテクチャのように見えるかもしれませんが、サービス間のサービスが非常に結合されているため、サービスもチームも自律的ではないため、そうではありません。

また、データを簡単に移動でき、IDE でリファクタリングできない分散モノリスを構築し、インフラストラクチャコストも高くなります。では、その状況に至らないようにするにはどうすればよいでしょうか。

私が行う最も基本的なアドバイスは、アーキテクチュアの分割をデータではなく知識に基づいて行うものとすることです。企業が知識をどのように構築するかは、人々とビジネスに完全に依存しますが、試みるに安価なパターンがいくつかあります。

これらのパターンを適用するには、私たちのビジネスをビジネスプラットフォームに準えて考える必要があります: 私たちは製品を持っていませんが、製品をセットとして持っています。これらの製品は、ペルソナに適用される一連の機能です。たとえば、このパターンに基づいて、下図のような購買活動が可能です。

成功した製品に関しては、それぞれ個別に評価して進化させる必要があります。ただし、お気付きのように、製品モジュール間には何らかの相互依存関係がある可能性があります。たとえば、ワンクリック購入は、通常の購入製品などの在庫情報とユーザー情報に依存する場合があります。これらの依存関係がチームのパフォーマンスに影響を与えず、且つロジックを重複させないようにするにはどうすればよいでしょうか。

まず、カップリングが発生している可能性のある場所を理解するために、製品をモジュールに切り分ける必要があります。

ご覧のとおり、ワンクリック購入と一般的購入のいづれも、同じソースからの情報を必要としています。しかし、より更に掘り下げて行くと、その違いがわかります。

・ワンクリック購入も標準購入も、その購入者は同一なのですか?
・書籍に関して必要な情報は、いづれのプロセスにおいても同一なのですか?
・在庫情報は、(ワンクリック、標準購入)両方の製品においてで同じ方法で関連づけられていますか?
・出荷情報は、(ワンクリック、標準購入)両方の製品においてで同じ方法で扱われていますか?

これら質問の回答がすべて「はい」の場合、おそらくは、いづれかの製品が重複し、依って少なくともいづれかが無いことになりますが、そうではありません。詳しく見てみましょう。

データソース ワンクリック購入 標準購入
購入者 他の書籍を以前に購入した購入者に限定 全購入者
書籍 入手可能な全ての情報が必要 入手可能な全ての情報が必要
在庫 在庫情報のみが必要 ユーザーに購入を促すに、在庫の品薄状況を知る必要あり
出荷 出荷元情報のみ 宅配業者

私たちの場合、同じ特徴を共有しているのは書籍だけで、それは行動ではなくデータです。この状況は、当社の製品がユーザーの問題に関する知識と理解が異なって境界付けられたコンテキストであることを意味します。そして私たちは、知識を製品と、そして製品をペルソナに結び付けていることからして、このことは理にかなっています。

境界付けられたコンテキスト間で情報を共有する場合は、可能な限りチームのパフォーマンスを優先する必要があります。つまり、知識を複製する必要がある場合があります。これは、他のシステムで非常に一般的です:私たちはバスルームとキッチンの両方にシンクを持っているのです。

境界付けられたコンテキスト間でデータを共有するさまざまな方法があり、イベント ベースのアーキテクチャ (SQS など) またはデータ ストリーミング プラットフォーム (Kafka など、状態ソーシングを行う) を使用してデータ ストリーミングを好みます。データベースビューなどのより単純なツール (Yugabyte や AWS RDS などの分散データベースがある場合) で情報を共有することもできます。

そして、そのようなパターンが無駄に見える場合でも、私たちの体がどのように動作するかを少し考えてください。私たちの体は、可用性と健康を保証するために、常に私たちの筋肉や臓器に血液を血管で送出しています。あなたの体の中で、筋肉が動こうとするたびに、あなたの心臓にいくばくかの血液を求める必要があり、その結果、あなたの心臓があなたの肺に酸素を求める必要がある場合は、今すぐ検討してください。これは今、筋肉ごとに毎秒繰り返されているのです。

ただし、情報は他の境界付けられたコンテキスト (例えば、新規購入者の登録プロセスなど) から取得する必要があり、それには所有者の存在が必要です。チームにとって扱いやすい小さなモジュールが手に入るまで、より多くの製品を泡立て、すすいで、繰り返し、分割することができます。たとえば、下記の系統図は、架空の書籍ショッピング プラットフォームにおける製品と(購入者間の)依存関係を示しています。

関連情報のほとんどが他の製品に公開されていることが判明した場合 (たとえば場合によっては、エクスプレスサインアップとプロフィールで公開されるすべての情報が他の製品で読み取られる可能性があります) は、その製品はより汎用的 (企業ではなく個人にとっての汎用性) に一元化することができるので、比較的より単純なサービス (UserService など) で公開することが可能になります。

それでは、役に立つと思う点をいくつか以下に要約して、共有したいと思います。

・プラットフォームで考えることは、私たちのビジネスをより良く分割することができます。
・製品をペルソナおよび境界付けられたコンテキストにリンクすると、境界が明示的になります。
・分散型および利用可能なプラットフォームを構築するには、ステートソーシングおよびイベント駆動型アーキテクチャが不可欠です。
・チームはコードを共有するのではなく、共通のプラットフォームを共有する必要があります。

完読を頂きありがとうございました。


コメントを読む

新着ピック  






















新着ニュース

Travis CIでRepositoryのアクセス権ごとにどんな操作が可能であるか確認してみた | Developers.IO

S3のユーザーポリシーを使用したバケットへのアクセスコントロールを公式チュートリアルで理解する | Developers.IO

ポケモンGOで初の大規模メンテナンス 2日未明から7時間

NeovimでScalaの編集環境を整えてみた | Developers.IO

営業推進室にジョインしました大森です | Developers.IO

AWS事業本部コンサルティング部にジョインしました大村です | Developers.IO

トレンドマイクロの製品に脆弱性? “マイクロソフトからBAN”の疑惑 公式は「事実と異なる」

「iPhone SE(第2世代)」用ケース選び 背面手帳型ケースおすすめ3選【2020年最新版】

Amazonギフト券がAmazon以外でも使える Amazon Payから残高を利用可能に

AWS事業本部にジョインしました川上です! | Developers.IO

DA事業本部にジョインした石川葉月です | Developers.IO

Disney+(ディズニープラス)、6月11日に日本上陸 ドコモが国内独占で提供

ImageBuilder をサポートした CloudFormation で AMI作成から EC2のオートスケール起動まで実装してみた | Developers.IO

新卒社員が入社2ヶ月でAWS Cloud Practitionerを取得した話。 | Developers.IO

“株式市場”のように商品を売買するECサイト「StockX」日本上陸 スニーカーやアパレルに特化

身内に潜む敵? 実はリモートより怖いlocal攻撃

ドローン動画「A World Artists Love」のアニ・アコピアン監督が語る制作秘話 | TechCrunch Japan

ドローン動画「A World Artists Love...

TechCrunch Japan / 12時間前


トランプ大統領の投稿にFacebookが行動を起こさない理由をザッカーバーグ氏が説明 | TechCrunch Japan

決定版!イマドキの ESLint 設定! | Developers.IO

PayPayがオンライン診断のオンライン決済に対応、調剤薬局の服薬指導にも使える | TechCrunch Japan

もっと見る
記事をPICKする
会員登録
Register
記事をPICKする

会員登録すると、もっと便利に利用できます。