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

Используя шаблон Data Mapper, должны ли объекты (объекты домена) знать о Mapper?

Я работаю с Doctrine2 в первый раз, но я думаю, что этот вопрос достаточно общий, чтобы не зависел от конкретной ORM.

Следует ли знать объекты в шаблоне Data Mapper - и использовать - Mapper?

У меня есть несколько конкретных примеров, но все они, похоже, сводятся к одному и тому же общему вопросу.

Если я имею дело с данными из внешнего источника - например, User имеет много Messages - и внешний источник просто предоставляет последние несколько объектов (например, RSS-канал), как можно $user->addMessage($message) проверить для дубликатов, если он не знает о Mapper или не выполняет поиск в коллекции (кажется, это неэффективная вещь).

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

Если у меня есть большая коллекция - опять-таки User со многими Messages - как может объект User предоставить ограничение и разбиение на страницы для коллекции без фактического проксирования вызова Mapper?

Опять же, контроллер или транзакция Script или что-то другое, использующее Entity, может использовать Mapper напрямую, чтобы получить коллекцию User Messages, ограниченную подсчетом, диапазоном дат или другими факторами, - но это тоже приводят к дублированию кода.

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

4b9b3361

Ответ 1

Правило №1: Держите свою модель домена простой и понятной.

Во-первых, преждевременно не оптимизируйте, потому что считаете, что это может быть неэффективно. Создайте свой домен так, чтобы объекты и синтаксис выполнялись правильно. Удерживайте интерфейсы в чистоте: $user- > addMessage ($ message) является чистым, точным и недвусмысленным. Под капотом вы можете использовать любое количество шаблонов/методов для обеспечения целостности (кеширование, поиск и т.д.). Вы можете использовать Службы для упорядочивания (сложных) зависимостей объектов, возможно, слишком для этого, но вот базовый образец/идея.

class User
{
  public function addMessage(Message $message)
  {
     // One solution, loop through all messages first, throw error if already exists
     $this->messages[] $message;
  }
  public function getMessage()
  {
     return $this->messages;
  }
}
class MessageService
{
  public function addUserMessage(User $user, Message $message)
  {
     // Ensure unique message for user
     // One solution is loop through $user->getMessages() here and make sure unique
     // This is more or less the only path to adding a message, so ensure its integrity here before proceeding 
     // There could also be ACL checks placed here as well
     // You could also create functions that provide checks to determine whether certain criteria are met/unmet before proceeding
     if ($this->doesUserHaveMessage($user,$message)) {
       throw Exception...
     }
     $user->addMessage($message);
  }
  // Note, this may not be the correct place for this function to "live"
  public function doesUserHaveMessage(User $user, Message $message)
  {
     // Do a database lookup here
     return ($user->hasMessage($message) ? true
  }
}
class MessageRepository
{
  public function find(/* criteria */)
  {
     // Use caching here
     return $message;
  }
}

class MessageFactory
{
   public function createMessage($data)
   {
     //
     $message = new Message();
     // setters
     return $message;
   }
}

// Application code
$user = $userRepository->find(/* lookup criteria */);
$message = $messageFactory->create(/* data */);
// Could wrap in try/catch
$messageService->sendUserMessage($user,$message);

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

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

Не переучивайте его с самого начала. Держите ваш домен сосредоточенным на своей цели и рефакторе, когда производительность на самом деле является проблемой.

Ответ 2

ИМО, Сущность должна не обращать внимания на то, откуда она взялась, кто ее создал и как заполнить связанные объекты. В ORM я использую (свой собственный), я могу определить объединения между двумя таблицами и ограничить его результаты, указав (в С#):

SearchCriteria sc = new SearchCriteria();
sc.AddSort("Message.CREATED_DATE","DESC");
sc.MaxRows = 10;
results = Mapper.Read(sc, new User(new Message());

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

results = Mapper.Read(sc, new  Message(new User());

объединение отменяется.

Таким образом, объекты Entities могут полностью не знать о картографе.

Ответ 3

Нет.

Вот почему: trust. Вы не можете доверять данным, чтобы действовать в интересах системы. Вы можете доверять системе только для работы с данными. Это фундаментальная логика программирования.

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

Пусть левая рука не знает, что делает правая рука! (в основном потому, что вы не хотите знать)