Зарегистрироваться | Поиск |
Результаты опроса: Какой вариант вы бы предпочли? И почему? | |||
validateAndWrite() + validateAndWriteNoThrow() | 1 | 8.33% | |
validateAndWriteOrThrow() + validateAndWrite() | 0 | 0% | |
validateAndWrite(boolean noThrow = false) | 1 | 8.33% | |
validateAndWrite(boolean noThrow = true) | 0 | 0% | |
validateAndWrite(boolean throwIfError = false) | 0 | 0% | |
validateAndWrite(boolean throwIfError = true) | 2 | 16.67% | |
я предложил свой вариант в этой ветке | 2 | 16.67% | |
затрудняюсь ответить, просто хочу посмотреть результаты опроса | 6 | 50.00% | |
Голосовавшие: 12. Вы ещё не голосовали в этом опросе |
|
Опции темы |
|
30.07.2021, 13:14 | #1 |
Участник
|
[CodeStyle] методы *noThrow vs *OrThrow vs optional parameter?
Вопрос про стиль кодирования. Любая версия аксапты.
Disclaimer: Понимаю, что о стилях не спорят. Поэтому спрошу "а как вы предпочитаете делать сами"? Мало того, чтобы отсечь уложняющие моменты, вопрос будет не о стандартной аксапте, а о самописном методе. Итак, в жизни есть методы, которые могут вернуть true/false, а могут бросить исключение. типичный пример: вы создаете метод validateAndWrite(). этот метод выполняет validateWrite() и write(). по идее, метод validateAndWrite может: * вернуть true/false, тогда вызывающий метод обязан обработать результат и что-то сделать. * бросить исключение если validateWrite не прошел. а можно создать два метода - один бросает исключение, а второй возвращает true/false. также можно добавить опциональный параметр в единственный метод. И тут собственно вопрос по CodeStyle. Какой вариант вы бы предпочли? И почему? |
|
30.07.2021, 13:25 | #2 |
Участник
|
Цитата:
В чем смысл одной функции с функционалом двух не очевидно |
|
30.07.2021, 13:38 | #3 |
Участник
|
Цитата:
Есть у кого ответы про стиль кодирования? Спасиба. |
|
30.07.2021, 13:47 | #4 |
Участник
|
Увы.
Сферический конь в вакууме конечно интересно, но стиль рождается от практики. Если некорректный пример то смысл рассуждать дальше. |
|
30.07.2021, 13:50 | #5 |
Участник
|
axm2017, спасибо за ваше ценное мнение.
итак, |
|
30.07.2021, 14:37 | #6 |
Участник
|
Возможно я тоже вопроса не понял, но я бы предпочел сделать/иметь один метод с опциональным параметром - ибо зачем плодить сущности в виде двух методов (которые внутри себя, вероятно, ещё вызывают третий с параметром - чтобы код не дублировать)?
|
|
|
За это сообщение автора поблагодарили: mazzy (2). |
30.07.2021, 15:22 | #7 |
Участник
|
Чтобы использование было удобным.
сравни код, который использует такие методы: X++: buf.validateAndWriteOrThrow(); // ок понятно что происходит, и понятно, что результата нет if (buf.validateAndWriteNoThrow()) // тоже понятно, хотя и длинно ... buf.validateAndWrite(); // будет исключение или нет? может просто результат отбрасывается? // легко решить, если в классе реализованы оба метода // легко ошибиться и пропустить результат, если в классе только один метод с опциональным параметром buf.validateAndWrite(false); // а что собственно здесь происходит? // надо заглянуть в класс или посмотреть в tooltip-подсказку Последний раз редактировалось mazzy; 30.07.2021 в 15:27. |
|
30.07.2021, 14:48 | #8 |
Moderator
|
не знаю почему, но я в 95% случаев в своем коде validateWrite() просто не вызываю. Просто мне кажется что механизм этот был придуман для контроля пользовательского ввода. В своем коде я скорее в какие-нибудь транзакционные таблицы или таблицы с документами пишу, в которых validateWrite() обычно отсутствует. Есть конечно 5% случаев когда приходится в справочники или таблицы документов писать (при всяких импортах например), и мне в этих 5% случаев не тяжело руками написать if (table.validateWrite()) table.update()
Вообще я когда в коде вижу расставленые на всех таблицах initValue(), validateField() и validateWrite(), мне сразу приходит в голову что код новичек писал и вызов этих методов - карго-культ. |
|
|
За это сообщение автора поблагодарили: Ace of Database (2), vmoskalenko (5). |
30.07.2021, 17:18 | #9 |
Участник
|
Проголосовал за первый вариант validateAndWrite() + validateAndWriteNoThrow()
Но как и остальным написавшим мне тоже это всё не нравится. Якобы "безопасный" метод, который перехватывает свои исключения и не отдаёт их наружу не должен быть нормой. Это скорее исключение, синтаксический сахар. Это грязный метод, после вызова которого остаётся неопределённость: а что именно выполнилось, что откатилось. Лучше так не делать, а если уж делать такие методы, то пусть их будет видно издалека. |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
30.07.2021, 17:46 | #10 |
Участник
|
а почему только boolean в параметрах. иногда приходится писать что-то где есть 3 значения.
1 - просто возвращать true-false для дизейбла кнопок на форме 2- показывать warning без исключения - когда что-то нельзя сделать, но дальнейший код не прерывать, т.е. типичный сценарий показывать ошибки по всем строкам журнала 3- выдавать исключение Т.е. это один метод типа validateAndWrite с параметром типа enum |
|
30.07.2021, 18:33 | #11 |
Участник
|
Цитата:
но в аксапте в транзакции срабатывает только самый внешний catch. поэтому никаких гарантий перехват не даст. методы NoThrow могут означать, что сам метод исключений не бросает. но исключение внутри этого метода может бросить ядро. Поэтому суффикс NoThrow не дает никаких гарантий относительно исключений. методы с OrThrow означают, что метод содержит throw, который явно вставил автор кода. Цитата:
да, именно про синтаксический сахар, который помогает понять код. и самому не забывать о. пример написания самих методов https://github.com/mazzy-ax/SysUtil/....xpp#L498-L519 пример использования я привел выше Цитата:
(o_O) ты ведь обратил внимание, что мы не сам метод validateAndWrite обсуждаем? а оформление, которое касается исключений (Throw - NoThrow - OrThrow). и о том, как оформление кода может помочь, а может запутать читателя. Последний раз редактировалось mazzy; 30.07.2021 в 18:40. |
|
30.07.2021, 19:23 | #12 |
Участник
|
Обработку исключений я бы делал снаружи. Потому что обработка внутри метода сразу ограничивает возможности его использования. Лучше иметь больше возможностей, чем меньше. Лучше иметь возможность по-разному реагировать на исключения в разных случаях использования такого метода, чем не иметь возможности этим управлять,
|
|
30.07.2021, 19:41 | #13 |
Участник
|
делайте.
(только помните, что любой может начать транзакцию и вызвать ваш код. и ваша обработка тут же превратится а внутри то методы как писать? |
|
30.07.2021, 21:01 | #14 |
Участник
|
Сергей, перечитайте свой исходный пост. Там нет вопроса, как писать внутри. Там вопрос, писать ли один метод или два. Вам отвечают на заданный вопрос, а Вы ожидаете ответов на другой вопрос, который не задавали. Поэтому Вам не нравятся ответы. Попробуйте переформулировать вопрос.
А писать надо красиво и аккуратно. |
|
30.07.2021, 21:11 | #15 |
Участник
|
Вообще говоря, пример с validateWrite + Write наглядный, но вводит в заблуждение относительно самой постановки вопроса. Сразу вопрос о транзакциях, разделении проверки и модификации и т.д. и т.п. Если не рассматривать именно этот пример, а сосредоточится на исходной постановке
Метод возвращает true/false. Если false, то следует ли вызывать исключение вместо возврата false? То тут проблема не столько в разовом (однократном) написании, сколько в сопровождении. Т.е. возможности внесения изменений Например, к указанной постановке задачи еще добавляют, а надо ли в случае false, если это не throw выводить текст сообщения об ошибке? Или, например, делать throw не для всех ошибок, а только для определенных? Если у нас один метод с параметром, то просто добавим еще параметры в этот один метод. А если методов много, то во все придется делать такое добавление. Ну, и традиционно, дублирование кода получаем, что крайне не желательно. Впрочем, об этом уже говорили Т.е. я за один общий метод с параметрами. Насчет того, что придется смотреть, что этот метод делает и что это за параметры, так это в любом случае придется делать. Даже если это будет в исходной постановке с кучей специализированных методов. По многим причинам То же самое и по поводу сокращения написания кода. Ну очень сомнительный аргумент. Далеко не факт, что такое сокращение вообще получится. А в общем случае, основное время разработчик тратит вовсе не на первичное написание кода, а на его отладку.
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
30.07.2021, 23:13 | #16 |
Участник
|
Цитата:
Была и другая вводная. Но я переписал на эту. Цитата:
О validate (который и в runbase есть) и write/update (который и в runbase есть) Да-да. оставлены голые методы голого ядра. в которые тем не менее программист может вставить код. Цитата:
Сообщение от Владимир Максимов
Если не рассматривать именно этот пример, а сосредоточится на исходной постановке
Метод возвращает true/false. Если false, то следует ли вызывать исключение вместо возврата false? То тут проблема не столько в разовом (однократном) написании, сколько в сопровождении. Т.е. возможности внесения изменений Например, к указанной постановке задачи еще добавляют, а надо ли в случае false, если это не throw выводить текст сообщения об ошибке? Или, например, делать throw не для всех ошибок, а только для определенных? как появляются эти noThrow-метод (как я это вижу) 1. разработчики пишут обычный метод, который бросает исключение 2. а потом начинают его вызывать из другого кода, где есть своя транзакция. и... 3. опа! вложенные catch обработчики перестают работать. Надо что-то делать! 4. из обычного метода выделяется смысловая часть в NoThrow-метод, которое возвращает какой-то результат. А выбрасывание исключения оставляется в исходном. Давно уже один раз я видел, когда произошло немножко наоборот. Чел заметил, что он всегда бросает исключение. Поэтому он написал OrThrow-метод. В результате получил очень чистый код в вызывающих методах. Мне тогда очень понравилась эта техника. Чел, проявись, пожалуйста. дай наставить тебе лайков. Цитата:
если посмотреть на https://en.cppreference.com/w/cpp/la.../noexcept_spec https://docs.oracle.com/javase/tutor.../throwing.html то видно, что люди думали над этой задачей. Но не сказать, что пришли к каким-то удовлетворительным решениям. конкретно эта тема появилась здесь после плотного размышления над статьей http://eao197.blogspot.com/2021/07/progthoughts-c.html подумалось о noThrow-методах и о том, а что можно было бы сделать в X++ с его дикими ограничениями. Опять же Котлин - там можно юзать именованные параметры в вызывающих методах. Что сразу делает читающему сухо и комфортно https://kotlinlang.ru/docs/reference/functions.html не говоря уже о контрактах и всевозможнных лямбдах и apply-методах https://stackoverflow.com/questions/...ions-in-kotlin ну и нормально работающих try/catch c finnaly... и эцилопп меня не имеет права бить по ночам ... ладно... в общем, вопрос что можно сделать в X++ Цитата:
расскажите почему вы решили что будет дублирование? ну, хоть на примере noThrow методов в стандартной аксапте пример в ax2009 - InventMovement::construct + InventMovement::constructNoThrow пример в ax2012 - PcGlobalTableConstraintCellEditor::validateIntegerValue + PcGlobalTableConstraintCellEditor::validateIntegerValueNoThrow если хотите, на примере того, что я выложил публично https://github.com/mazzy-ax/SysUtil/....xpp#L496-L519 т.е. вы предпочитаете видеть в вызывающем методе подобный код: X++: buf.validateAndWrite(false) а вы предпочитете видеть true или false для обозначения с исключением или без? или стоит создавать специальный enum? какой стиль лучше на ваш взгляд? особенно для нескольких параметров. Цитата:
поэтому и вопрос - а какие другие причины могут делать тот или иной способ удобнее для читающего? Тю-тю-тю-тю... Стопэ! у меня ничего про "сокращение написания кода" не было. если вы считаете, что было - прошу цитату. с этим никто не спорит. |
|
31.07.2021, 19:20 | #17 |
Участник
|
Цитата:
Сообщение от mazzy
расскажите почему вы решили что будет дублирование?
Ну, написал разработчик метод. Ну, перестал он корректно работать при определенных способах вызова. И что разработчик будет делать? Нет, чисто теоретически, возможно, что разработчик выполнит рефакторинг кода, выделит отдельные методы и организует их вызов, чтобы исключить дублирование кода, но практически будет реализован один из 2 вариантов 1. Будет добавлен параметр в существующий метод 2. Будет создан метод дубликат, где вместо false вызовут исключение. Или наоборот, вместо исключения вернут false. Смотря по тому, что было изначально Поскольку в данной теме речь идет именно о создании методов, то и получим дублирование кода К сожалению, я именно такой сценарий постоянно наблюдаю на практике. Когда большая группа разработчиков работает над одним проектом. Вот не делает никто рефакторинг в таких случаях. Это просто счастье, если параметр добавляют. Обычно именно тупо дубликат делают Цитата:
Сообщение от Владимир Максимов
Т.е. я за один общий метод с параметрами.
Цитата:
Сообщение от mazzy
ну, ооок...
а вы предпочитете видеть true или false для обозначения с исключением или без? или стоит создавать специальный enum? какой стиль лучше на ваш взгляд? особенно для нескольких параметров. Т.е. у меня в данном вопросе нет предпочтений. "Как получится" Цитата:
Сообщение от mazzy
это да. в X++ да.
поэтому и вопрос - а какие другие причины могут делать тот или иной способ удобнее для читающего? Нет и не может быть вариантов, делающих что-то "удобнее" кроме привычки. Тех самых "правил". Этот вопрос многократно и по разным поводам поднимался. То, что удобно (читай "привычно") для одного будет неудобно (не привычно) для другого. Я наблюдаю странные синтаксические конструкции, когда разработчик, привыкший работать в другом языке программирования тащит свои привычки в X++. Иногда что-то получается. Только вот я долго "туплю" над таким кодом, пытаясь понять, а что вообще хотели сделать-то? Именно по той причине, что "не привычно". Цитата:
Сообщение от mazzy
Тю-тю-тю-тю... Стопэ!
у меня ничего про "сокращение написания кода" не было. если вы считаете, что было - прошу цитату.
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
01.08.2021, 23:31 | #18 |
Участник
|
В дотнете tryxxx
✔️ CONSIDER the Try-Parse Pattern for members that might throw exceptions in common scenarios to avoid performance problems related to exceptions. ✔️ DO use the prefix "Try" and Boolean return type for methods implementing this pattern. ✔️ DO provide an exception-throwing member for each member using the Try-Parse Pattern. |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
02.08.2021, 09:58 | #19 |
Участник
|
Да ну?!
т.е. runbase с эго validate и run - "это другое" Цитата:
создание методов вовсе НЕ приводит к дублированию кода. Цитата:
это НЕ проблема самого CodeStyle. Насчет параметра. Правильно говоришь - скорее всего параметров будет много. вызовов метода с параметрами будет много. т.е. вот таких конструкций будет дофига: X++: myObj.myMethod(voucher, inventLocationId, true, inventColorId, false, params); и как понять допустимо ли здесь игнрорировать результат? поэтому код будет усеян уродливыми конструкциями вида X++: if( myObj.myMethod(voucher, inventLocationId, true, inventColorId, false, params) ) { throw Error::Error } X++: myObj.myMethodOrThrow(voucher, inventLocationId, true, inventColorId, params); какая постановка? этого вопроса "Какой вариант вы бы предпочли? И почему?"? как может быть такая постановка некорректной? Цитата:
Сообщение от Владимир Максимов
Как правило, подобные методы редко продумываются на этапе создания архитектуры проекта. Они возникают "естественным путем" по мере возникновения в них необходимости. Соответственно и варианты реализации также возникают "по месту". Вот что в данном случае покажется более уместным, то и делают
но это не повод не задавать вопросы и это не повод не выполнять рефакторинг. не так ли? |
|
02.08.2021, 14:27 | #20 |
Участник
|
Да. Логика другая. Это же не методы ValidateAndRun() и ValidateAndRunNoThrow(). В терминах исходного вопроса тут уместен был бы ValidateNoThrow()
Цитата:
Цитата:
1. Рассматриваемый здесь CodeStyle - не стандарт. Собственная разработка 2. При создании методов "естественным путем" требуется рефакторинг, который, в свою очередь, требует времени и сил. Вот сильно сомневаюсь, что с этим станут заморачиваться Т.е. это все-таки проблемы той команды, которая этот самый CodeStyle будет поддерживать... Цитата:
А вот если задача оказалась не разовая, а часто повторяется, вот в этом случае уже повод задуматься о рефакторинге и каком-то более удобном способе вызова Цитата:
Цитата:
Т.е. в исходной постановке задачи в данном теме - это метод ValidateWrite() скопировать в метод ValidateWriteNoThrow(), а в самом ValidateWrite() вывести исключение, если проверка с ошибкой Не надо "копать глубже" и делать ValidateAndWriteNoThrow() - это уже явно лишнее и избыточное решение В теории. На практике возможны варианты. И вот не знаю, к счастью или к сожалению. Нет однозначного ответа
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
|
|