9

私が「作業単位」の概念を完全に理解していない可能性があります(おそらく)。基本的に、私はそれをオブジェクト指向環境で使用される一種の広範なトランザクションと見なしています。作業単位を開始し、オブジェクトを操作し、コミットまたはロールバックします。しかし、これはどのようにしてそれらのオブジェクトの背後にあるデータストアの実際のトランザクションに分解されますか?

単一のDBとORM(NHibernateなど)を備えたシステムでは、それは簡単です。トランザクションはORMを介して維持できます。しかし、カスタムドメインモデルが多くの異なるデータソースを覆い隠しているシステムについてはどうでしょうか。そして、それらのデータソースのすべてがリレーショナルデータベースではありませんか?(このあたりのファイルシステムでは多くのことが行われています。)

今のところ、「SQL2005 DB、SQL2000 DB、DB2 DB、およびファイルシステムをすべて同じ「アトミック」なビジネスオペレーションでトランザクションを維持することはできない」という考えに固執しています。したがって、今のところ、コード内でトランザクションを手動で維持するのは、チームの開発者(通常は互いに独立して作業する)の責任です。各DBには適切なトランザクションを含めることができますが、全体としてのビジネスオペレーションは手動でチェックされ、重要なステップごとにバランスが取られます。

ただし、ドメインの複雑さが増し、標準の開発者の交代が進むにつれて、このアプローチはますます困難になり、時間の経過とともにエラーが発生しやすくなります。

このようなドメインにどのように対処するのが最適か、または以前にどのように対処したかについて、アドバイスや例はありますか?この場合の実際の「ドメイン」はまだ初期段階にあり、プロトタイプとして進化し、ある日、異種のレガシーアプリケーションの大規模なエコシステムを拡張および消費/置換します。したがって、再設計とリファクタリングの余地は十分にあります。

参考までに、私が現在目指している設計の10,000フィートのビューは、次のとおりです。中央のメッセージベースのサービスを呼び出す、可能な限り小さなクライアントアプリケーションの大規模なコレクション。このサービスは「ドメインコア」への入り口であり、1つの大きなMVCスタイルのアプリケーションと考えることができます。リクエストはサービスに対して行われ(「アクション」のように)、ハンドラー(「コントローラー」のように)によって取得されます。手続き的なものは何でもそこに行きます。それらは、すべてのビジネスルールを含むモデルと相互作用します。モデルは、リスナー(「サービス」?この部分はまだ設計が曇っており、改善される可能性があります)がリポジトリ(データベースx、データベースy、ファイルシステム、電子メール、外部リソース)と対話することによって取得および処理するイベントを公開します。すべての陽気に依存関係-それに応じて注入されます。

すべての冗長性について申し訳ありません:)しかし、誰かが何かアドバイスがあれば、私はそれを聞いてみたいです。(特に)そのアドバイスが「あなたのデザインが悪いなら、代わりにこれを試してみてください...」であるとしても、ありがとう!

4

1 に答える 1

10

私は以前、これを実現できるシステムに取り組んでいましたが、それはかなり簡単です。あなたのプロジェクトは初期段階にあるので、おそらくこれはあなたにとって有用な情報かもしれません。残念ながら、私はコードにアクセスできなくなりましたが、それでもコードがどのように機能するかを説明することに慣れています。

私が行ったことは、一般的なリポジトリパターンの実装を使用してリポジトリを構築することでした。基本リポジトリタイプは、常にサービスとUoWによる参照になります。説明のために、これをBaseRepositoryと呼びます。「T」は、ドメインオブジェクトを示すIEntity実装に制限されます。BaseRepositoryから、SqlBaseRepository、XmlBaseRepositoryなど、合成用の別の基本クラスのセットを作成しました。

UoWは、コア機能が存在する場所であるBaseRepositoryタイプのもののみを考慮します。(CRUDの)基本的なCUDが表され、Creates、Updates、およびDeletesに相当するものが提供されます。これらのそれぞれが行うことは、デリゲートを作成してUoW内のキューに配置し、トランザクションのタイプに関する情報と、それを完了するために必要な適切なデータを渡すことです。UoWは、トランザクションに関与する必要のあるリポジトリのリストの維持を開始しましたが、それでもそれがどのタイプであるかは気にしませんでした。事実上、ここでキューに入れることは、トランザクションに参加するようなものです。

BaseRepositoryは、.ApplyChange()のようなものと呼ばれる抽象メソッドを定義しました。UoWで.Commit()が呼び出されると、TransactionScope()が作成され、リスト内の遅延の呼び出しが開始され、情報が.ApplyChange()に返されます。.ApplyChange()の実際の実装は、特定のリポジトリベース、つまりSqlRepositoryBaseなどに存在し、実装によってオーバーライドされる可能性もあります。

トリッキーになったのは、少なくとも私にとっては、ロールバックでした。私は単一のデータベースのみを扱いましたが、ファイルベースの変更が行われることもありました。.RevertChange()メソッドを追加し、元の状態と変更された状態の追跡を開始して、基本的に逆デルタを適用してファイルスタックの元の場所に戻ることができるようにしました。

実装についてもっと具体的にしたいと思いますが、コードを見てから1年以上経ちました。元のコードの基礎は、TimMcCarthy著の著書「.NETDomain-DrivenDesign with C#:Problem-Design-Solution 」から生まれたと言えます。私のリポジトリ実装の大部分は彼の例に基づいており、私のカスタマイズの大部分はUoWとその実装に取り​​入れられています。

それがお役に立てば幸いです。:-)

于 2010-09-03T12:18:01.060 に答える