アプリケーションには3つのレイヤーがあります。外部APIを提供するサービス層。ビジネスロジック用のBOレイヤー、およびデータベース接続用のDAOレイヤー。
たとえば、ファイルを更新するたびに、フォルダー内の何かを変更したいとします。たとえば、「最終更新日」などです。これはトランザクションで行う必要があります。成功し、ファイルとフォルダの両方が編集されます。または、障害が発生してトランザクションがロールバックされ、両方のオブジェクトが前の状態になります。
「ファイルが編集されたときにフォルダを編集する」アクションは、純粋にビジネスロジックです。つまり、これはBOレイヤーに属していることになります。ただし、データベースにはObjectifyを使用しているため、トランザクションを開始するには、ofy()。transact(...)を呼び出す必要があります。この関数をBOレイヤーで呼び出すと、ビジネスレイヤーにデータベース固有の呼び出し(Objectify)が存在するため、デザインが壊れます。
この問題のクリーンな解決策は何でしょうか?
トランザクションをカットする方法は、確かにビジネスロジックです。したがって、DAOレイヤーが、あなたが言及したtransact
メソッド(およびおそらくcommit
やrollback
など)のためのdbフレームワークに依存しないAPIを提供できるようにします。その後、データベースやデータベースフレームワークに依存せずに、BOレイヤーから使用できます。
Objectify は、アトミックのようなトランザクション( Google Application Engine Transactions )用に設計されています。 トランザクション管理の独自の抽象化を開発する必要があります。
この場合。抽象化が続くトランザクション管理を上位層に委任するにはどうすればよいですか?
@DocBrownアプローチは、指定されたアーキテクチャー(レイヤードアーキテクチャー)に実装するためのより高速でよりクリーンなソリューションを私に見えます。
アプリケーションとそのコンテキストに関する情報が不足しているため、Docのソリューションが最も安全であるように思われます。
ただし、 UnitOfWorkビジネスレイヤーのデザインパターンを確認することをお勧めします。 Objectify が意図するトランザクション管理に適していると思います。
簡単にまとめると、このパターンはビジネスルールをBusiness Transactions(作業単位)にカプセル化することを目的としています。このパターンはB.Ts間の継承を許可しますが、これまでのところ、Objectifyも継承しています。作曲もサポートします。したがって、構成または継承のいずれかによって、アプローチは複雑なB.Tsを許可します。
特定のアーキテクチャに適用すると、次のようになります。
FileService -> FileBO : new EditFileTransaction().execute()
|-> ofy().transact(...)
|--> FileDAO.actionA()
|--> FolderDAO.actionA()
|-> [ofy().commit(...)|ofy().rollback()]