К какому слою относится Repository и как возвращать Business object?

Язык не важен. Например, у меня есть база данных с таблицей User.
В моей программе есть Data Access Layer (DAL) и Business Logic Layer (BLL).
В DAL для таблицы User у меня написан класс сущности UserEntity{username, secondname, age ...}, которая, соответственно и отражает в себе данные отдельного поля таблицы.
В своем BLL у меня есть объект User{fullname, age}, который получается путем превращения UserEntity -> User, т.е. происходит mapping.

Также у меня есть UserRepository, который инкапсулирует работу с хранилищем и возвращает данные. Вот здесь у меня и возникли вопросы:
1) Что должен возвращать UserRepository : UserEntity или User?
2) В каком слое должен находиться UserRepository DAL или BLL

Если по логике, то DLL вообще не должен знать про BLL, тем более про его объекты. Но выходить, что если я хочу, чтобы
репозиторий возвращал User, то получается DLL подвязан на BLL. То есть, если репозиторий находится в DAL, то он никак не должен возвращать объекты BLL. Но во многих статьях я видел, что наоборот, пишут - repository возвращает Business objects.

Как решить эти проблемы?
  • Вопрос задан
  • 1043 просмотра
Пригласить эксперта
Ответы на вопрос 4
@maltsever
Привет! Многое зависит от деталей и количества абстракций. Попытаюсь ответить как это должно выглядеть в самом общем случае. UserRepository использует напрямую доступ к базе данных (это может быть raw sql, какая-то ORM, неважно). Поэтому логично, чтобы он находился в Data Access Layer. Он поэтому так и называется, потому что на практике их может быть несколько: SqlDataAccessLayer, MongoDbDataAccessLayer и т.д. Также если мы говорим про ООП, то интерфейс IUserRepository должен хранится именно там, где планируется его использование. В нашем случае это BLL, он же Domain Layer. Не всегда удаётся придерживаться этого правила с интерфейсом, но к этому нужно стремиться.
По поводу того, что должен возвращать UserRepository: на самом деле без разницы. Смотря от ситуации мы можем либо возвращать просто контейнер c необходимыми данными (DTO), либо полноценного User'a. Если говорить о зависимостях, то главное понимать, что в общем случае наш Domain Layer не должен иметь зависимостей от каких-то других слоёв. А вот остальные части нашего проекта (например, DAL) могут использовать Domain Layer.
Ответ написан
dmitriylanets
@dmitriylanets
веб-разработчик
как правило Repository - уровень инфраструктуры а не домена, с доменом они связанны интерфейсами.
например доменная сущность (по сути это BLL):
Domains/User/User
Domains/UserCollection
Domains/User/RepositoryInterface (возвращает User, UserCollection)

Инфраструктура:
Infrastructure/User/Repository (реализует RepositoryInterface, работает с бд, использует DAL, mapping)

ну и Application
контроллеры, GUI , views
Ответ написан
Комментировать
Я обычно делаю это следующим образом.

Есть проект Domain в котором описаны общие интерфейсы для BLL и View(REST, SOAP, CLI, Desktop и т.д.). Тут есть некий интерфейс IUserService, который работает с User.
Есть проект со всей бизнес логикой, который реализует IUserService в UserService. Этот UserService ходит в DAL, откуда получает UserEntity и преобразовавает её в User. Кроме этого здесь происходят валиадации, отправка нотификаций, т.е. все что нужно бизнес логике. Отдельно есть проект DAL, который уже ходит в базу и возвращает UserEntity через UserRepository.

View при этом знает только o существования Domain проекта, а все реализации пробрасываются через IoC.

Я описал абстрактный пример, он может варироваться от платформы и размера приложения
Ответ написан
Комментировать
@AlexHell
class User {Id, Name, Age}

class UserRepository
{
 User GetUserById(long Id)
  {
  string[] data = {select from Users where id = Id}
  return new User() {Id = Id, Name = data[0], Age = data[1] };
  }

  void PutUser(User)
  {
    {insert into Users}
  }
}


Зачем вам UserEntity? Если у вас доменный объект User - везде его и передавайте, и Repo олжен его же вертать при чтении из БД и его же принимать чтоб сохранять в БД.

Если вопрос в EntityFramework (и иже с ними ORM) с обязательным отнаследованием от базового Entity класса - ну сделайте маппинг опять же внутри UserRepo и не отдавайте вообще никогда вовне UserEntity, всмысле как private class например чисто для namespace / пакета
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы