Подтвердить что ты не робот

Уровень бизнес-логики и уровня доступа к данным: круговая зависимость

У меня небольшая проблема с архитектурой. В моем проекте у меня есть Business Logic Layer (BLL), который содержит все мои бизнес-правила, модели и API OO для интерфейса. Каждый объект имеет статические методы, такие как getById, которые возвращают экземпляр указанного объекта. У каждого объекта также есть такие методы, как save и delete. Это очень простой код OO.

Теперь у меня есть уровень DataAccess (DAL), содержащийся в отдельном пространстве имен, для каждого объекта BLL у меня есть DataClass или "Репозиторий", который выполняет команды getById и save. Таким образом, методы BLL save и getById представляют собой тонкий слой вокруг методов DataClass.

public static NewsItem GetByID(int id)
{
       return DataFactory.GetNewsItemRepository().GetNewsItemById(id);
}

Чтобы DataClasses возвращал объекты BLL, они должны знать BLL. поэтому теперь мы имеем:

GUI --- > BLL < ---- > DAL

DataFactory возвращает только объекты, реализующие интерфейс, поэтому я могу скрыть детали реализации, такие как "OracleNewsItemRepository".

Но теперь для того, что меня прослушивало с тех пор, как я начал объектно-ориентированное программирование. В моем текущем решении, BLL и DAL должны знать друг друга. Это круговая зависимость, и лучше избегать круговых зависимостей. Также я хочу показать интерфейсы (и мой DataFactory), а не мои классы. Это можно сделать, поместив слой DAL в отдельную сборку. Это будет иметь смысл. Однако Visual Studio не позволяет двум ассамблям ссылаться друг на друга. Другой вопрос: модификаторы внутреннего доступа С#

Как-то я думаю, что у меня был весь шаблон доступа к данным. Похоже, что я сверлю шаблон ActiveRecord с другими вещами, такими как DataMappers. Я провел много времени на сайте Мартина Фаулерса, но эти шаблоны описываются очень обобщенно и иллюстрируются очень абстрактной диаграммой UML.

Они не решают мою проблему. Возможно, я немного анал, и нет такой вещи, как "идеальный шаблон доступа к данным". И то, что я сейчас делаю, не кажется ужасно неправильным. Но как я делаю сейчас, кажется, что...

Любые идеи?

4b9b3361

Ответ 1

Я думаю, что ваш шаблон доступа к данным в порядке. То, что вы не делаете, - это соединение вашего BLL с OracleDAL. Вы подключаетесь к интерфейсам DAL. Определенный бит сцепления абсолютно необходим, или вы никогда не сможете ничего сделать.

Я предполагаю, что ваши классы DataFactory и INewsItemRepository существуют вне вашего уровня DAL. Ниже приведен пример того, как мои решения организованы. Я не использую ActiveRecord, поэтому вам это может не понравиться.

Core (Project)
  Domain
    Business Entities
  Data
    Repository Interfaces
    **Your DataFactory**

OracleData (Project)
  Data
    Oracle Repository Implementations

SqlData (Project)
  Data
    Sql Repository Implementations

UI (Project)

Надеюсь, что это поможет.

Ответ 2

По-моему:

Уровень доступа к данным (DAL) должен работать с POCOs (обычными старыми объектами CLR), используя следующие операции: SaveNewsItem ( NewsItemDAO newsItemDAO ). POCOs - ваши DAO (объекты доступа к данным).

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

DAL не должен иметь никаких знаний о бизнес-логике. Теоретически она должна быть вызвана от любого клиента. Например, что, если вы хотите отделить DAL от приложения и развернуть его как отдельную службу, подвергая себя через WCF?

Как упоминалось, операции DAL, например, SaveNewsItem должен получить доступ через BO через интерфейсы, возможно, через инъекцию зависимости/IoC.

Ответ 3

Вы можете использовать инъекции интерфейсов/зависимостей, чтобы решить вашу проблему.

В бизнес-слое (BL) содержатся интерфейсы доступа к данным (DA), которые необходимо реализовать (возможно, более одного) DAL. Проекты DAL имеют ссылки на проекты BL, чтобы они могли выплескивать бизнес-объекты (BOs) и реализовывать интерфейсы DA.

Ваши BO могут вызывать DataFactory, который может создавать объект DA через инъекцию или отражение зависимостей.

Я использовал этот шаблон во многих наших приложениях здесь, на работе (как веб-интерфейс, так и smart-client), и он прекрасно работает.

Ответ 4

Теперь это немного устарело, но, возможно, вам следовало бы рассмотреть возможность размещения pocos/интерфейсов в другой сборке.

Project.Data references Project.Entities
Project.BL references Project.Entities and Project.Data
Project.UI references Project.Entities and Project.BL

Здесь нет круглых ссылок.

Ответ 5

Чтобы быть ясным, мне нравится думать о бизнес-модели и бизнес-логике как о двух отдельных слоях. Ваша бизнес-модель - это ваши POCO (обычные объекты CLR). Уровень вашей бизнес-логики будет отвечать за выполнение валидации, транзакций и т.д., Используя как вашу бизнес-модель, так и интерфейс к вашему DAL, который может быть подключен несколькими способами (Spring, замок или собственный домашний контейнер IoC).

Хорошим способом достижения нулевых зависимостей в вашем DAL с вашей бизнес-моделью является использование уже построенной структуры сопоставления объектных отношений (ORM), такой как NHibernate (бесстыдный плагин для моей любимой структуры ORM).

Ответ 6

IceHeat, пример @Craig Wilson имеет наибольший смысл и, вероятно, вытекает из этой статьи: http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx.

Это ХОРОШО стоит читать и решать проблемы, связанные с доменом, которые решают проблемы, с которыми вы сталкиваетесь здесь. Id рекомендую это кому угодно, даже если вы не дадите обезьянам о NHibernate свою отличную статью.

Ответ 7

Я бы удалил любой метод Get() и Save() из вас BLL (модель домена).. вот что я сделал бы

GUI попросит репозиторий получить объект домена по id.. и как только GUI имеет объект домена, вы можете перемещаться по нему для доступа к другим объектам. Таким образом, для уровня домена не нужно ничего знать о репозиториях.

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

Вот хорошая запись на ту же тему... Восстановление объектов

Прочитайте комментарий Дейана Петрова о том, как использовать динамический прокси

Ответ 8

DAL должен быть абстрактным, поэтому он должен содержать только простые объекты ADO.NET, которые взаимодействуют с базой данных, например, DataAdapter, DataReader и т.д. Имея это в виду, вы можете ссылаться на DAL в своем Biz-слое, а когда дело доходит до ваших сущностей с небольшой абстракцией, вы можете решить все свои проблемы, например, если у вас есть класс клиентов, вы можете создать класс клиента abstaractoin, который реализует основные операции для взаимодействия с DAL, такие как сохранение, обновление и извлечение данных, а в другом классе, который наследует класс абстракции, переопределяет реализацию методов базового класса для соответствия вашей проверке Biz и т.д.