Как уменьшить дублирование объектов домена/объекта/DTO?
Я в процессе пересмотра моего текущего проекта, чтобы быть более ремонтопригодным, и прилагаю все усилия, чтобы следовать хорошей практике проектирования. В настоящее время у меня есть решение с компонентом Silverlight, хостом ASP.Net для упомянутого приложения SL, которое также содержит службу WCF RIA и библиотеку с общим классом, поэтому SL и WCF-служба могут обмениваться объектами. Бизнес-логика разбросана по всему месту, и все операции CRUD кодируются вручную в моих WCF-сервисах. Итак, я создаю новую структуру для всего и переношу этот беспорядок в новый формат. В процессе выполнения этого я нахожу, что я дублирую классы, когда не знаю, должен ли я быть.
Моя новая структура выложена как таковая:
Клиент:
Reporting.Silverlight = приложение Silverlight. Это будет ссылка на мои классы DTO.
Reporting.Web = держит мое приложение SL и является основной точкой входа для людей, чтобы добраться до него.
Бизнес:
Reporting.Services = Мои службы WCF живут здесь. Мое приложение SL сделает вызовы для этого, чтобы сделать материал, и эти службы вернут классы DTO.
Reporting.Services.Contracts = Удерживает мои интерфейсы для служб WCF и содержит классы DTO с декораторами DataContract.
Reporting.Domain = хранит мои объекты домена и бизнес-логику
Данные:
Reporting.Data.Contract = хранит мои интерфейсы для хранилища и единицы работы
Reporting.Data = Конкретная реализация репозитория /UoW. Контекст Entity Framework 5 определен здесь.
Reporting.Data.Models = Сохраняет все мои объекты Entity, поэтому EF5 может выполнять свою задачу с помощью SQL.
У меня 3 места, где у меня почти такой же класс, и для меня это пахнет. Внутри Reporting.Services.Contracts У меня есть DTO, который передается клиенту SL. Вот пример:
[DataContract(Name = "ComputerDTO")]
public class ComputerDTO
{
[DataMember(Name = "Hostname")]
public string Hostname { get; set; }
[DataMember(Name = "ServiceTag")]
public string ServiceTag { get; set; }
// ... lots more
}
Я думаю, что вышеупомянутый DTO прекрасен, поскольку это всего лишь куча свойств, которые передаются клиенту SL. Подавляющее большинство моих свойств DTO сопоставляются с собственными объектами объектов Entity 1:1, за исключением полей ID. Вот мой объект Entity, который соответствует указанному выше DTO:
[Table("Inventory_Base")]
public class ComputerEntity
{
// primary key
[Key]
public int AssetID { get; set; }
// foreign keys
public int? ClientID { get; set; }
// these props are fine without custom mapping
public string Hostname { get; set; }
public string ServiceTag { get; set; }
// ... plus a bunch more in addition to my navigation properties
}
Я использую первый подход кода с EF5. Я все еще нахожусь на начальных этапах моей перезаписи, и до сих пор у меня сложилось впечатление, что бизнес-логика НЕ должна быть внутри моего EF Entity. У DTO также не должно быть бизнес-логики. Это означает, что он входит в мою модель домена, верно? Ну, это дает мой третий почти идентичный класс в Reporting.Domain
public class Computer
{
public string Hostname { get; set; }
public string ServiceTag { get; set; }
// ... lots more, pretty much mirrors the DTO
public string Method1(string param1)
{
// lots of methods and logic go in here
}
}
Имея 3 почти одинаковых класса, возможно, не может быть правильным способом, чтобы это сделать, не так ли? Должен ли я помещать всю свою бизнес-логику в объект EF, а затем проецировать результат в DTO, который проходит через провод? Если было бы хорошей идеей перерезать всю мою доменную/бизнес-логику внутри классов сущностей EF, структурно я должен перенести эту сборку на свой бизнес-уровень и за пределы моего уровня данных, даже если эти объекты будут сохранены в моей базе данных? В идеале я пытаюсь сохранить ссылки на Entity Framework, содержащиеся в моих проектах с данными и вне моих бизнес-проектов. У меня около 200 или около того классов, которые я переношу и буду содержать мой домен, и я ожидаю, что эта вещь будет масштабироваться до гораздо большей функциональности, как только я получу эту перезапись. Любое понимание того, как структурировать эту вещь и сохранить ее DRY, было бы высоко оценено.
В случае, если это поможет определить, что я пытаюсь сделать лучше, сообщите мне, следует ли мне включить мою методологию репозитория /unitofwork, за которой я следую.
Ответы
Ответ 1
Наличие 3 почти одинаковых классов не может быть правильным способом пойдите об этом, не так ли?
ИМО они не "3 почти одинаковые классы", они не служат той же цели. Они представляют собой несколько аспектов одного и того же понятия домена, каждый из которых предназначен для нужд определенного уровня.
Это цена за модульность и четкое разделение проблем. Чем больше портов (как в Шестиугольной архитектуре, чем больше портов и адаптеров), тем больше фактов вам понадобится и больше сопоставления вам придется делать.
Хорошая статья об этом: http://blog.ploeh.dk/2012/02/09/IsLayeringWorththeMapping/