Комментарии 26
Так я не против базового класса. Я просто за то, что бы заменить механизм наследования, на механизм получения нужных контекстов.
Что имеется ввиду под получением контекстов? DDD bounded context?
Наследование обычно лучше всего отражает отношение "является", а контрагент является либо юрлицом, либо физлицом. Отдельные контексты можно выделить для ведения реестров юрлиц и физлиц, особенно если в системе они выступают не только в роли контрагентов, но в контексте договоров сущности "контрагент-физлицо" и "контрагент-юрлицо", являющиеся наследниками (абстрактной) сущности "контрагент" обычно всё равно удобнее, даже если "контрагент" хранит только идентификатор и тип, а наследники ещё и идентификатор в соответствующем реестре и больше ничего.
P.S. Это даже не привязываясь к хранению в РСУБД вообще и обеспечению ссылочной целостности малой кровью.
Лучше выделять контексты по нужде. Например, если в рамках контекста договоров нам нужно иметь физлиц не только в качестве контрагентов, но и в качестве своих сотрудников, то имеет смысл рассмотрение выделения физлиц в отдельный контекст или хотя бы агрегат с хранением в контексте договоров в сущностях "контрагент-физлицо" и "сотрудник" скалярных идентификаторов сущности "физлицо" из нового контекста/агрегата. С одной стороны избежим дублирования сущностей, с другой простота манипулирования объектным свойством "контрагент" для сущности "договор" останется.
Во второй части, с tpt, обойдены вниманием юрлица иностранных государств, физлица иностранных государств, граждане с видом на жительство…
Делаем ИП наследником физлица, возможно с каким-то общим интерфейсом (или тупо копипастой) с юрлицами, и дело в шляпе. Портят они сильно жизнь когда их пытаются вынести в отдельную категорию, или в подкатегорию юрлиц.
Это законодатели вырастили, а мы лишь моделируем :) В некоторых юрисдикциях подобного понятия нет или его контрагентов оно не касается, им безразлично приобретает физлицо что-то для личного потребления или для предпринимательской деятельности без образования юрлица — это исключительно проблемы его и государства.
И это в случае отношений в одну сторону, а когда еще и обратно в виде получения услуг или товаров от физиков, юриков и ИП — там свои нюансы.
p/s/ возможно скоро еще выделятся в отдельную сущность — самозанятые граждане =)
Если акцент на юриков, может получиться, что проще отнаследоваться от юрлица, и недостающее откопипастить с физиков.
Да, есть еще traits. Но и они не панацея.
И у наследования ИП от физика свои минусы. Насколько я понимаю, при наследовании от физлица, запись по ИП содержит только уникальные для ИП атрибуты, а фио и прочее на физике.
Как с точки зрения БД отличить покупку Васи от покупки ИП Васи? На сущности Покупка у атрибута Покупатель будет одиковый ID в обоих случаях.
Решение в лоб — для Васи запись в таблице "контагенты" с типом "контрагент-физлицо", для ИП Васи — "контрагент-физлицо-ИП" с дублированием персональных данных. Более сложное создание сущности "физлицо" на которое будут ссылаться "контрагент-физлицо" и "контрагент-физлицо-ИП" и, вероятно, "контрагент-юрлицо" в полях типа "гендир", "главбух", и даже "сотрудники".
А чем поведение всех этих типов отличается? Вы нам показали 3-4 abstract data type, которые отличаются только данными, но не поведением в контексте задачи.
Почему вообще кому-то надо знать детали того, что у организации есть атрибут1, а у физлица — атрибут2? Почему всех контрагентов нельзя подвести под единый интерфейс а-ля IContactSigner с одним методом sign(IContract contract)?
Как минимум могут (или даже должны) отличаться формы договоров. В одном, "и ФИО, одни реквизиты", в другом "и название, другие реквизиты, в лице ФИО, третьи реквизиты, действующего на основании четвертые реквизиты"
Да лепить можно чем угодно, главное что в предметной области это разные подтипы одного типа "контрагент". Собственно особо вариантов нет, по-моему — или "суперконтрагент", включающий все свойства всех подтипов, а также свойство подтипа, или наследование. Какие-то другие варинты, что в голову приходят будут лишь разновидностью одного или другого. А как на базу маппить дело десятое. Хорошо, если ссылочную целостность можно обеспечить внешним ключом, а нет — так и бог с ним. Может она и не нужна вовсе.
Signature { get;}
у контрагента. Это свойство ушло в IContractor
. Но, если бы общего поведения не было, то сделали бы pattern matching по всем наследникам.Я акцентировал внимание на том, что версия:
public virtual LegalContact LegalContact { get; set; }
public virtual PersonContact PersonContact { get; set; }
была хуже финального варианта с точки зрения хранения данных
Union Type, TPT, DDD, ORM и RDBMS