Вот, обычно делают слои и на уровне каждого слоя свои объект — для строгого разделения. А потом мапперы между слоями.
И у меня сейчас проект, который нужно дорабатывать. Там этой парадигмы разделения не придерживались строго, так что в ui проникают как dto, так и entity. Проект пока не большой, около 25 тыс. строк кода, т.е. за пару-тройку дней можно разделить и добавить мапперы.
Но задумался — а какие реальные бонусы? Вот что пишет зазнайка:
Если использовать DTO в Домене: Ваша бизнес-логика становится зависимой от API-контрактов. Если фронтенд попросит переименовать поле в JSON для удобства отображения, вам придется менять это поле в бизнес-логике, что может повлечь ошибки в расчетах. Внешний мир начинает диктовать правила внутреннему.
Если использовать Entity в Домене: Ваша бизнес-логика зависит от схемы базы данных. Если вы решите денормализовать таблицу для производительности или сменить PostgreSQL на MongoDB, вам придется переписывать бизнес-правила.
Правило архитектуры: Зависимости должны быть направлены внутрь. Слой Домена (бизнес-логика) должен быть самым стабильным и не зависеть ни от Базы Данных, ни от UI/API.
Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.
Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.
Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.
Далее. Если добавим тесты и фейковые реализации сервисов — то что мешает в этих фейковых реализациях использовать уже существующие классы для объектов, ведь у них есть конструктор...
По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.
Здравствуйте, 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...
Здравствуйте, 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...
Здравствуйте, 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 - //возвращаем в нужном формате
}
}
Здравствуйте, 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...
Здравствуйте, 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...
Здравствуйте, 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...
Здравствуйте, 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...
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...
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, Qulac, Вы писали:
Q>>А ради чего дрючиться, ради какой такой святой цели? Что бы с "оптимизировать" код который имеет низкую ценность и вообще ни на что не влияет?
S>А зачем плодить лишние сущности? Вот в чем вопрос. Какой реальный смысл создавать одинаковые классы на каждом уровне и потом еще и маппить один в один?
Вот опять вопрос понимания. Сущности сидят в БЛ, а тут нет сущностей, тут классы, просто так удобней. Вообще класс — это синтаксическая конструкция языка, а будет он сущностью или нет зависит от того, как мы им пользуемся.
Программа – это мысли спрессованные в код
Re: Что если не разделять строго dto, entity, bo...
Здравствуйте, Shmj, Вы писали:
S>Вопрос такой.
S>Вот, обычно делают слои и на уровне каждого слоя свои объект — для строгого разделения. А потом мапперы между слоями.
S>Но задумался — а какие реальные бонусы?
Реальные бонусы для кого?
Если для заказчика/стейкхолдера/пользователя, то очевидно никаких. Тому кто платит деньги и конечному пользователю без разницы сколько у вас слоев, дто и мапперов.
Для разработчика зачастую бонусы есть:
— возможность написать много кода, с разумным оправданием. Программисты зачастую испытывают удовольствие от написания кода и создания «архитектуры», даже если мела ной потребности в этом нет
— возможность дороже продать свою работу. написать одну строку стоит в 10 раз дешевле, чем написать 10 строк.
— возможность применить больше хайповых паттернов и библиотек, чтобы написать в резюме. В одну строку много паттернов не запихнешь, а в 10 уже можно.
Re[2]: Что если не разделять строго dto, entity, bo...
Здравствуйте, Qulac, Вы писали:
Q>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.
Вы сейчас о чем говорите? Самая дорогая часть это UI. Туда обычно тратится больше всего времени аналитиков, дизайнеров, и разработчиков. Это касается и веба, где ui от бизнес-логики отделен http-вызовами, и десктоп приложений, где визуальное представление связано с логикой через viewmodel/presenter.
А на втором месте по объему затрат и кода занимает работа с базой и обеспечение согласованности.
Если вы отделяете работу с базой от БЛ, то что выполняется в БЛ после того как вы вытащили данные из базы и перед тем как отдали в UI?
Re[3]: Что если не разделять строго dto, entity, bo...
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Qulac, Вы писали:
Q>>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги. G>Вы сейчас о чем говорите? Самая дорогая часть это UI. Туда обычно тратится больше всего времени аналитиков, дизайнеров, и разработчиков. Это касается и веба, где ui от бизнес-логики отделен http-вызовами, и десктоп
приложений, где визуальное представление связано с логикой через viewmodel/presenter.
Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.
G>А на втором месте по объему затрат и кода занимает работа с базой и обеспечение согласованности.
Это почти все бизнес-логика, как и должно быть.
G>Если вы отделяете работу с базой от БЛ, то что выполняется в БЛ после того как вы вытащили данные из базы и перед тем как отдали в UI?
Преобразование к модели вида, т.е. данные отображения.
Программа – это мысли спрессованные в код
Re[2]: Что если не разделять строго dto, entity, bo...
Здравствуйте, gandjustas, Вы писали:
G>Если для заказчика/стейкхолдера/пользователя, то очевидно никаких. Тому кто платит деньги и конечному пользователю без разницы сколько у вас слоев, дто и мапперов.
Для заказчика важно чтобы скорость разработки и поддержки была приемлемой, будет плохо если один простой баг будут исправлять день а то и несколько дней. И никто на земле не сможет исправить быстрее, ведь там слишком все запутано как узелок с нитками.
И что заказчику делать, если разработчик три дня исправляет простой баг а после исправления создает новый баг? Выгонять?
Ок, выгнал (а скорее тот сам ушел еще до того, как проблема стала очевидной). Берет нового — новый говорит что нужно все переписывать с нуля. Берет другого — тот делает вид что работает, месяц делает вид, два — говорит что еще разбирается в проекте. А потом начинает работать еще медленнее.
=сначала спроси у GPT=
Re[3]: Что если не разделять строго dto, entity, bo...
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, gandjustas, Вы писали:
G>>Если для заказчика/стейкхолдера/пользователя, то очевидно никаких. Тому кто платит деньги и конечному пользователю без разницы сколько у вас слоев, дто и мапперов.
S>Для заказчика важно чтобы скорость разработки и поддержки была приемлемой, будет плохо если один простой баг будут исправлять день а то и несколько дней. И никто на земле не сможет исправить быстрее, ведь там слишком все запутано как узелок с нитками.
А откуда мнение что код с кучей dto и мапперов менее запутанный и проще поддерживается чем без него?
Я вот проводил замеры maintainability index для кода с разделением и без и не код с разделением стабильно проигрывал.
Это потом что maintainability index зависит от halastead volume, по сути от нормированного количества строк.
В целом я не понимаю как увеличение количества кода может положительно сказываться на стоимости поддержки.
S>И что заказчику делать, если разработчик три дня исправляет простой баг а после исправления создает новый баг? Выгонять?
Чтобы ответить на этот вопрос надо понимать почему так происходит.
S>Ок, выгнал (а скорее тот сам ушел еще до того, как проблема стала очевидной). Берет нового — новый говорит что нужно все переписывать с нуля. Берет другого — тот делает вид что работает, месяц делает вид, два — говорит что еще разбирается в проекте. А потом начинает работать еще медленнее.
Если ты заказчик, который не разбирается в процессе, то плати только за результат, а не за время
Re[4]: Что если не разделять строго dto, entity, bo...
Здравствуйте, Qulac, Вы писали:
Q>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.
Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.
Q>Преобразование к модели вида, т.е. данные отображения.
То есть то, что делает маппер?
Re[5]: Что если не разделять строго dto, entity, bo...
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Qulac, Вы писали:
Q>>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает. G>Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.
Если вы используете какую ни будь хорошую библиотеку для ui, то все практические превращается в банальное формошлебство — т.е. соединение одного с другим. Это если правильно делать. Приведу пример из практики как не правильно. Дано: штук 5 справочников к которым нужно приделать новый фронт на реакт + добавить возможность редактирования. Все уже для этого есть и компонеты и дизайн. Казалось бы делай вот так:
1. Получили из апи данные справочника
2. Загрузили из другого апи данные выпадающего списка
3. Отправили на апи результат из диалоговой формы
4. Перешли к другому справочнику
На фронтенду захотелось сделать универсальный для таких случаев способ, т.е. что бы один запрос возвращал json который описывает данные, поля, выпадающие списки и прочее что может быть в форме. В результате конечно полезли баги, а как это работает через неделю уже не вспомнишь. Вот на пустом месте сами себе создали проблему и дрючились. И такое где react и vue встречается довольно часто, т.е. люди сами себе усложняют задачу, зачем и ради какой цели — не понятно. И это только один пример у меня было еще хлеще.
Q>>Преобразование к модели вида, т.е. данные отображения. G>То есть то, что делает маппер?
Нет, маппер к нужным видам приводит, их может быть несколько разных, бл возвращает данные такими какие они есть в бд.
Здравствуйте, 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...
Здравствуйте, 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...
Здравствуйте, 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 будут всегда жестко связаны с БД и быть один-в-один с таблицами/колонками.
Тут же нет запрета — хочешь создавай спец. объект для отдельного слоя.
Вопрос лишь вот в чем: если взять это за обязательное правило — то в чем плюсы?