BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル DDDアプローチを用いたビジネスルールの検証

DDDアプローチを用いたビジネスルールの検証

キーポイント

  • Business rules express part of the knowledge a system has about a specific domain.
  • Structuring business rules appropriately reduces the possibility of error and makes the maintenance easier.
  • Business rules have different responsibilities, such as providing validation or generating outputs.
  • Deciding how to process events has an impact on the general design and the consequences need to be understood before making any decision.
  • Using a command approach should be structured around tasks a user executes and provide a clear output.
     

原文(投稿日:2020/06/15)へのリンク

ビジネスルールと聞いて思い浮かべるのは、あなたが技術関係者であるならば、おそらくはコード行か、あるいは(使用しているならば)ビジネスルールエンジンでしょう。しかしビジネスルールとは、コーディングよりも知識管理に関連が深いものなのです。建築関係に従事する人ならば、ベッドルームの最小限のサイズや、ベッドルームに求められる書斎とは違った特質について、多くのルールがあることを知っています。ルールと、それを適用する方法を知ることが、人をその分野の専門家にするのです。私たちの目標は、各分野の専門家の振る舞いをエミュレートするソフトウェアアプリケーションの開発です。

今回の記事では、共有会社のリソース予約システムを取り上げます。このシステムの目的は、ノートやプロジェクタ、卓球台などを、従業員が手軽に予約できるようにすることです。

この最初の文章を読んだだけで、"リソースとは何か?"、"リソースを予約するというのはどのような意味か?"、"リソースを2回以上予約することはできるのか?"、というような疑問リストがすぐに作れるのではないかと思います。これらの疑問には、その分野の専門家に答えてもらう必要があります。そしてそれが、システムの振る舞いをコントロールする"ビジネスルール"になるのです。

同時にこれは、エンティティやバリューオブジェクト、コマンドといった、その他のシステム要素を定義する上でのガイダンスにもなります。各要素を定義する方法については、今回の記事の対象範囲を越えています。

ちなみに、この話題に関しては、Eric Evans氏の"Domain-Driven Design"のように、それを専門に取り上げた書籍があります。また、.NETを扱っているのであれば、"Hands-On Domain-Driven Design with .NET Core"がお勧めできます。

この記事では、ビジネスルールの構築において必要な条件、という部分に限定したいと思います。すなわち、

  1. 一貫性があること。すべての開発者が理解できる方法でルールを体系化することは、将来的な変更のために極めて重要です。システムは常に変化するものであり、アプリケーションはその変化に備える必要がある、と考えておくべきでしょう。
  2. テストが容易であること。テストの可能なルールを作ることは、変更が既存の機能を損なわないことを保証する唯一の手段です。
  3. データの一貫性を維持すること。データの一貫性を保つことは、ビジネスルールの大きな責務のひとつです。個人的な経験から言えば、データの品質上の問題の多くは、システムルールの不十分な運用に関連しています。
  4. 診断が容易であること。予期しないエラーは回避する必要がありますが、それでも例外は常に発生します。エラーの情報が、例えば"nullオブジェクト参照"というような情報のみであれば、状況はさらに悪くなります。

この記事では、システムのルールを表現するために、"インプット・プロセス・アウトプット"モデルを使用しています。このモデルでは、システムにインプットが与えられて、内部のプロセッサがインプットを取得してオペレーションを実行し、アウトプットを生成します。ただし、プロセッサが何らかのアクションを実行する前に、提供されたインプットの有効性を検証(validation)しなければなりません。次のセクションでは、この検証を行う方法について説明します。

詳細モデル

ドメインベースのアプローチを用いて検証を処理するためのベースモデル — システムに送信されるコマンドを示す

このモデルは、システム内でビジネスルールを処理する実装例を示したものです。このアプローチはドメイン駆動設計(Domain-Drivern-Design、DDD)に基づきますが、DDDを使用しない場合にも適用することができます。実行シーケンスは次のとおりです。

システムに送信されるコマンド

1. クライアントのコマンド送信

クライアントが実行可能なコマンドをモデリングするためには、それらに名前を付ける必要があります。例えば、"MakeReservation"というようなものです。これらの設計定義を、ソフトウェア設計とビジネスデザインの中間に置いている点に注意してください。些細なことに思われるかも知れませんが、これを明確にしておくことで、システム設計をより効果的に理解できるようになります。この考え方は、タスクを念頭に置いてシステムを設計するという、HCI(Human-Computer Interaction)の概念に関連しています。システムのサポートすべきタスクについて設計者が考える時、コマンドという概念が役に立つのです。

コマンドは、日付やリソース名、使用法の説明というように、追加的なパラメータを伴う場合があります。コマンドとクエリの責務分離(Command and Query Responsibility Segregation、CQRS)は、システムインタラクションのモデリングにコマンドを使用するパターンのひとつです。モデルのイメージの中でのクライアントはユーザですが、他のシステムであっても構いません。単にデータを返すものから、システムの状態を変更するようなものまで、さまざまなアクションを振る舞いとして持つようなシステムの設計が可能です。

コマンドの構文検証

2. 構文規則の検証

次のステージは構文検証(syntax validation)です。構文(syntax)とは、Merriam-Webster辞典によると、言語要素(linguistic element、単語など)を組み合わせて構成要素(constituent、句や節など)を形成する方法です。私たちの状況においては、そのドメインのコンテキストにおいてコマンドが有意である、という意味になります。

これを検証することにより、提供されたデータがシステムにとって首尾一貫したものである、ということが保証されます。検証の一例として、予約の開始日を考えてみましょう — 開始日は過去であったり、nullであってはなりません。 検証ステージ中のエラーの返却には、さまざまな方法があります。Vladimir Khorikov氏はこのような検証を行う方法について、いくつかの例を紹介しています。この検証は、システムの他のエンティティでも同じように発生する可能性があります。例えば、過去の日付を入力できないようにするには、入力値を検証のためにバックエンドサービスに送信するよりも、ユーザインターフェース内で検証する方が望ましいでしょう。ただし、同じ検証をドメイン内で行うべきでない、という意味ではありません — 別のクライアントによる誤用を防ぐことができるからです。

システム状態を使用した意味規則の検証

3. 意味規則の検証

意味検証(semantic validation)はシステム状態に依存します。このタイプの規則は、入力されたコマンドがシステムの現在の状態において適切かをチェックするためのもので、通常はシステムエンティティ間で保管や受信が行われます。MakeReservasionコマンドの例であれば、このような検証のひとつは、要求されたリソースを他のユーザが予約していないことの確認です。この検証をクライアント側のアプリケーションで行うことも可能ですが、そうであったとしても、さまざまな理由から、同じリソースを予約する要求をドメインが受信する可能性は残ります。データの一貫性を確保するのはシステム側の責任なのです。

システム状態を変更するプロダクション規則

4. プロダクション規則

プロダクション規則はシステムの心臓部です。これまでの説明の中で、コマンドは、与えられた要求が実行可能であることを保証すべく、さまざまなステージを渡り歩いてきました。プロダクション規則は、要求された状態に達するために、システムが実行しなければならないアクションを指定するルールであり、クライアントが実行しようとするタスクを対象とします。MakeRservationコマンドを例に取るならば、要求されたリソースを予約済(reserved)として登録するために必要な変更を行います。これらの操作の結果として、エンティティとドメインサービスはイベントを生成して、クライアントや他のシステムに変更があったことを伝えられるようになります。私たちの使っている例では、ResourceReservedがそれに当たります。

イベント生成と処理

5. イベント

イベントは、他のシステムやサブシステムと対話するためのコミュニケーション機構です。ただし、自分のドメインにそれを実装する前に、システムがこれらのシグナルにどのような反応をするのかを決めなければなりません。イベントの処理には2つの選択肢があって、どちらも利点と欠点があります。

ひとつはトランザクション整合性(transactional consistency)を使用する方法です。このモデルでは、システムは同じトランザクションを使うことで、エンティティ変更の一貫性を確保します。複数の集合が関与している場合であっても、トランザクションがその変更を追跡し、プロセスの最後に変更を永続化します。このパターンは作業単位(unit of work)として知られているもので、コードの作成に関しては、その単純さと効率性という明らかなメリットがある反面で、使用するのが困難な場合があります。理由のひとつとして、修正したエンティティをメモリ中に保持する、ということがあります。そのため、ロードによっては、メモリの使用量やリソースの処理が過剰になる場合があるのです。さらに、ドメイン外とコミュニケーションする場合には、分散トランザクションが必要になるため、アプリケーションはさらに複雑なものになります。

第2の選択肢は結果整合性(eventual consistency)を用いることです。この場合は、コマンド実行中に大規模なエンティティグラフをメモリ内で処理する必要がないため、システムの能力は向上します。この決定には、しかしながら、別の結果があります。予約システムは変更を完了することが前提であるため、他システムが失敗を通知する場合には、前回の操作を元に戻す補正トランザクション(compensation transaction)を実装しなければなりません。同時にこれは、ユーザにもエラーが通知される、という意味でもあります。どちらかを選択するためは、利点と欠点、開発コスト、必要なインフラストラクチャを検討しなければなりません。例えば、他ドメインとのメッセージの送受信をするために、メッセージブローカが必要になるかも知れないのです。

クライアントに通知を送る

6. 通知

コマンドが完了したならば、クライアントに実行結果を伝えなければなりません。クライアントが別システムの場合は、この部分は省略可能ですが、相手がアプリケーションの場合、特に非同期通信が関与している時には、コマンド実行の成否をユーザに通知する必要があるでしょう。ここでもう一度、MakeReservationコマンドを例にすると、要件のひとつとして、指定されたリソースを割り当てる前に所有者の承諾が必要である、というものがあります。リソースの使用が承諾されたならば、システムはその結果をユーザに送信しなければなりません。このモデルの通知(notification)は、ResourceApprovedイベントが生成された時に始まります。このイベントは、コマンドの結果であるという点では、すでに説明したものと同じロジックに従っていますが、実行するのが別のユーザである点が異なります。

これを設計に含めるならば、承認が付与されるまでユーザタスクが完了しない、というものになります。また、もし承認されなかった場合には、変更済の部分を元に戻す必要があるでしょう。システムを設計する場合には、ユーザのタスクが完了するまでのインタラクションをすべて考慮しなければなりません。

結論

ビジネスルールは、アプリケーションがドメインに関して所持している知識を表現するものです。ビジネスルールの適切な構造は、開発者のコードの理解を容易にすると同時に、その責務に応じて様々なカテゴリに分類する必要があります。また、ユーザタスクを表現するようにコードを構成すれば、開発者が理解する必要のあるコンセプトの数は小さくなります。ビジネスルールはシステム設計に依存するため、ソリューションアーキテクトは設計の有用性を考慮しなければなりません。

著者について

Fabian Lopez氏はソフトウェアエンジニアです。氏はジョージア工科大学で、コンピュータ科学の修士号を取得しています。現在はInter-American Development Bankのソリューションアーキテクトとして、銀行業界におけるプロセス管理アプリケーションを設計しています。Lopez氏は、開発上の多くの問題を解決するための基準点を提供してくれるという理由から、ソフトウェアパターンの作成と活用に注力するとともに、ユーザパターンを特定し、ユーザにとって有益なソリューションを開発するために、定期的にユーザ調査に参加しています。かねてから氏は、アプリケーションを使用するユーザを失ったことで数多くの優れた技術的ソリューションが失敗に終わり、結果としてソリューションの品質に対する認識の低下を招いている、という指摘をしています。

 

この記事に星をつける

おすすめ度
スタイル

BT