Короче говоря, да, это приемлемо.
Однако, как вы можете видеть в комментариях и других ответах, не все согласны здесь.Итак, позвольте мне объяснить мой ответ.
Аргумент 1 - вводит в заблуждение потребителя
И теперь есть второй Api, который принимает тот же dto, но в этом вызове APIЯ использую только Streer1, Street2, Contact
, все остальные игнорируются.
Проблема заключается в том, чтобы прояснить ваши намерения.Если вы разрешаете потребителю отправлять вам полностью развернутый текст AddressDTO
, но затем используете только часть свойств, то вы вводите своего потребителя в заблуждение.Вы заставили их думать, что другие свойства имеют отношение.
Это фактически то же самое, что:
public int AddNumbersTogether(int a, int b, int c, int d)
{
return a + c + d; //we ignore b
}
Нет никаких оснований для существования b
.Любой, кто использует этот метод, будет чесать голову, когда AddNumbersTogether(1,2,3,4)
возвращает значение 8
.Синтаксис противоречит поведению.
Да, параметр неиспользуемого метода легче опустить, чем разрабатывать второй DTO.Но вы должны быть последовательны и придерживаться того же принципа: не вводить в заблуждение потребителя .
Аргумент 2 - DTO не является сущностью
Взаимодействие вашего потребителя с вашими API-интерфейсами должно происходить без того, чтобы потребитель ничего не знал о структуре записей вашей базы данных.
Именно поэтому вы используете DTO, а не класс сущностей для начала.!Вы обеспечиваете логическое разделение между выполнением действия и хранением данных этого действия.
Потребителю все равно, где хранятся данные.Независимо от того, сохраняете ли вы улицу в той же таблице, что и адрес, или в другой таблице (или базе данных) в целом, не имеет значения в области действия потребителя, вызывающего метод API.
Аргумент 3 - Противодействие S.Akbari
А как насчет наследования и / или принципа разделения интерфейса в SOLID ?- S.Akbari
Это недопустимые аргументы для данного конкретного случая.
Наследование является ошибочным подходом.Да, вы можете технически сделать что-то вроде AddressDto : AddressDtoForSecondAPI
в опубликованном примере кода, но это огромный запах кода.
Что происходит, когда нужен третий DTO, например тот, где толькопочтовые индексы и названия городов используются?Вы не можете иметь AddressDto
наследовать от нескольких источников, и нет логического перекрытия между AddressDtoForSecondAPI
и вновь созданными AddressDtoForThirdAPI
.
Интерфейсы не являются решением здесь.Да, вы могли бы технически создать интерфейс IAddressDtoForSecondAPI
и IAddressDtoForThirdAPI
с соответствующими полями, а затем сделать что-то вроде AddressDto : IAddressDtoForSecondAPI, IAddressDtoForThirdAPI
.Однако это тот же самый массивный запах кода снова.
Что произойдет, если у второго и третьего варианта будет несколько общих свойств и несколько отдельных?Если вы применяете сегрегацию интерфейса, то перекрывающиеся свойства должны быть абстрагированы в интерфейсе сами по себе.
Если затем появляется четвертый вариант, который имеет некоторые общие свойства со вторым вариантом, некоторые с третьим вариантом, некоторые си во втором, и в третьем варианте, и в некоторых отдельных свойствах, вам потребуется создать еще больше интерфейсов!
Учитывая достаточно вариантов одного и того же объекта и многократно применяя принцип разделения интерфейса;вы получите интерфейс для каждого свойства объекта;что требует смешного количества накапливания.В итоге вы получите что-то вроде:
public class AddressDto : IAddressCity, IAddressCountry, IAddressContact, IAddressStreet1, IAddressStreet2, IAddressState, IAddressZip
{
public string City { get; set; }
public string Country { get; set; }
public string Contact { get; set; }
public string Street1 { get; set; }
public string Street2 { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
Представьте, что вам нужно сделать это для всех классов;поскольку тот же принцип применим к каждому DTO, используемому API.
Аргумент 4 - DRY здесь не применяется
Я понимаю, почему вы 'опасаются создания двух классов.Скорее всего, у вас в голове поднимается флаг ошибки СУХОЙ / ВЛАЖНОЙ.
Избегать WET - хороший рефлекс;но ты не всегда можешь это слушать.Потому что, если вы действительно избегаете дублирования, вам также не следует создавать отдельные сущности и классы DTO, поскольку они обычно являются копиями / вставками друг друга.
DRY не является абсолютным,Принимая пример сущности / DTO, здесь есть баланс соображений:
- Хотите ли вы избежать повторения любой ценой?(= СУХОЙ)
- Хотите отделить свой DAL от логики API?(= разделение интересов)
В этом случае последний обычно выигрывает.
В вашем случае применяется тот же аргумент.Аргумент против после DRY (это аргументы, которые я только что перечислил) far перевешивает преимущества следования за DRY в этом сценарии.