Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 28.11.25 17:47
Оценка:
Вопрос такой.

Вот, обычно делают слои и на уровне каждого слоя свои объект — для строгого разделения. А потом мапперы между слоями.

И у меня сейчас проект, который нужно дорабатывать. Там этой парадигмы разделения не придерживались строго, так что в ui проникают как dto, так и entity. Проект пока не большой, около 25 тыс. строк кода, т.е. за пару-тройку дней можно разделить и добавить мапперы.

Но задумался — а какие реальные бонусы? Вот что пишет зазнайка:

Если использовать DTO в Домене: Ваша бизнес-логика становится зависимой от API-контрактов. Если фронтенд попросит переименовать поле в JSON для удобства отображения, вам придется менять это поле в бизнес-логике, что может повлечь ошибки в расчетах. Внешний мир начинает диктовать правила внутреннему.

Если использовать Entity в Домене: Ваша бизнес-логика зависит от схемы базы данных. Если вы решите денормализовать таблицу для производительности или сменить PostgreSQL на MongoDB, вам придется переписывать бизнес-правила.

Правило архитектуры: Зависимости должны быть направлены внутрь. Слой Домена (бизнес-логика) должен быть самым стабильным и не зависеть ни от Базы Данных, ни от UI/API.


Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.

Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.

Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.

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

По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.
=сначала спроси у GPT=
Отредактировано 28.11.2025 17:53 Shmj . Предыдущая версия .
Re: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 28.11.25 19:05
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>Вопрос такой.


S>Вот, обычно делают слои и на уровне каждого слоя свои объект — для строгого разделения. А потом мапперы между слоями.


S>И у меня сейчас проект, который нужно дорабатывать. Там этой парадигмы разделения не придерживались строго, так что в ui проникают как dto, так и entity. Проект пока не большой, около 25 тыс. строк кода, т.е. за пару-тройку дней можно разделить и добавить мапперы.


S>Но задумался — а какие реальные бонусы? Вот что пишет зазнайка:


S>

S>Если использовать DTO в Домене: Ваша бизнес-логика становится зависимой от API-контрактов. Если фронтенд попросит переименовать поле в JSON для удобства отображения, вам придется менять это поле в бизнес-логике, что может повлечь ошибки в расчетах. Внешний мир начинает диктовать правила внутреннему.

S>Если использовать Entity в Домене: Ваша бизнес-логика зависит от схемы базы данных. Если вы решите денормализовать таблицу для производительности или сменить PostgreSQL на MongoDB, вам придется переписывать бизнес-правила.

S>Правило архитектуры: Зависимости должны быть направлены внутрь. Слой Домена (бизнес-логика) должен быть самым стабильным и не зависеть ни от Базы Данных, ни от UI/API.

Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

S>Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.

Можно и руками.

S>Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.

Ни чего не понял.

S>Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.

Да хоть в 10 местах, что это меняет, откуда такая мания экономить на спичках?

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

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

S>По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.


Ну не применяй.
Программа – это мысли спрессованные в код
Re[2]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 07:11
Оценка:
Здравствуйте, Qulac, Вы писали:

S>>Правило архитектуры: Зависимости должны быть направлены внутрь. Слой Домена (бизнес-логика) должен быть самым стабильным и не зависеть ни от Базы Данных, ни от UI/API.

S>>[/q]
Q>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

Это на серверной части. А у клиента основная сложная логика — это авторизация, смена пользователя — важно чтобы приложение правильно эту логику отработало.

Остальное у клиента — это практически дергание API и базы а так же синхронизация данных API, базы и UI.

Из частых проблем может быть — на форме обновили значение суммы (допустим) а в общем балансе забыли обновить — но это состояние приложения.

S>>Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.

Q>Можно и руками.

Я не о том что руками — вопрос в объектах. Что если не создавать ViewModel и даже не создавать business object для domain-слоя — а тупо в UI применять dto, который отдало API. В чем минус такого подхода?

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

S>>Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.

Q>Ни чего не понял.

Ну если внешней сервис изменил имя поля в ответе — как то было WokrTime а стало WorkTime — один хрен, даже если ты создал dto, bo, entity — придется менять dto + в маппере dto->bo и скорее всего в маппере dto->entity. Это 3 изменения кода. Если не создавал отдельно bo — то сразу меняешь в dto и в ui — два изменения кода. Получается не создавать объекты + мапперы — меньше работы и нет особых минусов

S>>Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.

Q>Да хоть в 10 местах, что это меняет, откуда такая мания экономить на спичках?

Чем меньше монотонной работы — тем лучше. Всегда лучше изменить в одном месте чем 4 местах, ибо раздражает, тратится время. А плюс в чем?

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

Q>Зачем фейковые сервисы,если они только не являются сторонними к проекту. Фейковыми должны быть репозитории.

Так сервисы же есть внешние (которые связывают с API) и сервисы domain-слоя (бизнес логика). Можно мокать и внешние и бизнес слоя. Бизнес слойные сервисы мокают если хотят протестить один из сервисов, независимо от других — другие заменяют моками/фейками.

S>>По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.

Q>Ну не применяй.

Но все же хочется понять — почему принято делать 3 похожих типа объектов, если нет реальных плюсов:

1. dto — в виде, который отдает внешний сервис.
2. entity — в виде, который хранится в таблице базы данных.
3. business object — в виде, который представлен в бизнес-логике — domain-слое.
(4). Иногда добавляют view model — в виде, который отображается пользователю на форме.

+ еще и мапперы между каждым из слоев

Просто что всех так по учебникам учили?
=сначала спроси у GPT=
Re[3]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 08:03
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, Qulac, Вы писали:


S>>>Правило архитектуры: Зависимости должны быть направлены внутрь. Слой Домена (бизнес-логика) должен быть самым стабильным и не зависеть ни от Базы Данных, ни от UI/API.

S>>>[/q]
Q>>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

S>Это на серверной части. А у клиента основная сложная логика — это авторизация, смена пользователя — важно чтобы приложение правильно эту логику отработало.


S>Остальное у клиента — это практически дергание API и базы а так же синхронизация данных API, базы и UI.


S>Из частых проблем может быть — на форме обновили значение суммы (допустим) а в общем балансе забыли обновить — но это состояние приложения.


S>>>Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.

Q>>Можно и руками.

S>Я не о том что руками — вопрос в объектах. Что если не создавать ViewModel и даже не создавать business object для domain-слоя — а тупо в UI применять dto, который отдало API. В чем минус такого подхода?


S>Минус вижу один — не получится отвязать физически слои в разные библиотеки и тестировать из независимо. Но на практике это и не нужно, как бы это уникальный случай, когда над каждым слоем работает отдельный человек, а взаимодействие на основе контрактов.


S>>>Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.
Q>>Ни чего не понял.

S>Ну если внешней сервис изменил имя поля в ответе — как то было WokrTime а стало WorkTime — один хрен, даже если ты создал dto, bo, entity — придется менять dto + в маппере dto->bo и скорее всего в маппере dto->entity. Это 3 изменения кода. Если не создавал отдельно bo — то сразу меняешь в dto и в ui — два изменения кода. Получается не создавать объекты + мапперы — меньше работы и нет особых минусов


S>>>Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.

Q>>Да хоть в 10 местах, что это меняет, откуда такая мания экономить на спичках?

S>Чем меньше монотонной работы — тем лучше. Всегда лучше изменить в одном месте чем 4 местах, ибо раздражает, тратится время. А плюс в чем?


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

Q>>Зачем фейковые сервисы,если они только не являются сторонними к проекту. Фейковыми должны быть репозитории.

S>Так сервисы же есть внешние (которые связывают с API) и сервисы domain-слоя (бизнес логика). Можно мокать и внешние и бизнес слоя. Бизнес слойные сервисы мокают если хотят протестить один из сервисов, независимо от других — другие заменяют моками/фейками.


S>>>По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.

Q>>Ну не применяй.

S>Но все же хочется понять — почему принято делать 3 похожих типа объектов, если нет реальных плюсов:


S>1. dto — в виде, который отдает внешний сервис.

S>2. entity — в виде, который хранится в таблице базы данных.
S>3. business object — в виде, который представлен в бизнес-логике — domain-слое.
S>(4). Иногда добавляют view model — в виде, который отображается пользователю на форме.

S>+ еще и мапперы между каждым из слоев


S>Просто что всех так по учебникам учили?



Еще раз повторю: проекты валятся не из-за того, что в 10 местах переменную переименовать нужно, а из-за того, что в БЛ в в том виде в котором она реализована, становится невозможно вносить изменения, а баги начинают жить вечно. Это вопрос собственно какую ценность мы выбираем: проект или код в котором не нужно менять в трех местах переменную. Это чисто "житейский" подход, что мы отделаем главное от не главного, а код здесь вторичен.


P.S. Я это видел на практике, один объект везде, что-то типа такого:

class Customer: Entity
{ 
   [NoMapper] - что это здесь делает?
   strring property{get;set;}

   DateTime DateTime {get;set;}

   string FomratDateTime
   {
     returt DatetTim.Format - //возвращаем в нужном формате
   }
}
Программа – это мысли спрессованные в код
Отредактировано 29.11.2025 8:10 Qulac . Предыдущая версия .
Re[4]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 09:23
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Еще раз повторю: проекты валятся не из-за того, что в 10 местах переменную переименовать нужно, а из-за того, что в БЛ в в том виде в котором она реализована, становится невозможно вносить изменения, а баги начинают жить вечно. Это вопрос собственно какую ценность мы выбираем: проект или код в котором не нужно менять в трех местах переменную. Это чисто "житейский" подход, что мы отделаем главное от не главного, а код здесь вторичен.


Давай на примерах рассмотрим.

Q>P.S. Я это видел на практике, один объект везде, что-то типа такого:

Q>

Q>class Customer: Entity
Q>{ 
Q>   [NoMapper] - что это здесь делает?
Q>   strring property{get;set;}

Q>   DateTime DateTime {get;set;}

Q>   string FomratDateTime
Q>   {
Q>     returt DatetTim.Format - //возвращаем в нужном формате
Q>   }
Q>}
Q>


Т.е. вам не нравится что в одном классе лишние поля, часть из которых не нужна для конкретного слоя? А что если добавить методы-расширения или mixin, чтобы нужные для конкретного слоя поля были в этом слое?
=сначала спроси у GPT=
Re[5]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 09:36
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, Qulac, Вы писали:


Q>>Еще раз повторю: проекты валятся не из-за того, что в 10 местах переменную переименовать нужно, а из-за того, что в БЛ в в том виде в котором она реализована, становится невозможно вносить изменения, а баги начинают жить вечно. Это вопрос собственно какую ценность мы выбираем: проект или код в котором не нужно менять в трех местах переменную. Это чисто "житейский" подход, что мы отделаем главное от не главного, а код здесь вторичен.


S>Давай на примерах рассмотрим.


Q>>P.S. Я это видел на практике, один объект везде, что-то типа такого:

Q>>

Q>>class Customer: Entity
Q>>{ 
Q>>   [NoMapper] - что это здесь делает?
Q>>   strring property{get;set;}

Q>>   DateTime DateTime {get;set;}

Q>>   string FomratDateTime
Q>>   {
Q>>     returt DatetTim.Format - //возвращаем в нужном формате
Q>>   }
Q>>}
Q>>


S>Т.е. вам не нравится что в одном классе лишние поля, часть из которых не нужна для конкретного слоя? А что если добавить методы-расширения или mixin, чтобы нужные для конкретного слоя поля были в этом слое?


А ради чего дрючиться, ради какой такой святой цели? Что бы с "оптимизировать" код который имеет низкую ценность и вообще ни на что не влияет?
А как быть с вот таким ответом из БЛ:

class CustomerCarTuple: ValueObject
{
  public Customer Customer {get;private set}

  public Car Car {get;private set}
}

//метод сервиса
public Ienumerable<CustomerCarTuple> GetCustomerCarReport()
{
  //
  returt ...
}

Программа – это мысли спрессованные в код
Re[6]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 09:43
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>А ради чего дрючиться, ради какой такой святой цели? Что бы с "оптимизировать" код который имеет низкую ценность и вообще ни на что не влияет?


А зачем плодить лишние сущности? Вот в чем вопрос. Какой реальный смысл создавать одинаковые классы на каждом уровне и потом еще и маппить один в один?

Ну ОК, если совсем другая структура — то создай. А для всех случаев в чем смысл? Однообразно и безобразно?

Q>А как быть с вот таким ответом из БЛ:


Q>
Q>class CustomerCarTuple: ValueObject
Q>{
Q>  public Customer Customer {get;private set}

Q>  public Car Car {get;private set}
Q>}

Q>//метод сервиса
Q>public Ienumerable<CustomerCarTuple> GetCustomerCarReport()
Q>{
Q>  //
Q>  returt ...
Q>}
Q>

Q>

А в чем вопрос?
=сначала спроси у GPT=
Re[7]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 09:46
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, Qulac, Вы писали:


Q>>А ради чего дрючиться, ради какой такой святой цели? Что бы с "оптимизировать" код который имеет низкую ценность и вообще ни на что не влияет?


S>А зачем плодить лишние сущности? Вот в чем вопрос. Какой реальный смысл создавать одинаковые классы на каждом уровне и потом еще и маппить один в один?


S>Ну ОК, если совсем другая структура — то создай. А для всех случаев в чем смысл? Однообразно и безобразно?


Q>>А как быть с вот таким ответом из БЛ:


Q>>
Q>>class CustomerCarTuple: ValueObject
Q>>{
Q>>  public Customer Customer {get;private set}

Q>>  public Car Car {get;private set}
Q>>}

Q>>//метод сервиса
Q>>public Ienumerable<CustomerCarTuple> GetCustomerCarReport()
Q>>{
Q>>  //
Q>>  returt ...
Q>>}
Q>>

Q>>

S>А в чем вопрос?


Здесь в viewModel только маппинг нужен.
Программа – это мысли спрессованные в код
Re: Что если не разделять строго dto, entity, bo...
От: DiPaolo Россия  
Дата: 29.11.25 10:20
Оценка:
S>И у меня сейчас проект, который нужно дорабатывать. Там этой парадигмы разделения не придерживались строго, так что в ui проникают как dto, так и entity. Проект пока не большой, около 25 тыс. строк кода, т.е. за пару-тройку дней можно разделить и добавить мапперы.

Ну может оно и не надо? Тут надо оценить целесообразность и учесть:
— на каком этапе проект
— сколько денег приносит и сколько клиентов имеет
— объем доработок (+ в процентах к текущим LOC)
— единоразовая ли доработка
— как часто проект требует вмешательства в-принципе

Я бы сильно задумался, а стоит ли оно вообще что-то менять вот так кардинально. И учел бы ответы на вопросы выше. ИМХО вот так сходу кажется, что не стоит ничего менять

S>Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.


S>Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.


S>Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.


Основная суть даже не в тестировании (хотя и это тоже), а в том, чтобы абстрагировать каждый слой и сделать его независимым от внешних изменений, оставляя нетронутым его интерфейс.

Давай на примерах:
— связка сервис <-> слой БД: ты захотел оптимизировать хранение и теперь хочешь хранить не доллары+центы, а доллары умноженные на 100. Если у тебя один общий объект, ты должен по всему коду в сервисе и в БД поменять 1 поле на два + всю связанную логику. Если два отдельных объекта: поменял только часть на стороне БД и живешь дальше спокойно
— связка REST API <-> сервис: ну тут вообще часто бывают изменения во внутренних сервисах, которые не должны никак затрагивать REST API, оставляя его неизменным. Например, пришла пора порефакторить внутри код и вынести какую-то логику в отдельный сервис. Вот у тебя информация об автомобиле приходила в одном объекте, а теперь есть отдельный сервис для хранения и расчетов по технической части. Тогда тебе надо, чтобы информация также и приходила в одном объекте через АПИ, а потом надо побить его на два объекта: каждый в свой сервис пойдет
— UI <-> REST API: тоже часто бывают изменения, например, когда сущности/элементы UI меняют свое название либо требуют отдельных полей для удобства работы. Ну например, был у тебя один элемент для тех же долларов+центов, ты его там строкой показывал. А теперь понадобилось сделать два отдельных элемента, да чтобы они еще и отдельно каждые могли изменяться пользователем. Сплетешь флоатинг филд, приходящий с РЕСТ АПИ, на два Филда по Инту на каждый и биндишь его к своим двум элементам управления на UI.

В целом, надо всегда думать головой и выбирать, что уместнее в каждом конкретном случае. Где-то и один и тот же объект удобнее таскать А где-то внутренние entity будут всегда жестко связаны с БД и быть один-в-один с таблицами/колонками.
Патриот здравого смысла
Re[7]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 10:32
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, Qulac, Вы писали:


Q>>А ради чего дрючиться, ради какой такой святой цели? Что бы с "оптимизировать" код который имеет низкую ценность и вообще ни на что не влияет?


S>А зачем плодить лишние сущности? Вот в чем вопрос. Какой реальный смысл создавать одинаковые классы на каждом уровне и потом еще и маппить один в один?


Вот опять вопрос понимания. Сущности сидят в БЛ, а тут нет сущностей, тут классы, просто так удобней. Вообще класс — это синтаксическая конструкция языка, а будет он сущностью или нет зависит от того, как мы им пользуемся.
Программа – это мысли спрессованные в код
Re: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 12:46
Оценка: +1 -1
Здравствуйте, Shmj, Вы писали:

S>Вопрос такой.


S>Вот, обычно делают слои и на уровне каждого слоя свои объект — для строгого разделения. А потом мапперы между слоями.


S>Но задумался — а какие реальные бонусы?

Реальные бонусы для кого?

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

Для разработчика зачастую бонусы есть:
— возможность написать много кода, с разумным оправданием. Программисты зачастую испытывают удовольствие от написания кода и создания «архитектуры», даже если мела ной потребности в этом нет
— возможность дороже продать свою работу. написать одну строку стоит в 10 раз дешевле, чем написать 10 строк.
— возможность применить больше хайповых паттернов и библиотек, чтобы написать в резюме. В одну строку много паттернов не запихнешь, а в 10 уже можно.
Re[2]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 12:55
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

Вы сейчас о чем говорите? Самая дорогая часть это UI. Туда обычно тратится больше всего времени аналитиков, дизайнеров, и разработчиков. Это касается и веба, где ui от бизнес-логики отделен http-вызовами, и десктоп приложений, где визуальное представление связано с логикой через viewmodel/presenter.

А на втором месте по объему затрат и кода занимает работа с базой и обеспечение согласованности.

Если вы отделяете работу с базой от БЛ, то что выполняется в БЛ после того как вы вытащили данные из базы и перед тем как отдали в UI?
Re[3]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 13:38
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, Qulac, Вы писали:


Q>>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

G>Вы сейчас о чем говорите? Самая дорогая часть это UI. Туда обычно тратится больше всего времени аналитиков, дизайнеров, и разработчиков. Это касается и веба, где ui от бизнес-логики отделен http-вызовами, и десктоп
приложений, где визуальное представление связано с логикой через viewmodel/presenter.

Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

G>А на втором месте по объему затрат и кода занимает работа с базой и обеспечение согласованности.

Это почти все бизнес-логика, как и должно быть.

G>Если вы отделяете работу с базой от БЛ, то что выполняется в БЛ после того как вы вытащили данные из базы и перед тем как отдали в UI?


Преобразование к модели вида, т.е. данные отображения.
Программа – это мысли спрессованные в код
Re[2]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 13:45
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Если для заказчика/стейкхолдера/пользователя, то очевидно никаких. Тому кто платит деньги и конечному пользователю без разницы сколько у вас слоев, дто и мапперов.


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

И что заказчику делать, если разработчик три дня исправляет простой баг а после исправления создает новый баг? Выгонять?

Ок, выгнал (а скорее тот сам ушел еще до того, как проблема стала очевидной). Берет нового — новый говорит что нужно все переписывать с нуля. Берет другого — тот делает вид что работает, месяц делает вид, два — говорит что еще разбирается в проекте. А потом начинает работать еще медленнее.
=сначала спроси у GPT=
Re[3]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 14:32
Оценка: 78 (1)
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, gandjustas, Вы писали:


G>>Если для заказчика/стейкхолдера/пользователя, то очевидно никаких. Тому кто платит деньги и конечному пользователю без разницы сколько у вас слоев, дто и мапперов.


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


А откуда мнение что код с кучей dto и мапперов менее запутанный и проще поддерживается чем без него?
Я вот проводил замеры maintainability index для кода с разделением и без и не код с разделением стабильно проигрывал.
Это потом что maintainability index зависит от halastead volume, по сути от нормированного количества строк.

В целом я не понимаю как увеличение количества кода может положительно сказываться на стоимости поддержки.

S>И что заказчику делать, если разработчик три дня исправляет простой баг а после исправления создает новый баг? Выгонять?

Чтобы ответить на этот вопрос надо понимать почему так происходит.

S>Ок, выгнал (а скорее тот сам ушел еще до того, как проблема стала очевидной). Берет нового — новый говорит что нужно все переписывать с нуля. Берет другого — тот делает вид что работает, месяц делает вид, два — говорит что еще разбирается в проекте. А потом начинает работать еще медленнее.

Если ты заказчик, который не разбирается в процессе, то плати только за результат, а не за время
Re[4]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 14:57
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.


Q>Преобразование к модели вида, т.е. данные отображения.

То есть то, что делает маппер?
Re[5]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 15:17
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, Qulac, Вы писали:


Q>>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

G>Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.

Если вы используете какую ни будь хорошую библиотеку для ui, то все практические превращается в банальное формошлебство — т.е. соединение одного с другим. Это если правильно делать. Приведу пример из практики как не правильно. Дано: штук 5 справочников к которым нужно приделать новый фронт на реакт + добавить возможность редактирования. Все уже для этого есть и компонеты и дизайн. Казалось бы делай вот так:

1. Получили из апи данные справочника
2. Загрузили из другого апи данные выпадающего списка
3. Отправили на апи результат из диалоговой формы
4. Перешли к другому справочнику

На фронтенду захотелось сделать универсальный для таких случаев способ, т.е. что бы один запрос возвращал json который описывает данные, поля, выпадающие списки и прочее что может быть в форме. В результате конечно полезли баги, а как это работает через неделю уже не вспомнишь. Вот на пустом месте сами себе создали проблему и дрючились. И такое где react и vue встречается довольно часто, т.е. люди сами себе усложняют задачу, зачем и ради какой цели — не понятно. И это только один пример у меня было еще хлеще.

Q>>Преобразование к модели вида, т.е. данные отображения.

G>То есть то, что делает маппер?

Нет, маппер к нужным видам приводит, их может быть несколько разных, бл возвращает данные такими какие они есть в бд.
Программа – это мысли спрессованные в код
Отредактировано 29.11.2025 15:17 Qulac . Предыдущая версия .
Re[6]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 17:09
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Здравствуйте, gandjustas, Вы писали:


G>>Здравствуйте, Qulac, Вы писали:


Q>>>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

G>>Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.

Q>Если вы используете какую ни будь хорошую библиотеку для ui, то все практические превращается в банальное формошлебство — т.е. соединение одного с другим. Это если правильно делать. Приведу пример из практики как не правильно. Дано: штук 5 справочников к которым нужно приделать новый фронт на реакт + добавить возможность редактирования. Все уже для этого есть и компонеты и дизайн. Казалось бы делай вот так:


Q>1. Получили из апи данные справочника

Q>2. Загрузили из другого апи данные выпадающего списка
Q>3. Отправили на апи результат из диалоговой формы
Q>4. Перешли к другому справочнику
То есть предлагаете копипастить кучи кода?

А что делать на нетривиальных формах?
— кода видимость/обязательность одних элементов зависит от значен у других?
— когда используются справочники, в том числе каскадные ?
— когда а одной форме есть mater-detail и логика работающая на всех detail записях?

На стороне бл это простое дерево объектов: получили, обновили из запроса, записали в базу.
А на стороне клиента это тонна логики

Q>На фронтенду захотелось сделать универсальный для таких случаев способ, т.е. что бы один запрос возвращал json который описывает данные, поля, выпадающие списки и прочее что может быть в форме. В результате конечно полезли баги, а как это работает через неделю уже не вспомнишь. Вот на пустом месте сами себе создали проблему и дрючились. И такое где react и vue встречается довольно часто, т.е. люди сами себе усложняют задачу, зачем и ради какой цели — не понятно. И это только один пример у меня было еще хлеще.

То есть вы против dry на клиенте, потому что создание повторно используемого кода это сложно?
Может на сервере делать также? Просто скопипастить код в контроллерах, и поменять запросы?

Q>>>Преобразование к модели вида, т.е. данные отображения.

G>>То есть то, что делает маппер?

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

Ну выглядит так, что именно это маппер и делает. В чем тогда заключается БЛ, если отделяем её от запросов?
Re[7]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 17:21
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, Qulac, Вы писали:


Q>>Здравствуйте, gandjustas, Вы писали:


G>>>Здравствуйте, Qulac, Вы писали:


Q>>>>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

G>>>Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.

Q>>Если вы используете какую ни будь хорошую библиотеку для ui, то все практические превращается в банальное формошлебство — т.е. соединение одного с другим. Это если правильно делать. Приведу пример из практики как не правильно. Дано: штук 5 справочников к которым нужно приделать новый фронт на реакт + добавить возможность редактирования. Все уже для этого есть и компонеты и дизайн. Казалось бы делай вот так:


Q>>1. Получили из апи данные справочника

Q>>2. Загрузили из другого апи данные выпадающего списка
Q>>3. Отправили на апи результат из диалоговой формы
Q>>4. Перешли к другому справочнику
G>То есть предлагаете копипастить кучи кода?

Тут в копипастинге нет ни чего плохого, потому что это не приводит к проблемам. В конце концов есть наследование, можно его использовать.

G>А что делать на нетривиальных формах?

G>- кода видимость/обязательность одних элементов зависит от значен у других?
G>- когда используются справочники, в том числе каскадные ?
G>- когда а одной форме есть mater-detail и логика работающая на всех detail записях?

Что делать, писать код.

G>На стороне бл это простое дерево объектов: получили, обновили из запроса, записали в базу.

G>А на стороне клиента это тонна логики

Q>>На фронтенду захотелось сделать универсальный для таких случаев способ, т.е. что бы один запрос возвращал json который описывает данные, поля, выпадающие списки и прочее что может быть в форме. В результате конечно полезли баги, а как это работает через неделю уже не вспомнишь. Вот на пустом месте сами себе создали проблему и дрючились. И такое где react и vue встречается довольно часто, т.е. люди сами себе усложняют задачу, зачем и ради какой цели — не понятно. И это только один пример у меня было еще хлеще.

G>То есть вы против dry на клиенте, потому что создание повторно используемого кода это сложно?

Оно просто не нужно.

G>Может на сервере делать также? Просто скопипастить код в контроллерах, и поменять запросы?


Q>>>>Преобразование к модели вида, т.е. данные отображения.

G>>>То есть то, что делает маппер?

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

G>Ну выглядит так, что именно это маппер и делает. В чем тогда заключается БЛ, если отделяем её от запросов?

Еще раз, видом у сущности может быть много, не пихать же каждый в бл, поэтому бл должна возвращать данные в каком — то одном виде, а уже потом это будет преобразоваться.
Программа – это мысли спрессованные в код
Re[2]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 18:08
Оценка:
Здравствуйте, DiPaolo, Вы писали:

DP>Давай на примерах:


а давай

DP>- связка сервис <-> слой БД: ты захотел оптимизировать хранение и теперь хочешь хранить не доллары+центы, а доллары умноженные на 100. Если у тебя один общий объект, ты должен по всему коду в сервисе и в БД поменять 1 поле на два + всю связанную логику. Если два отдельных объекта: поменял только часть на стороне БД и живешь дальше спокойно


Ну можно же 1 поле добавить для хранения а то что было ранее — сделать Transient (не хранится в базе) — а сразу вычисляется на основе нового поля, которое хранится в базе. Тогда 1 изменение и все. А вам с вашим разделением строгим — еще в маппере нужно менять, то есть 2 изменения против одного.

Получается код с единственным классом — выигрывает

DP>- связка REST API <-> сервис: ну тут вообще часто бывают изменения во внутренних сервисах, которые не должны никак затрагивать REST API, оставляя его неизменным. Например, пришла пора порефакторить внутри код и вынести какую-то логику в отдельный сервис. Вот у тебя информация об автомобиле приходила в одном объекте, а теперь есть отдельный сервис для хранения и расчетов по технической части. Тогда тебе надо, чтобы информация также и приходила в одном объекте через АПИ, а потом надо побить его на два объекта: каждый в свой сервис пойдет


Ну тут еще вот в чем дело. В этом проекте нет строгости — то есть для части объектов есть маппинг api object -> data enity. Когда это удобно — маппинг есть. Примерно в 40% случаев. Но только когда это имеет смысл.

Я же думаю над тем чтобы не решать имеет смысл или нет — а делать строгое разделение для всех случаев.

И сейчас пытаюсь понять плюсы и минусы.

Похоже что плюсов особо нет.

Т.е. еще раз. В этом проекте нет именно что строгой идеи — что будем делать только так. В одном месте для одного случая разделение объектов добавили — кое-где даже ViewModel есть. А в других случаях разделения нет и api object отображается прямо на форме.

DP>- UI <-> REST API: тоже часто бывают изменения, например, когда сущности/элементы UI меняют свое название либо требуют отдельных полей для удобства работы. Ну например, был у тебя один элемент для тех же долларов+центов, ты его там строкой показывал. А теперь понадобилось сделать два отдельных элемента, да чтобы они еще и отдельно каждые могли изменяться пользователем. Сплетешь флоатинг филд, приходящий с РЕСТ АПИ, на два Филда по Инту на каждый и биндишь его к своим двум элементам управления на UI.


Ну так можно же методы-расширения/mixin добавить для таких редких случаев. Т.е. оставляете тот же объект, но в отдельной папочке пишите extension — и добавляете поверх новые свойства.

Тут вопрос — стоит ли брать за правило обязательное разделение или же делать его опциональным только там где это действительно нужно.

DP>В целом, надо всегда думать головой и выбирать, что уместнее в каждом конкретном случае. Где-то и один и тот же объект удобнее таскать А где-то внутренние entity будут всегда жестко связаны с БД и быть один-в-один с таблицами/колонками.


Тут же нет запрета — хочешь создавай спец. объект для отдельного слоя.

Вопрос лишь вот в чем: если взять это за обязательное правило — то в чем плюсы?
=сначала спроси у GPT=
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.