Trochę wiedzy domenowej
Piszę oprogramowanie POS (Point Of Sales), które pozwala płacić towary lub zwracać je. Płacąc lub zwracając pieniądze , należy określić, z którego przelewu pieniężnego korzystać: gotówka, EFT (~ = karta kredytowa), karta lojalnościowa, kupon itp.
Te środki przekazu pieniężnego są skończonym i znanym zestawem wartości (rodzaj wyliczenia).
Problem polega na tym, że muszę mieć możliwość przechowywania niestandardowego podzbioru tych środków na potrzeby płatności i zwrotów (oba zestawy mogą być różne) na terminalu POS.
Na przykład:
- Dostępne środki płatności: gotówka, EFT, karta stałego klienta, kupon
- Dostępne zwroty oznaczają: gotówka, kupon
Aktualny stan realizacji
Wybieram wdrożenie koncepcji przekazu pieniężnego w następujący sposób:
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...
}
Powodem, dla którego nie jest to „zwykły wyliczenie” jest to, że istnieje pewne zachowanie wewnątrz tych klas. Musiałem także zadeklarować klasy wewnętrzne jako publiczne (zamiast prywatne), aby odwoływać się do nich w mapowaniu FluentNHibernate (patrz poniżej).
Jak to jest używane
Zarówno środki płatności, jak i środki zwrotu są zawsze przechowywane lub pobierane w / z DB jako zestaw. Są to tak naprawdę dwa odrębne zestawy, chociaż niektóre wartości w obu zestawach mogą być takie same.
Przypadek zastosowania 1: zdefiniuj nowy zestaw środków płatności / zwrotu
- Usuń wszystkie istniejące środki płatności / zwrotu
- Wstaw nowe
Przypadek użycia 2: odzyskaj wszystkie środki płatności / zwrotu
- Uzyskaj zbiór wszystkich przechowywanych środków płatności / zwrotów
Problem
Utknąłem z obecnym projektem dotyczącym aspektu trwałości. Używam NHibernate (z FluentNHibernate do deklarowania map klas) i nie mogę znaleźć sposobu na mapowanie go na jakiś prawidłowy schemat DB.
Odkryłem, że możliwe jest mapowanie klasy wiele razy przy użyciu encji-nazwy jednak nie jestem pewien, czy jest to możliwe w przypadku podklas.
Nie jestem gotowy, aby zmienić publiczny interfejs API MoneyTransferMean, aby móc go utrzymać (na przykład dodanie bool isRefund
rozróżnienia między nimi). Jednak dodanie jakiegoś prywatnego pola dyskryminującego jest w porządku.
Moje obecne mapowanie:
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...
To mapowanie kompiluje się, ale generuje tylko 1 tabelę i nie jestem w stanie rozróżnić płatności / zwrotu przy zapytaniu o tę tabelę.
Próbowałem zadeklarować dwa odwzorowania odwołujące się zarówno MoneyTransferMean
do innej tabeli, jak i nazwy encji, ale prowadzi mnie to do wyjątkuDuplicate class/entity mapping MoneyTransferMean+CashMoneyTransferMean
.
Próbowałem również powielić mapowania podklas, ale nie jestem w stanie określić „mapowania nadrzędnego”, co prowadzi mnie do tego samego wyjątku jak powyżej.
Pytanie
Czy istnieje rozwiązanie pozwalające zachować moje obecne domeny?
Jeśli nie, to jaki byłby najmniejszy refaktor, który muszę wykonać na moich podmiotach, aby były trwałe w 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).
: Dlaczego nie? To prosta i słodka zmiana, która powinna rozwiązać twój problem. Można uzupełnić z trzech możliwych wartości (choć dwa zrobi z duplikatów zapisów lubFlag
typ):Payment
,Refund
,Both
. Jeśli dwie wartości Ci odpowiadają,bool
właściwość jest świetna.