Передача данных между бизнес-уровнем и уровнем доступа к данным – плохой код?
-
10-07-2019 - |
Вопрос
Я использую следующий код в классе JCProperty для получения данных из DAL:
Dim x As JCProperty
x = JCPropertyDB.GetProperty(PropertyID)
If Not x Is Nothing Then
Me.PropertyID = x.PropertyID
Me.AddressLine1 = x.AddressLine1
Me.AddressLine2 = x.AddressLine2
Me.AddressLine3 = x.AddressLine3
Me.AddressCity = x.AddressCity
Me.AddressCounty = x.AddressCounty
Me.AddressPostcode = x.AddressPostcode
Me.TelNo = x.TelNo
Me.UpdatedOn = x.UpdatedOn
Me.CreatedOn = x.CreatedOn
Me.Description = x.Description
Me.GUID = x.GUID
End If
Это работает нормально, но требует, чтобы объект DAL (JCPropertyDB) знал о бизнес-объекте (JCProperty), и я эффективно создаю и заполняю один и тот же объект дважды (один раз в DAL, чтобы вернуться в BL, а затем снова в объекте BL, чтобы заполнить сам).
Мне здесь что-то не хватает, я знаю, что должен быть лучший способ!
Фактически мне нужно назначить «Me = x», что запрещено.Может кто-нибудь меня пояснить?
Решение
Лично я ленив.Обычно я делаю что-то вроде:
class JCProperty : inherits JCPropertyDB
{
New()
{
MyBase.New()
GetProperty(PropertyID)
}
}
Тогда все, по сути, готово, пока у вас не появится какая-то дополнительная функциональность в классе JCProperty, которая должна быть реализована «поверх» функциональности, уже существующей в JCPropertyDB.Затем вы переопределяете методы JCPropertyDB, чтобы сначала вызвать базовый метод, а затем добавить новые функции.
Рон
Другие советы
Вы находитесь на правильных линиях, однако немного пропускаете одну точку.
Обычно ваш уровень доступа к данным (DAL) возвращает объекты передачи данных (DTO) из вашей базы данных. Это простые старые объекты CLR (POCO), которые не содержат бизнес-логики, просто свойства более или менее соответствуют таблицам базы данных.
Тогда у вас будет код, который создает модель домена из этих DTO, называемых Картограф данных . Классы в доменной модели могут иметь похожие имена (например, CustomerDTO -> Customer), но в дополнение к данным они будут содержать правила проверки и, возможно, другую бизнес-логику.
Именно эту модель домена вы затем используете на своем бизнес-уровне, а не фактические DTO. Это означает, что если вы изменяете DTO, возвращаемые из DAL (то есть, внедряя новый инструмент ORM), вам нужно всего лишь изменить свой Data Mapper, при условии, что модель данных останется прежней.
Я рекомендую поискать шаблоны доступа к данным «Шаблоны архитектуры корпоративных приложений» Мартина Фаулера . / р>
Не уверен, что это ответит на ваш вопрос, но важно отметить, что модель домена не зависит от отображения и не зависит от хранилища. Это часто обозначается как разделение интересов. Идея состоит в том, чтобы ослабить связи и создать простую систему, в которой объекты не имеют несколько совершенно разных обязанностей.
Поэтому я хотел бы позволить DAL напрямую создавать бизнес-объекты, но при этом убедиться, что я не загрязняю свои бизнес-объекты чем-либо, связанным с DAL. Точно так же я не хочу загрязнять их специфическими для пользовательского интерфейса вещами, такими как HTML.
На мой взгляд, все в порядке, что и бизнес-уровень, и DAL-уровень и UI-уровень имеют зависимости от модели предметной области, однако не вполне нормально иметь зависимости от модели предметной области и от этих других компонентов.
Чтобы ослабить муфты, вам может помочь что-то Spring или любой другой контейнер для инъекций Dependency вместе с интерфейсами и проводкой.
Восстанавливая один и тот же объект в каждом слое, вы нарушаете принцип СУХОГО (не повторяйте себя) и вводите код котельной пластины и увеличиваете вероятность появления ошибки где-либо.
Проверить: http://www.icemanind.com/layergen.aspx р>
Я принимал BO и отправлял обратно BO из DAL через модель моста и модель провайдера. Я не вижу смысла в DTO, если не боюсь тяжелой сериализации (скажем, веб-службы или JSON). Мой подход состоял в том, чтобы абстрагировать уровень данных и бизнес-уровень через интерфейс и предоставить анонимный уровень данных, который подается в бизнес-объект. Это означает, что я могу подключить любой уровень данных, реализовать интерфейс, который имеет универсальные методы Load и Save и который затем доступен через уровень моего домена. В BL нет кода DAL - просто вызов предоставленного и абстрагированного уровня данных. Мой вызов уровня данных управляется шаблоном провайдера (без прямой ссылки), и я просто делаю:
public class Person : IBusinessObject<Person>
{
protected IDataLayer<T> dataLayer;
Person Load() { this.dataLayer.Load(this); }
}
в слое данных у меня есть ...
public class PersonMapper : IDataLayer<Person>
{
Person Load(Person person) {
...get DB stuff...map to person...decorate object...
return person;
}
}
Я до сих пор не знаю, хорошо ли это, но у меня это хорошо работает. Мне удалось получить ленивую загрузку для вложенных объектов с помощью отражения.