Продолжение вот этой темы. За прошедшие месяцы регулярно сталкивался с этим паттерном в разных кодовых базах, написанных разными разработчиками. Такое ощущение, что выросло новое поколение программистов, смотрящих на код совсем по-другому.
Вроде бы понял, в чем смысл. С обычными return-ами часто пишут так:
int some_func(some_arg & arg) { if(!is_valid(arg)) return -1; if(!approriate_state(arg)) return -1; if(!some_another_condition(arg)) return -1; ... // Ну а здесь уже какие-то действия. } |
Похоже, этот подход пытаются переложить на тело цикла, только вместо преждевременных return-ов используют continue:
for(auto & item : collection) { if(!is_valid(item)) continue; if(!appropriate_state(arg)) continue; if(!some_another_condition(arg)) continue; ... // Ну а здесь уже какие-то действия. } |
Понять-то я понял, а вот принять не получается 🙁
Во-первых, дело в том, что в реальном коде все это выглядит не так опрятно и понятно, как в моих псевдопримерах. Между if-ами, зачастую, еще какие-то действия выполняются, а сами if-ы могут быть и вложенными, и кроме continue еще встречаются и break, и даже return...
В общем, когда пытаешься вчитаться в незнакомый код вот с такими вот continue, то приходится в голове таблицу переходов вручную выстраивать. Невольно вспоминаются времена программирования на Basic-е с нумерацией строк и ассемблере 😁
Во-вторых, недавно довелось несколько циклов преобразовать в лямбды, которые передаются во что-то типа `std::ranges::for_each`, т.е. было:
for(const auto & item : detect_collection_for_processing()) { ... // Тут обработка с continue/break-ами. } |
а стало:
for_all_ready_to_processing_items(token, [&](const auto & item) { ... // Тут обработка, но уже без continue/break. }); |
Так вот, оказалось, что тела тех циклов, которые были написаны по-человечески, без continue и break, трансформируются в лямбды легко и непринужденно. Ну вот вообще не припомню, чтобы нужно было делать что-то кроме замены for-а на вызов функции с лямбдой.
Тогда как тела циклов с continue -- это вот прям минное поле 😔
Хорошо хоть, что компилятор бьет по рукам когда видит continue вне цикла. Несколько раз это меня выручало, т.к. в сложных if-ах я continue просто не замечал.
Посему в очередной раз приходится делать вывод о том, что куски кода, оформленные в виде "одна точка входа, одна точка выхода", оказываются наиболее простыми и в изучении, и в сопровождении. Деды, которые учили меня структурному программированию 35 лет назад, были таки правы.
Не хочу создать впечатление, что в моем коде только правило "единственного return-а" и ничего больше.
Это далеко не так.
И break-и использую, и несколько return-ов из функций. В том числе, бывает, сочетаю в теле цикла и break, и return.
Но стараюсь, чтобы таких вещей было по минимуму. Ибо недостаточно умен, чтобы писать и поддерживать сложный код. Так что тут, как говорится, не было счастья (т.е. ума), да несчастье (т.е. низкий IQ) помогло.
А вот continue в моем коде, действительно, найти тяжело. Практически не использую. Чего и вам желаю 😎
Комментариев нет:
Отправить комментарий