Абасс... обсудите рахитекурту
У нас кстати тоже подобный паттерн довели до абсолюта - для любой операции существует свой код. Сохраняем объект так-то - одни код, сяк-то - другой. Там ещё можно их комбинировать. Поначалу казалось неплохо, а потом этих операций развелось... и отличаются друг от друга для одной сущности в небольших деталях. Потом на проект приходит новичок, и не понимает, какую правильную операцию из пары десятков выбрать для какой задачи. На вид они все похожи. Ну и начинает делать свой двадцать первый вариант, подсматривая поведение из предыдущих двадцати. Юнит оф ворк, мать его. Если бы тупо всё писалось по месту применения - в каждой форме или её модели, без отсылок к слою паттернов-шматтернов, было бы то же самое, но без лишнего слоя или двух.
Какие такие шматтерны? Это вообще никого не интересует. Тут начальнички всех мастей грызуться и сходят с ума, и скоро похоронят всю индустрию нафиг. Понравились фразы из комментов: "Не связано ли это с тем, что весь крупняк за последние 15 лет в той или иной степени сросся с Левиафаном и перенял у него склонность к сохранению лояльных, а не высокопрофессиональных кадров?", "ПМ просто бегает вокруг команды и следит, чтобы с лица заказчика не слезала улыбка". Только одно непонятно - на всё это кто-то должен слить прорвы денег. Кого кидают?
а переименовать я потом могу по вкусу.
Из опыта - подобное обычно не наступает никогда.
Вот интересно узнать ваше мнение: сделали мне ревью кода, а я говорю - некогда фигней маяться, завтра сдавать, и так постоянно. Это правильно? Куда придём в итоге?
Главное, что код работает как мне нужно
Есть только надежда, что когда то вы поймете, что главное не в работающем коде, как мне сейчас нужно.
И чем дольше в чей-то говнокод будешь погружаться, тем больше будет сужаться твоё мировоззрение и подходы
вот именно, главное что бы код работал как надо
а переименовать я потом могу по вкусу.Из опыта - подобное обычно не наступает никогда.
F2, "бла-бла".
Главное, что код работает как мне нужноЕсть только надежда, что когда то вы поймете, что главное не в работающем коде, как мне сейчас нужно.
Вы щас опять со своего острова, где все проекты на 100% вперёд проработаны и все знают изначально, чего хотят. А у меня пока непонятно, во что это выйти может - разработка экспериментальная. Может, я объединю эти свойства, а может добавлю других.
где все проекты на 100% вперёд проработаны и все знают изначально, чего хотят
У вас несколько искаженное представление о нашем острове.
Но у нас на любом этапе есть некая система, а не так - хряк, хряк, хряк и готово. И где каждый отдельный хряк еще долго обдумывается.
Может, я объединю эти свойства, а может добавлю других.
опять таки, речь идет о конкретной части, а не о всей системе.
Попробуйте чисто для себя, лично, задуматься о всей системе и как бы вы ее спроектировали "правильно". Есть большое подозрение, что подобных классов бы не понадобилось в принципе.
где все проекты на 100% вперёд проработаны и все знают изначально, чего хотятУ вас несколько искаженное представление о нашем острове.
Но у нас на любом этапе есть некая система, а не так - хряк, хряк, хряк и готово. И где каждый отдельный хряк еще долго обдумывается.
А бывает, что надо срочно хрякнуть, без обдумываний? Ну или вдруг захотелось запрещёночки?
Попробуйте чисто для себя, лично, задуматься о всей системе и как бы вы ее спроектировали "правильно". Есть большое подозрение, что подобных классов бы не понадобилось в принципе.
Нельзя правильно подумать о том, о чём пока не имеешь полного представления. Ну подумал, сделал, потом переподумал и решил сделать по-другому. Мутить полную технологическую канву под это дело, типа техзадание, дизайн-документ, архитектуру, тесты, и лишь потом писать код - это и бессмысленно, и кайфа нет. Прямой путь к забросу проекта. И вообще, у нас же аджайл в моде - делаем по велению левой пятки в темпе спринта, потом по велению правой пятки.
Вы не понимаете. Я свой проект разрабатываю как прототип, и чтобы было самому интересно. Я сделал что-то, что мне хотелось больше всего первым попробовать - понравилось. Думаю, хочу добавить это и это - снова понравилось. Потом хочу ещё что-то - архитектура не позволяет - исправляю архитектуру и все прежде сделанные фичи, если исправления их затрагивают. Т.е. проект пока лишь прототип, и много всего не сделано, то так можно довольно долго и много экспериментировать. Когда наделаю фич, что мне будет казаться достаточным, что проект стал неким законченным, с достаточной функциональностью, я это всё более-менее зафиксирую и напишу тесты и прочее подробнее. А сейчас я тесты пишу лишь для основной механики и математических функций.
Работать по заранее сделанному плану можно, если подобный проект хотя бы раз уже делал и знаешь, что надо реализовать в костяке. А я пока не знаю. У меня есть просто идеи, видение, как это должно выглядеть в идеале, но в коде реализации нет. Вот я шаг за шагом делаю прототип, приближающийся к моему видению. Пока получается. Главное, что мне нравится, и почти нет такого, что неделями, а то и месяцами делаешь какую-то неинтересную нудятину.
А бывает, что надо срочно хрякнуть,
Бывает, но всё равно думаешь перед тем как делать
Ну или вдруг захотелось запрещёночки?
Зачем?
Нельзя правильно подумать о том, о чём пока не имеешь полного представления.
Очень даже можно, может быть и не на 100%
Ну типа, перед тем как строить дом делаем для него фундамент. Какие будут окна и крыша фиг его знает сейчас.
типа техзадание, дизайн-документ, архитектуру, тесты
когда то было и такое
и кайфа нет
У кого как Кайф как раз от хорошей архитектуры.
у нас же аджайл в моде - делаем по велению левой пятки в темпе спринта
опять тема для баальшой дискуссии
Я свой проект разрабатываю как прототип, и чтобы было самому интересно
ну именно так для себя и делаю постоянно.
хочу ещё что-то - архитектура не позволяет
Бывает конечно, но на любом этапе она должна быть "правильной". Что под этим понимать будет конечно у каждого по разному.
Но в любом случае это первое о чем думаешь. Код вообще не интересен.
Главное, что мне нравится,
ну так это и есть самое главное. Если делаешь для себя то всё остальное вообще полная ерунда. Хотя всё равно получается так как для других бы делал
Вы не понимаете.
Скорее всего, поэтому и хотелось знать больше. Понять другого человека очень даже не просто.
Видишь абсолютную ерунду делает, а как разберёшься, понятно что с его точки зрения все правильно. Что с этим делать уже другой вопрос, на который часто нет ответа.
Когда наделаю фич
Похоже у нас просто разные подходы к проектированию. У вас похоже снизу вверх, а у меня очень часто наоборот.
За время выполнения теста валидация вызывалась примерно 200 тысяч раз.
Я конечное многое могу понять, но зачем валидировать весь объект после каждого изменения?
В гуях есть одна кнопочка, при нажатии на которую для одного договора валидация вызывается 3,5 тысяч раз.
Ну так сами себе злобные Буратины :) Что мешает вызывать валидацию один раз? Одна кнопка - одно нажатие - одна валидация.
Многое зависит от контекста, но давай возьмем простой пример: есть некий объект с множеством зависимых друг от друга пропертей. Этот объект пересылается от А к Б в виде XML/JSON и потом восстанавливается. В общем случае, валидировать при изменении проперти (при десериализации) нельзя, т.к. мы не можем гарантировать, что сначала будут десериализованы "базовые" проперти, а потом "зависимые". Следовательно после десериализации
мы должны иметь возможность валидировать весь объект.
Я конечное многое могу понять, но зачем валидировать весь объект после каждого изменения?
А вдруг? Потому что каждая операция "независима" и не знает ничего о том кто вызывался до нее, а кто после. И она "согласованная" (consistent). Т.е. результатом каждой операции должен быть валидный объект. А значит что? Каждая операция после изменений валидирует. А пока был один большой метод, он и отрабатывал. После каждой операции.
Ну так сами себе злобные Буратины :) Что мешает вызывать валидацию один раз? Одна кнопка - одно нажатие - одна валидация.
Не-не. Кнопка-то одна, и "пользовательское действие" одно - "ausfertigen". А сам процесс, который это нажатие запускает, если расписать то 5 листов в пдф получается. И после каждой операции валидируем. Чтобы "вовремя остановиться". Ведь каждая операция у нас что? Независимая и согласованная. Прям как транзакция. И её можно использовать в куче других процессов. И это правильно, да. Но по уму валидировать надо не всё в бооольшой сети объектов. А только изменения. Добавил застрахованное здание - мне не надо валидировать 10 других зданий, только добавленное.
Этот объект пересылается от А к Б в виде XML/JSON и потом восстанавливается. В общем случае, валидировать при изменении проперти (при десериализации) нельзя, т.к. мы не можем гарантировать, что сначала будут десериализованы "базовые" проперти, а потом "зависимые".
Очень даже можно. Начиная от "подсказок" в каком порядке вызывать сеттеры десериализатору и кончая написанием своего десериализатора. Получил от JSON-а мэп и десериализируй как тебе надо. Я это, конечно, про явовские jackson и gson, но думаю в шарповских библиотеках всё достаточно похоже.
Иногда и циклическая зависимость появиться может. А зависит от Б, Б от В, а В снова от А. Тогда прячем сеттеры, в сеттерах не валидируем, а делаем подходящую по смыслу операцию, которой одновременно передаются и А, Б и В. Ну а если всё ещё сложнее (что только не придумают бвл-щики, лишь бы не думать) то говорим - сорян, сам объект ничего не гарантирует, валидация только общая (всего объекта целиком), и не вызывается при каждом изменении.
В общем я это к чему: валидацию всего объекта в одном методе (классе) я теперь делаю только тогда, когда это внешняя валидация. Не внутри самого класса. И когда валидируемый класс никаких обещаний о своей "верности" не делает (в документации).
За время выполнения теста валидация вызывалась примерно 200 тысяч раз.Я конечное многое могу понять, но зачем валидировать весь объект после каждого изменения?
В вашем примере в мной немного переписанном вашем примере (справа) на каждое изменение свойства Param или ParamVolatile вызывается валидация всего объекта - оба свойства валидируются. Я же предлагал ввести отдельные методы для валидации зависимых свойств. Т.е. если 2 свойства зависимы, то оба получают один валидатор, внутри которого проверяются оба эти свойства. Не нужно делать все возможные комбинации проверок, а только отдельных независимых свойств и зависимых свойств.
Этот объект пересылается от А к Б в виде XML/JSON и потом восстанавливается. В общем случае, валидировать при изменении проперти (при десериализации) нельзя, т.к. мы не можем гарантировать, что сначала будут десериализованы "базовые" проперти, а потом "зависимые". Следовательно после десериализации мы должны иметь возможность валидировать весь объект.
А зачем вам валидировать объект при сериализации-десериализации? Защита от изменения сериализованного объекта при его передаче? Или вы тестируете фреймворки сериализации, правильно ли и без ошибок они работают?
У некоторых до маразма доходит - любой слой валидирует объект, даже если это всё в пределах одно оперативной памяти происходит. "На всякий случай". Если вы в такой враждебной среде запускаете код, что боитесь изменения при использовании даже оперативки, то тут явно другой подход нужен, а не бесполезная в этом случае валидация на каждом шаге.
Я вообще предлагал в типичных приложениях делать лишь валидацию на сервере при важных операциях, типа записи в БД, а пользовательский ввод задавить в рамки принудительной валидации, когда контролы просто не позволяют вводить неправильные значения. Если нужна защита не от дурака или случайности, а от специального вредителя, то это не валидацией делается.
Очень даже можно. Начиная от "подсказок" в каком порядке вызывать сеттеры десериализатору и кончая написанием своего десериализатора. Получил от JSON-а мэп и десериализируй как тебе надо. Я это, конечно, про явовские jackson и gson, но думаю в шарповских библиотеках всё достаточно похоже.
Конечно всё там есть. И полностью кастомная сериализация-десериализация есть.
https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Jso...
https://www.newtonsoft.com/json/help/html/JsonPropertyOrde...
Иногда и циклическая зависимость появиться может. А зависит от Б, Б от В, а В снова от А. Тогда прячем сеттеры, в сеттерах не валидируем, а делаем подходящую по смыслу операцию, которой одновременно передаются и А, Б и В.
Некоторые сериализаторы могут сохранять ссылки на объкты - один раз сохранил объект в формате сериализации, и потом везде на его копии ссылки вставляются. Я сделал проще - у меня БД на клиенте, и она небольшая, поэтому к свойствам с объектом MyType MyObject я просто добавляю его айдишник int MyObjectId, который и сериализую (а сам объект - нет). Близко к сохранению ссылки на объект в формате сериализации.
Ну а если всё ещё сложнее (что только не придумают бвл-щики, лишь бы не думать) то говорим - сорян, сам объект ничего не гарантирует, валидация только общая (всего объекта целиком), и не вызывается при каждом изменении.
Ещё вариант - при десериализации присваивать значения полям поддержки свойств, а не самим свойствам. Т.к. валидация запускается обычно через свойства, то она не будет вызываться, если в конструкторе не вызывать их сеттеры.
Сериализовать и десериализовать айди вместо всего объекта просто. Для коллекций там сложнее. У меня есть такая конструкция. Тут бизнес логика работает лишь со свойством Items (комментарий "for business logic"), а всё остальное - обвязка. Приватные члены не сериализуются (если не обозначить атрибутом JsonProperty). Сериализуется лишь список айдишников ItemIds, который просто проходится по списку предметов, выбирая их айдишники. Для бизнес логики обвязка в виде ItemIds не используется, хотя может. Вместо ленивой инициализации можно использовать инициализацию в конструкторе. Но репозиторий тогда тоже должен быть доступен в нём же - т.е. в процессе десериализации. А это иногда нетривиально сделать. Поэтому ленивая загрузка - один из выходов.
// for deserialization and lazy initialization of Items List<int> itemIds; // for serialization [JsonProperty] List<int> ItemIds => Items.Select(i => i.Id).ToList(); // for lazy initialization of Items and as a backing field for it List<Item> items; // for business logic [JsonIgnore] public List<Item> Items => items ??= itemIds ?.Select(/* obtain item from somewhere by its id */) .ToList() ?? new List<Item>(); [JsonConstructor] public MyClass(List<int> itemIds) { this.itemIds = itemIds; }