Архитектура для уровня доступа к бизнес-объектам / базе данных

StackOverflow https://stackoverflow.com/questions/118955

  •  02-07-2019
  •  | 
  •  

Вопрос

По разным причинам мы пишем новую библиотеку бизнес-объектов / хранения данных.Одним из требований этого уровня является разделение логики бизнес-правил и фактического уровня хранения данных.

Возможно иметь несколько уровней хранения данных, которые реализуют доступ к одному и тому же объекту - например, основной источник хранения данных "база данных", который реализует большинство объектов, и другой источник "ldap", который реализует объект Пользователя.В этом сценарии пользователь может необязательно приходить из источника LDAP, возможно, с немного иной функциональностью (например, невозможно сохранить / обновить объект User), но в остальном он используется приложением таким же образом.Другим типом хранилища данных может быть веб-служба или внешняя база данных.

Есть два основных способа, которыми мы рассматриваем реализацию этого, и мы с коллегой расходимся во мнениях на фундаментальном уровне, который является правильным.Я бы хотел получить несколько советов о том, какой из них лучше всего использовать.Я постараюсь, чтобы мои описания каждого из них были как можно более нейтральными, поскольку я ищу здесь несколько объективных точек зрения.

  • Бизнес-объекты являются базовыми классами, а объекты хранения данных наследуют бизнес-объекты.Клиентский код имеет дело с объектами хранения данных.

    В этом случае общие бизнес-правила наследуются каждым объектом хранения данных, и именно объекты хранения данных непосредственно используются клиентским кодом.

    Это подразумевает, что клиентский код определяет, какой метод хранения данных использовать для данного объекта, поскольку он должен явно объявить экземпляр для этого типа объекта.Клиентский код должен явно знать информацию о соединении для каждого используемого им типа хранилища данных.

    Если уровень хранения данных реализует другую функциональность для данного объекта, клиентский код явно знает об этом во время компиляции, потому что объект выглядит по-другому.Если метод хранения данных изменен, необходимо обновить клиентский код.

  • Бизнес-объекты инкапсулируют объекты хранения данных.

    В этом случае бизнес-объекты используются непосредственно клиентским приложением.Клиентское приложение передает базовую информацию о соединении на бизнес-уровень.Решение о том, какой метод хранения данных использует данный объект, принимается кодом бизнес-объекта.Информация о соединении будет представлять собой фрагмент данных, взятый из файла конфигурации (клиентское приложение на самом деле не знает / не заботится о его деталях), который может быть одной строкой подключения для базы данных или несколькими строками подключения для различных типов хранения данных.Дополнительные типы подключений к хранилищу данных также могут быть считаны из другого места - например, из таблицы конфигурации в базе данных, которая определяет URL-адреса различных веб-служб.

    Преимущество здесь заключается в том, что если к существующему объекту добавляется новый метод хранения данных, во время выполнения можно задать параметр конфигурации, определяющий, какой метод использовать, и он полностью прозрачен для клиентских приложений.Клиентские приложения не нужно изменять, если изменяется метод хранения данных для данного объекта.

  • Бизнес-объекты являются базовыми классами, объекты источника данных наследуются от бизнес-объектов.Клиентский код имеет дело в основном с базовыми классами.

    Это похоже на первый метод, но клиентский код объявляет переменные базовых типов бизнес-объектов, а статические методы Load()/Create()/etc для бизнес-объектов возвращают соответствующие объекты, типизированные для источника данных.

    Архитектура этого решения аналогична первому методу, но основное отличие заключается в том, что решение о том, какой объект хранения данных использовать для данного бизнес-объекта, принимается бизнес-уровнем, а не клиентским кодом.

Я знаю, что уже существуют библиотеки ORM, которые предоставляют часть этой функциональности, но, пожалуйста, пока не обращайте на них внимания (есть вероятность, что уровень хранения данных реализован с помощью одной из этих библиотек ORM) - также обратите внимание, что я намеренно не говорю вам, какой язык здесь используется, кроме того, что он строго типизирован.

Я ищу здесь несколько общих советов о том, какой метод лучше использовать (или не стесняйтесь предложить что-то еще) и почему.

Это было полезно?

Решение

могу ли я предложить другую альтернативу, возможно, с лучшей развязкой:бизнес-объекты использование объекты данных и объекты данных реализовать объекты хранения.Это должно сохранить бизнес-правила в бизнес-объектах, но без какой-либо зависимости от источника хранения или формата, позволяя объектам данных поддерживать любые требуемые манипуляции, включая динамическое изменение объектов хранения (напримердля онлайн/оффлайн манипуляций)

это относится ко второй категории выше (бизнес-объекты инкапсулируют объекты хранения данных), но более четко отделяет семантику данных от механизмов хранения

Другие советы

У вас также может быть видимость, чтобы ваш клиент не звонил в компанию напрямую.Кроме того, это создает общие точки входа в ваш бизнес.

Как уже было сказано, ваш бизнес не должен подвергаться воздействию ничего, кроме вашего DTO и Фасада.

ДА.Ваш клиент может иметь дело с DTO.Это идеальный способ передачи данных через ваше приложение.

Обычно я предпочитаю "бизнес-объект инкапсулирует объект данных / хранилище".Однако, вкратце, вы можете обнаружить высокую избыточность ваших объектов данных и бизнес-объектов, что может показаться нецелесообразным.Это особенно верно, если вы выбираете ORM в качестве основы вашего уровня доступа к данным (DAL).Но реальная отдача приходит в долгосрочной перспективе:жизненный цикл приложения.Как показано, нередко "данные" поступают из одной или нескольких подсистем хранения (не ограничиваясь СУБД), особенно с появлением облачных вычислений, и как это обычно бывает в распределенных системах.Например, у вас могут быть некоторые данные, поступающие из службы Restful, другой фрагмент или объект из СУБД, другой из XML-файла, LDAP и так далее.При таком понимании это подразумевает важность очень хорошей инкапсуляции доступа к данным со стороны бизнеса.Также позаботьтесь о том, какие зависимости вы предоставляете (DI) через свои c-tors и свойства.

Тем не менее, подход, с которым я играл, заключается в том, чтобы поместить "мясо" архитектуры в бизнес-контроллер.Рассматривая современный доступ к данным скорее как ресурс, чем традиционное мышление, контроллер затем принимает URI или другую форму метаданных, которые могут быть использованы для определения того, какими ресурсами данных он должен управлять для бизнес-объектов.Тогда бизнес-объекты САМИ ПО себе НЕ инкапсулируют доступ к данным;скорее, это делает контроллер.Это делает ваши бизнес-объекты легкими и специфичными и позволяет вашему контроллеру обеспечивать оптимизацию, компоновку, среду транзакций и так далее.Обратите внимание, что затем ваш контроллер будет "размещать" ваши коллекции бизнес-объектов, подобно тому, как это делают контроллеры многих ORM.

Кроме того, также рассмотрите управление бизнес-правилами.Если вы внимательно присмотритесь к своему UML (или модели в своей голове, как это делаю я : D ), вы заметите, что ваша модель бизнес-правил на самом деле является другой моделью, иногда даже постоянной (например, если вы используете движок бизнес-правил).Я бы подумал о том, чтобы позволить бизнес-контроллеру также фактически управлять вашей подсистемой правил и позволить вашему бизнес-объекту ссылаться на правила через контроллер.Причина в том, что реализации правил неизбежно часто требуют выполнения поиска и перекрестной проверки, чтобы определить достоверность.Часто для этого может потребоваться как расширенный поиск бизнес-объектов, так и поиск по внутренней базе данных.Рассмотрите возможность обнаружения дублирующихся объектов, например, там, где гидратирован только "новый" объект.Предоставив свои правила управлению вашему бизнес-контроллеру, вы сможете делать практически все, что вам нужно, не жертвуя этой приятной чистой абстракцией в вашей "модели предметной области".

В псевдокоде:

using(MyConcreteBusinessContext ctx = new MyConcreteBusinessContext("datares://model1?DataSource=myserver;Catalog=mydatabase;Trusted_Connection=True ruleres://someruleresource?type=StaticRules&handler=My.Org.Business.Model.RuleManager")) {

User user = ctx.GetUserById("SZE543");
user.IsLogonActive = false;
ctx.Save();
}

//a business object
class User : BusinessBase {
  public User(BusinessContext ctx) : base(ctx) {}

  public bool Validate() {
    IValidator v = ctx.GetValidator(this);
    return v.Validate();
  }
}

// a validator
class UserValidator : BaseValidator, IValidator {
 User userInstance;
 public UserValidator(User user) {
  userInstance = user;
 }

 public bool Validate() {
   // actual validation code here
   return true;
 }
}

Клиенты никогда не должны иметь дело непосредственно с объектами хранения.Они могут работать с DTO напрямую, но любой объект, имеющий какую-либо логику для хранения, которая не заключена в ваш бизнес-объект, не должен вызываться клиентом напрямую.

Ознакомьтесь с CSLA.net Рокки Лхоткой.

Что ж, вот и я, коллега, о котором упоминал Грег.

Грег с большой точностью описал альтернативы, которые мы рассматривали.Я просто хочу добавить некоторые дополнительные соображения к описанию ситуации.

Клиентский код может не знать о хранилище данных, в котором хранятся бизнес-объекты, но это возможно либо в случае, когда существует только одно хранилище данных, либо существует несколько хранилищ данных для одного и того же типа бизнес-объекта (пользователи хранятся в локальной базе данных и во внешнем LDAP), но клиент не создает эти бизнес-объекты.С точки зрения системного анализа, это означает, что не должно быть вариантов использования, в которых наличие двух хранилищ данных объектов одного и того же типа могло бы повлиять на поток вариантов использования.

Как только возникает необходимость различать объекты, созданные в разных хранилищах данных, клиентский компонент должен осознавать множественность хранилищ данных в своем юниверсе, и он неизбежно становится ответственным за решение, какое хранилище данных использовать в момент создания объекта (и, я думаю, загрузки объекта из хранилища данных).Бизнес-уровень может притворяться, что принимает эти решения, но алгоритм принятия решений будет основан на типе и содержании информации, поступающей от клиентского компонента, что делает клиента эффективно ответственным за принятие решения.

Эта ответственность может быть реализована различными способами:это может быть объект подключения определенного типа для каждого хранилища данных;это могут быть отдельные методы для вызова для создания новых экземпляров BO и т.д.

С уважением,

Майкл

CLSA существует уже давно.Однако мне нравится подход, который обсуждается в книге Эрика Эванса http://dddcommunity.org/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top