Трохи доменних знань
Я пишу POS (Point Of Sales) програмне забезпечення, яке дозволяє оплатити товари або повернути їх. Під час оплати чи повернення коштів потрібно вказати, який грошовий переказ означає використовувати: готівка, EFT (~ = кредитна картка), картка лояльності, ваучер тощо.
Ці засоби грошових переказів є кінцевим і відомим набором значень (свого роду перерахунок).
Складна частина полягає в тому, що мені потрібно вміти зберігати користувальницьку підмножину цих коштів як для платежів, так і для повернення коштів (два набори можуть бути різними) на POS-терміналі.
Наприклад:
- Доступні засоби оплати: готівка, EFT, картка лояльності, ваучер
- Доступні кошти повернення коштів: готівка, ваучер
Поточний стан виконання
Я вирішую реалізувати концепцію грошових переказів таким чином:
public abstract class MoneyTransferMean : AggregateRoot
{
public static readonly MoneyTransferMean Cash = new CashMoneyTransferMean();
public static readonly MoneyTransferMean EFT = new EFTMoneyTransferMean();
// and so on...
//abstract method
public class CashMoneyTransferMean : MoneyTransferMean
{
//impl of abstract method
}
public class EFTMoneyTransferMean : MoneyTransferMean
{
//impl of abstract method
}
//and so on...
}
Причина, що це не «звичайний перелік», полягає в тому, що існує певна поведінка, яка є всередині цих класів. Я також повинен був оголосити внутрішні класи загальнодоступними (замість приватних) для того, щоб посилатися на них у FluentNHibernate mapping (див. Нижче).
Як воно використовується
І засоби оплати, і кошти повернення завжди зберігаються або отримуються в / з БД як набір. Вони справді є двома різними наборами, хоча деякі значення всередині обох наборів можуть бути однаковими.
Використовуйте випадок 1: визначте новий набір засобів оплати / відшкодування
- Видаліть усі існуючі засоби оплати / повернення коштів
- Вставте нові
Використовуйте випадок 2: отримайте всі засоби оплати / відшкодування
- Отримайте колекцію всіх збережених засобів оплати / повернення коштів
Проблема
Я застряг у своєму теперішньому дизайні на аспект стійкості. Я використовую NHibernate (з FluentNHibernate для оголошення карт класу), і я не можу знайти спосіб відобразити його до якоїсь дійсної схеми БД.
Я виявив, що можна кілька разів зіставити клас за допомогою імені сутності, однак я не впевнений, що це можливо з підкласами.
Те, що я не готовий зробити, - це змінити громадський API MoneyTransferMean, щоб мати змогу зберігати його (наприклад, додавати bool isRefund
для розмежування двох). Однак додавати поле приватного дискримінатора чи так це нормально.
Моє поточне відображення:
public sealed class MoneyTransferMeanMap : ClassMap<MoneyTransferMean>
{
public MoneyTransferMeanMap()
{
Id(Entity.Expressions<MoneyTransferMean>.Id);
DiscriminateSubClassesOnColumn("Type")
.Not.Nullable();
}
}
public sealed class CashMoneyTransferMeanMap : SubclassMap<MoneyTransferMean.CashMoneyTransferMean>
{
public CashMoneyTransferMeanMap()
{
DiscriminatorValue("Cash");
}
}
public sealed class EFTMoneyTransferMeanMap : SubclassMap<MoneyTransferMean.EFTMoneyTransferMean>
{
public EFTMoneyTransferMeanMap()
{
DiscriminatorValue("EFT");
}
}
//and so on...
Таке зіставлення складається, однак воно створює лише 1 таблицю, і я не в змозі розмежувати платіж / відшкодування при запиті до цієї таблиці.
Я намагався оголосити два відображення, посилаючись MoneyTransferMean
на різні таблиці та ім’я сутності, однак це призводить мене до виключення Duplicate class/entity mapping MoneyTransferMean+CashMoneyTransferMean
.
Я також намагався дублювати відображення підкласів, але я не можу вказати "батьківське відображення", що призводить мене до того ж винятку, що і вище.
Питання
Чи існує рішення для збереження моїх поточних об'єктів домену?
Якщо ні, то який би найменший рефактор, який мені потрібно виконати для моїх утворень, щоб зробити їх стійкими з NHibnernate?
What I'm not ready to do is to alter the MoneyTransferMean public API to be able to persist it (for example adding a bool isRefund to differentiate between the two).
: Чому ні? Це проста і мила зміна, яка повинна вирішити вашу проблему. Ви можете зробити з трьома можливими значеннями (хоча два і буде робити з дублюванням записів абоFlag
типу):Payment
,Refund
,Both
. Якщо два значення для вас,bool
властивість чудова.