All streams
Search
Write a publication
Pull to refresh
63
0.5
Михаил @michael_v89

Программист

Send message

Это правильный вопрос. А правильный ответ на него - в сервисе. Такие примеры как раз и показывают, что бизнес-правила не привязаны к сущностям, а существуют сами по себе и могут относиться к нескольким сущностям.

дополнительные атрибуты (для документации API, для UI)
это все протечет в домен. И меня это смущает.

Если вы имеете в виду аннотации, а не поля класса, то обычно никаких проблем с этим нет. Это то же самое, что аннотации в сущности для маппинга на таблицу БД.
Если не хотите так делать, тогда можно сделать в слое контроллеров дублирующие DTO, и сделать в них методы конвертации toDomainDto(). Тогда да, будет 3 DTO (или 4). Но 3-е DTO у вас и так есть, просто обозначается ключевым словом interface. Мне кажется, лучше явно указывать, что и куда вы передаете, чем прятать DTO из другого слоя за интерфейсом. Наследование тут точно не нужно, и вообще наследование DTO лучше нигде не делать.

при таком подходе детали внешнего интерфейса протекают в слой домена

// namespace Domain

class CreateOrderDTO {
  public string field1;
  public string field2;
  ...
}


// namespace Application

import Domain.CreateOrderDTO;

class OrderController {
  public function create(Request request): Order {
    var createOrderDTO = new CreateOrderDTO();
    createOrderDTO.field1 = request.get('field1');
    createOrderDTO.field2 = request.get('field2');
    ...
  }
}

Покажите пожалуйста, какие именно детали в CreateOrderDTO относятся к внешнему интерфейсу.
Если вы имеете в виду какие-то аннотации для фреймворка, чтобы он автоматически мапил request на dto, то можно сделать дублирующие DTO в слое контроллеров, но обычно никаких проблем с этим нет. Аннотации не влияют на остальной код класса и просто обеспечивают соединение слоев.

и от DDD остаётся только название

А когда вы в сущности пишете аннотации для маппинга на таблицу БД, или используете низкоуровневые типы, такие как четырехбайтовый int, не остается?)

есть два контроллера с немного разными DTO

В это случае либо вы конвертируете один DTO в другой, либо у вас должно быть 2 разных метода с логикой, которые принимают на вход разные DTO.

Если я добавляю интерфейс - я просто те два DTO для котроллеров наследую от интерфейса.

Это то же самое, что конвертирование, только очень странное. С ненужной абстракцией, которая используется не по назначению. Интерфейс описывает поведение, у DTO нет поведения, значит интерфейс не нужен.

Если бы я переходил на DDD и добавил бы еще один DTO на уровне Domain - у меня стало бы три штуки DTO.

Нет, у вас был бы один или два DTO, с которыми работают контроллеры. В слое контроллеров в этом случае нет своих DTO.

И в реальном проекте с анемичной моделью и публичными сеттерами - используется автомаппер (из этих двух DTO прям в анемичную сущность).

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

Мне кажется, вы не совсем понимаете, что такое Aggregate в DDD. Коллекция это не Aggregate.

https://martinfowler.com/bliki/DDD_Aggregate.html
Aggregate is a pattern in Domain-Driven Design. A DDD aggregate is a cluster of domain objects that can be treated as a single unit. An example may be an order and its line-items.
DDD Aggregates are sometimes confused with collection classes (lists, maps, etc).

Абстракция для коллекции документов это репозиторий DocumentRepository, добавлять еще одну это неправильно.
Даже если вы добавите, как сохранить в базу новый документ после вызова Documents.add? Удалять все и сохранять заново все которые есть в Documents? Это не DDD и не трилемма, это просто неправильная архитектура.
Добавлять бизнес-логику в DocumentRepository тоже неправильно.
Documents может использовать DocumentRepository, но тогда и загружать все документы не надо. То есть Documents превратится просто в сервис с логикой, который использует репозиторий.

Так вам не нужны разные DTO, будет только один DTO, добавляете туда поле и всё.
Не очень понятно, что вы имеете в виду под маппингами. Вы же уже как-то создаете CreateOrderDTO и как-то его используете. Просто он будет в другом неймспейсе, и вместо ICreateOrder будет CreateOrderDTO.

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

Интерфейс для DTO это довольно бессмысленная вещь. Если вам в параметрах нужен DTO, просто объявляйте DTO. Нет никакой проблемы в том, чтобы объявлять DTO в слое домена. Так же как enum-ы, value object-ы, и любые другие классы.

чтобы в use case "создание заказа" мне создать заказ из DTO, где куча полей - все эти поля нужно добавить в конструктор

Не нужно. Вам же уже сказали выше - в этом случае в конструктор надо передавать DTO со всеми этими полями.

Аналогично, чтобы в use case "обновление заказа" изменить поля - надо нагенерить кучу методов UpdateXXX().

Аналогично, не надо. Если хотите делать логику в сущности, то в сущности должен быть метод update, который принимает DTO с полями из формы обновления заказа в интерфейсе и содержит логику обновления.

Но я рекомендую вам подумать, как вы будете проверять в сущности длину поля, если бизнес попросит вас сделать максимальную длину например описания товара настройкой, которая хранится в базе данных.

Доступ к миллионам юзеров сейчас и так есть у всяких фейсбуков и рекламщиков. Или те же телевизор и радио.

Когда вся логика лежит в сервисах, а не в доменных объектах, то это все еще работает, но уже не особо что-то моделирует.

Моделирует. То, что и должна - бизнес-требования.

// Если заказ успешно оплачен, перевести заказ в статус "Оплачено"
// и отправить письмо пользователю с информацией о заказе.

class OrderService {
  public function pay() {
    ...
    
    $paymentResult = $this->sendPayment($order, $paymentDetails);
    
    if ($paymentResult === PaymentResult::Success) {
      $this->moveOrderToStatus(OrderStatus::PAID);      
      $this->sendSuccessEmail(order);
    }
  }

  private function moveOrderToStatus(OrderStatus $status) {
      $order->setStatus($status);
      $this->entityManager->save($order);
  }
}

Как вы будете делать оплату и отправку email из сущности, непонятно. Учтите, что отправку email надо делать после сохранения сущности.

Обратите внимание, что в бизнес-требованиях написано "перевести заказ в статус N", а не "перевести это в статус N". Поэтому код $order->setStatus(N) более правильно моделирует бизнес-требования, чем $this->status = N.

не нужно быть АГИ. Вот представьте себе, что он есть, что человечество может его просить?

Вы путаете AGI (интеллект общего назначения) и ASI (сверхинтеллект). AGI по уровню аналогичен обычному человеку. Просить его о чем-то это то же самое, что просить любого человека. Ну может не любого, а ученого или группу ученых. Никаких тайн он вам не скажет.

человек - не совсем AGI

Человек это AGI просто по определению AGI.

А, я понял, у вас название составлено по принципу "article - откуда? - from DTO". Это еще хуже, потому что не бывает такого понятия "сущность оттуда", "сущность отсюда". Сущность потому так и называется, что она существует сама по себе.

Функционал валидатора проверяет значение поля Status объекта articleFromDTO.

Откуда там возьмется статус без подгрузки из БД, тоже непонятно. То есть вы еще и сущность загружаете 2 раза вместо одного. Если надо помечать, что сущность пришла из DTO, то можно просто передать DTO.

Значение Id статьи в articleFromDTO идентично значению в поле Id в таблице

А раз это у вас всё-таки сущность, и к тому же содержит поле "id", то как я и сказал, записывая в нее title и text до проверки статуса, вы приводите ее в невалидное состояние и нарушаете бизнес-требования. Да, состояние невалидное даже если вы не сохраняете его в базу.

А поскольку оно не сохраняется, то вы используете этот объект только для передачи данных, то есть у вас это всё-таки data transfer object (объект передачи данных). Использование класса сущности в качестве DTO это нарушение многих договоренностей по наименованию и проектированию, потому что сущность это не DTO. Это запутывает программиста, которые не писал этот код. О какой правильной архитектуре тут можно говорить.

При этом вы так не ответили на вопрос, откуда вы взяли, что DTO не должно быть в слое бизнес-логики. Любой слой может описывать структуры, которые он принимает на вход. Список из 10 аргументов метода это такое же DTO, просто неявное.

Выглядит как ответ ChatGPT. Который вы похоже не поняли.

Веб-контролер вызывает функционал объекта application logic типа UpdateArticleUsecase.
Это объект articleFromDTO. Ссылка на этот объект находится в объекте типа UpdateArticleUsecase.

Я так и сказал, из контроллера в сервис передается DTO.

Далее должна пройти валидация - то есть сравнение полей Title и Text в articleFromDTO с такими же полями статьи
валидатор сравнивает поля Text и Title

Не надо там ничего сравнивать, в бизнес-требованиях этого нет. Сравнивать надо только статус.

Изменение значений полей сущности в соответствии с бизнес-требованиями это и есть бизнес-логика. Например, если статья в статусе "На модерации", ее нельзя редактировать. То есть записывать новые значения в поля text и title. Если у вас контроллер это делает без проверки статуса, то он нарушает бизнес-требования. Если с проверкой, то он содержит всю бизнес-логику действия.

Непонятно, что вы будете делать, когда на входе приходит GUID, а в сущности мы храним числовой id. В этом случае в сущности вообще нет такого поля, чтобы записать туда GUID.
Или есть галочка вида "Отправить уведомление пользователю/автору/менеджеру" при совершении некоторого действия с сущностью. В сущности она не хранится, она нужна только для логики действия.
Как вы будете реализовывать бизнес-логику фильтров вида "В товаре есть изображения" или "От-до" для одного поля "Дата создания" тоже непонятно. Тут вообще нет сущности, куда их можно записать.

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

"Перенос данных из DTO в сущность" это и есть бизнес-логика, он должен следовать заданным правилам. То есть у вас бизнес-логика в контроллере. Если же у вас "объект модели данных" это не сущность, то это и есть DTO.

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

Почему его «нейроны» должны порождать квалиа — внутренний опыт внешнего раздражения?

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

Мы говорим о «сознании» как о механизме интерпретации

Интерпретация это обработка информации, этот механизм называется "интеллект".

«Сознание возникает, когда знаковая система осознаёт свою неспособность описать саму себя».

Это бессмысленное утверждение. "Знаковая система" это например алфавит или язык. Даже если под этим подразумевать LLM, то в определении есть рекурсия - "Сознание это когда осознаёт". Почему сознание не возникает, когда система осознаёт что-то другое, тоже непонятно. Осознаёт же.

Если сознание имманентно машине — оно проявится в эпицентре этого контролируемого апокалипсиса знаков.

В каком эпицентре, как он выглядит? Что такое "апокалипсис знаков", как он проявляется? Это когда LLM генерирует случайные символы?

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

Как проявляется этот разрыв, что под этим подразумевается? Как выглядит отсутствие разрыва.

Сознание же — одно из проявлений эмерджентности на биологическом уровне.
Эволюционно человек пришёл к способности к означению

С чего вдруг сознание стало эквивалентно использованию знаков? Использование знаков (письмо, речь) это в чистом виде интеллект. В этом есть полный консенсус со времен их появления.

ИИ, оснащенный датчиками, сталкивается не просто с „вспышкой сенсора“, а с непрерывным, аналоговым, мультимерным потоком сырых данных (электромагнитные частоты, временные метки с наносекундной точностью, тепловые шумы, пространственные координаты)

А как их измерять-то? Измерения это и есть "вспышки сенсора".

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

Любая нейросеть, анализирующая или генерирующая изображение, имеет такие датчики. И память тоже имеет.

неименуемый поток сенсорных событий. Это не новый знак

Это именно знак, число. Например код цвета со значениями R,G,B.

система легитимирует хаос

"Легитимировать" это "придавать законный статус". Что значит "система придаёт законный статус хаосу"? Это выражение не имеет смысла.

Дальше неохота разбирать, и так много получилось. Сомневаюсь, что автор способен ответить на эти вопросы.

Information

Rating
1,953-rd
Location
Россия
Registered
Activity