JavaRush/Java блог/Random/Избегаем лишней вложенности в циклах
ZloyLis
58 уровень

Избегаем лишней вложенности в циклах

Статья из группы Random
участников
Делая первые шаги в изучении программирования, многие новички сталкиваются с ветвлением и начинают писать длинные вложенные циклы. К примеру, возьмем ситуацию, когда нам нужно дать пользователю доступ к кошельку (isAccess()). Мы вводим следующие две проверки: 1) Пользователь залогинен 2) Пользователь идентифицирован За проверки у нас отвечает результат методов isLogin() и isIdentify(). Они возвращают логические true или false. РАЗРАБОТЧИК И МАКАРОННАЯ ФАБРИКА Да, ничего сложного в задаче нет. Пишем проверки, если прошла первая проверка (isLogin()) - движемся ко второй(isIdentify()). Если все проверки прошли успешно - даем доступ к кошельку(isAccess()). Вот как обычно это выглядит у новичков: Избегаем лишней вложенности в циклах. - 1 Мы получили вложенные проверки. Сейчас у нас всего две проверки, а если их четыре, пять или более? У кода с такой архитектурой есть жирный минус - его неудобно читать, в нём бывает сложно разобраться. БУДЬ ПРОЩЕ Перед нами стоит задача написать код проще и понятнее. Как это сделать? Да как два байта переслать 😉. Необходимо избавиться от вложенных проверок, заменив их проверками с противоположными условиями. В Java для этого есть специальный логический оператор НЕ (!)(логическое отрицание). Он меняет логическое значение операнда с истины на ложь и наоборот. Смысл наших действий в том, чтобы прописать не условия, когда нужно что-то делать, а условия, когда чего-то ДЕЛАТЬ НЕ НУЖНО и стоит завершить программу. Т.е., мы пишем своеобразный фейсконтроль, если входные данные условиями не вышли - мы сразу же завершаем программу. Обычно это делается следующим образом: 1) В условии проверки меняют значение на противоположное с помощью логического оператора (!). 2) Если это условие выполняется (т.е. мы получили неподходящие входные данные), то программа сразу же останавливается. 3) Все ранее вложенные друг в друга условия делают невложенными и размещают друг под другом. Перепишем наш код: Избегаем лишней вложенности в циклах. - 2 Теперь наша логика работает следующим образом: 1) Пользователь не залогинен? Выходим из функции. 2) Пользователь не идентифицирован? Выходим из функции. 3) Даем достум тем, кто не вышел на всех предыдущих этапах. Таким образом мы получаем: 1) Код стало легче читать. 2) В код можно легко внести новые проверки или убрать ненужные. Как видим, немного изменив код, мы сделали его более понятным и чистым. А значит, стали еще ближе к качественному коду. Но, на всякий случай помним: "Хорошо задокументированный баг, автоматически становится фичей!" Спасибо за внимание!
Комментарии (4)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Денис Enterprise Java Developer
13 марта, 15:23
А при чем тут циклы если не секрет?) Ну и по кодстайлу пара замечаний, названия методов очень плохо говорят о том что они делают. Например wallet.isAccess() это что? префикс is обычно ставится перед булевыми методами или полями, например
if (session.isAlive()) { /*doSomething*/ }
Но общая идея вполне здравая. Хотя в данном конкретном примере можно было бы обойтись обычным &&
if (user.isLogin() && user.isIdentify())
А можно было бы на уровне юзера сделать отдельный метод для этих целей:
if (user.isAuthorized()) {}
В общем подходов хватает на самом деле. Главное чтобы код сохранял читаемость и модифицируемость.
ZloyLis
Уровень 58
13 марта, 22:59
Да, именование "циклы" здесь не удачное. Условия, вложенные условия - так было бы правильнее. По именованию методов:
За проверки у нас отвечает результат методов isLogin() и isIdentify(). Они возвращают логические true или false
Они и есть булевые. Сам код взят просто как упрощенный пример. Он ни в коем случае не претендует на роль реального кода - эдакий псевдокод. Про
в данном конкретном примере можно было бы обойтись обычным &&
вы не совсем правы. В данном конкретном случае, нужно было показать, КАК РАЗНЕСТИ проверки и сделать их более независимыми друг от друга, менее завязанными друг на друга и избежать лишней вложенности. И исходя из этого, делаем вывод, что Ваш подход не очень корректен, т.к. сообщения об ошибках идут разные. В вашем случае придется внутри писать проверку какой текст ошибки выводить и мы снова вернемся к if/else или к вложенным if-ам, что опять же сделает код более сложным. P.S. понятно, что мой пример притянут за уши, но уж как есть. Даже из такого примера можно сделать определенные выводы.
Денис Enterprise Java Developer
14 марта, 07:45
Ну так я про логин и идентифай ничего не писал :) Хотя они тоже названы не вполне внятно, особенно второй, мне кажется это из-за того, что терминология выбрана не очень удачная, здесь куда нагляднее было бы использовать аутентификацию и авторизацию. Первое это фактически то что ты называешь логином, а второе - проверка прав на доступ к ресурсу. Мой вопрос был про кошелёк :) почему предоставление доступа к кошельку тоже выглядит как булев метод? :) А что до сообщений об ошибке достаточно было бы вернуть что у этого конкретного чувака прав на доступ в эту область нет, не важно, не залогинился он или прав действительно нет, но в обоих случаях делать ему в этой секции нечего. Если говорить о безопасности то предоставлять слишком много информации не стоит ) А то может выйти как в той шутке, "Вы не можете использовать этот пароль, он уже используется пользователем Вася777". В прочем, здесь я не претендую на истину в последней инстанции, я просто ленивый :)
ZloyLis
Уровень 58
14 марта, 08:16
Это просто псевдокод, чтобы показать, как делать код более читаемым, избегая лишней вложенности. Так то авторизация и безопасность вообще иначе пишутся и с помощью другого инструментария :) А насчет доступа к кошельку - ну что ж, я просто в названии хотел показать, что делает метод к которому мы пытаемся дойти - дает доступ или не дает доступ.