システム内のエンティティにカスタム フィールドをアタッチする方法に関連する重要な設計上の問題に直面しています。エンティティは C# で表され、RavenDB に永続化されます。ドメイン駆動設計のテナントに大まかに従っており、エンティティは集約ルートです。
[注: DDD アプローチにおけるカスタム フィールドのような一般的な機能の適切性に関する議論は避けたいと思います。正当なユーザーがエンティティに任意のデータを添付して表示する必要があると仮定しましょう。また、設計上の課題を説明するために、例を一般的なものにしました。:)]
私の質問は、フィールド定義とフィールド値インスタンスをどのようにレイアウトするのが最善かに関するものです。
Book と Author の集約ルートを持つドメインを想像してみてください。ユーザーが任意のデータ属性を Books と Authors のインスタンスにアタッチできるようにしたいと考えています。したがって、次のようなクラスでカスタム フィールドを定義できます。
public enum CustomFieldType
{
Text,
Numeric,
DateTime,
SingleSelect,
MultiSelect
}
public class CustomFieldDefinition
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public CustomFieldType Type { get; set; }
public Collection<string> Options { get; set; }
}
Bookにアタッチされた CustomFieldDefinition (CFD) には、次のような値が含まれる場合があります。
- ID: "BookCustomField\1"
- 名前:「フードコード」
- タイプ:テキスト
- 説明:「Foo Corp の特別な識別子。」
- タイプ:テキスト
- オプション: null
私が直面している最初の質問は、Book の各インスタンスに何を格納するかということです。選択肢は次のとおりです...
ローエンド:
CFD ID とインスタンス値のみを保存します
に
ハイエンド:
値とともにCFD全体を保存します
別のドキュメントにあるCFDを引き込まないとBookを表示できないため、「ローエンド」は悪いです。また、何らかの方法で CFD を変更すると、履歴文書の値の意味が変更されます。
多くの重複があるため、「ハイエンド」は悪いです。定義には選択可能なすべてのオプションが含まれているため、選択リスト CFD の場合、CFD はかなり重いものになる可能性があります。
最初の質問は...各ブックのドキュメントにどれだけ保存する必要があるかです。Book を表示するだけで十分です (ユーザーが CF 値を編集できるようにする場合は、CFD に戻ってオプションと説明を表示する必要があります)。
2 番目の質問は... 1 つのエンティティ タイプの CFD のコレクション全体を 1 つのドキュメントに保存するか、各 CFD を独自のドキュメントに保存する必要がありますか?
ドキュメントとしての各 CFD は、各 CFD の物事をシンプルに保ちます (特に、定義を無効にするなどの作業を開始するとき) が、Book CFD を Author CFD から分離する方法が必要です。これにより、エンティティを編集するたびに、エンティティに添付された CF ごとに 1 つのドキュメントをロードすることも強制されます。
1 つのドキュメント内の特定のタイプの CFD をすべて読み込むと、1 つのドキュメントだけを読み込むことができますが、非アクティブ化されたすべての定義も読み込むことになります。
3番目の質問...これを完全に実装するより良い方法はありますか?
4 番目の質問...この車輪を再発明する必要がないように、サンプルまたはオープン ソース ソリューションはありますか?