私は現在、共通の機能を共有する複数のかなり複雑なシステムの設計段階にあります(たとえば、両方に顧客関係管理(CRM)と販売機能があります)。したがって、ドメインの共通部分を抽出して、両方のアプリケーションで再利用しようとしています。
アプリケーションAとアプリケーションBがあり、どちらもCRM機能を使用しているとします。ほとんどの場合、CRMの機能は同じですが、どちらのアプリケーションもCRMに関連するいくつかの機能を強化することを好みます。
CRMシステムの基本バージョンを実装するライブラリを作成したいと思います。たとえば、顧客は次のように抽象化されます。
interface ICustomer {
string CustomerNumber {get;set;}
}
ベースライブラリにはICustomerの基本的な実装があります
class Customer: ICustomer
アプリケーションAはこれを拡張できるようになりました。
interface IACustomer : ICustomer {
bool ReceivesNewsletter {get;set;}
}
class ACustomer : Customer, IACustomer {
...
}
同様に、Bには独自のバリエーションがあります。
interface IBCustomer : ICustomer {
string NickName {get;set;}
}
class BCustomer : Customer, IBCustomer {
....
}
抽象化の目的で、ベースライブラリで具象型をインスタンス化することはありませんが、ファクトリまたはDIコンテナを使用します。例:
interface ICrmFactory {
ICustomer CreateCustomer();
}
AとBは、ACustomersまたはBCustomersがそれぞれ作成されるように、それに応じてファクトリを実装します。
これが私が意味するUML図です(アプリケーションBは表示されていません):
永続性のために、NHibernateを使用します。AとBはどちらも、追加のプロパティを含めるための独自のマッピング(コードによるマッピング)を提供します。さらに、AはIACustomerをACustomerのプロキシタイプとして定義し、BはIBCustomerをBCustomerのプロキシタイプとして定義します。
これで、NHibernateを使用して、AとBのエンティティ(たとえばA)を操作できます。
session.QueryOver<ACustomer>()
.Where(c=>c.ReceivesNewsletter)
.List()
ここで、ベースライブラリ(たとえば、ある種のサービスオブジェクト)の顧客と何かをしたいとします。非常に単純なバージョンのプロトタイプを作成しましたが、これまでのところ、これは正常に機能しているようです。
session.QueryOver<ICustomer>()
.Where(c => c.CustomerNumber == "1234ABC")
.List()
つまり、QueryOverで特定のエンティティのプロキシタイプの基本クラスを使用でき、NHibernateは正しいクエリを作成します(例:A)。
SELECT
this_.Id as Id0_0_,
this_.CustomerNumber as Customer2_0_0_,
this_.ReceivesNewsletter as Receives3_0_0_
FROM
ACustomer this_
WHERE
this_.CustomerNumber = @p0;
@p0 = '1234ABC' [Type: String (4000)]
私の質問
これらのクエリは常に期待どおりに機能しますか?基本ライブラリのクエリで、プロキシインターフェイスの基本タイプを常に安全に使用できますか?NHibernateは常に取得する「正しい」エンティティタイプとテーブルを見つけますか?または、これがクエリの効率に悪影響を与える状況がありますか?b / c NHibernateは推測作業を行う必要がありますか?このシナリオで知っておくべき他の落とし穴はありますか?
ドキュメントでこれに関する情報を見つけることができませんでした。このアプローチにより、一部のドメインの共通部分を独自のベースライブラリにきちんと移動できますが、確実に機能するようにしたいと思います。