Это текст, который сдвигает вашу программистскую парадигму и существенно повышает качество кода.
Задача
Представьте ситуацию: вы пишете админку для панели управления сервером. Вам нужно показать эту панель, если пройдены три проверки. Если какие-то из них не пройдены, нужно вывести ошибку.
Проверки такие:
- Подключён к Wi-Fi-сети.
- Вошёл в систему со своими логином и паролем.
- Есть админские права доступа.
За эти условия отвечают 3 логических переменных — wifi, login и admin. Проверка должна идти именно в этом порядке. Если одна из проверок не прошла, следующую можно не проводить.
Решение в лоб
Кажется, что написать код для этих проверок просто, и это на самом деле так: проверяем первое, если прошло — проверяем второе, если прошло — третье. Если всё прошло, то выводим панель управления. Если что-то не проверилось, сообщаем. Вот эти три проверки, вложенные друг в друга:
function access() {
// если подключён к Wi-Fi
if (wifi) {
// если вошёл в систему
if (login) {
// если пользователь — администратор
if (admin) {
// то показываем панель администратора
show_admin_panel();
}
// иначе выводим сообщение о доступе только для администраторов
else {
console.log('Доступ только для администраторов');
}
}
// иначе выводим сообщение про логин и пароль
else {
console.log('Для доступа нужно ввести логин и пароль');
}
}
// иначе выводим сообщение про подключение к Wi-Fi
else {
console.log('Доступ возможен только при подключённом Wi-Fi');
}
}
Упрощаем код
У кода со вложенными проверками есть минус: его неудобно читать и сложно сразу разобраться, что за что отвечает и где заканчивается каждая проверка.
Наша задача — сделать код понятнее, чтобы его было легко читать сейчас и поддерживать в будущем. Главное неудобство во вложенных проверках: трудно глазами следить, что за чем проверяется и что во что вложено.
Решение — избавиться от вложенных условий, заменив их условиями с противоположным значением, а именно:
❌ было if(wifi) — «если в переменной wifi значение true»;
✅ стало if(!wifi) — «если в переменной wifi не значение true, то есть false».
В английском языке это называется guard clauses. Устоявшегося перевода на русский пока нет, поэтому для простоты мы назовём это «охранные условия».
Смысл такого подхода в том, чтобы в коде прописывать не условия, когда нужно что-то делать; а условия, когда нужно чего-то не делать и выйти из программы, — это и есть те самые охранные условия. Если охранные условия не выполняются, значит, охрана не нужна и можно выполнять то, ради чего программу вызывали.
Для этого обычно делают так:
- В каждом условии меняют значение условия на противоположное.
- Если оно выполняется (то есть функция встретила неподходящее для неё значение), то всё сразу останавливается и функция дальше не идёт.
- Все вложенные условия делают обычными, невложенными, и просто размещают их друг под другом.
Покажем, как это работает, сначала на примере проверки подключения к Wi-Fi:
function access() {
// если НЕ подключён к Wi-Fi
if (!wifi) {
// выводим сообщение
console.log('Доступ возможен только при подключённом Wi-Fi');
// выходим из функции
return;
}
}
Теперь из кода видно, что если пользователь не подключён к Wi-Fi, то он получит сообщение об этом, а потом функция остановится. Это первый уровень защиты, когда мы проверяем первое условие для показа панели администратора.
Теперь это упражнение можно повторить для двух других условий. Логика будет такой:
- Я не подключён к Wi-Fi? Если не подключён, то выходим из функции.
- Я не вошёл в систему? Если не вошёл, то выходим из функции.
- У меня нет админских прав? Если прав нет, то выходим из функции.
- Показать админскую панель тем, кто не вышел из программы на всех предыдущих этапах.
function access() {
if (!wifi) {
console.log('Доступ возможен только при подключённом Wi-Fi');
return;
}
if (!login) {
console.log('Для доступа нужно ввести логин и пароль');
return;
}
if (!admin) {
console.log('Доступ только для администраторов');
return;
}
// если к этому моменту функция ещё работает, то показываем панель администратора
show_admin_panel();
}
Что дальше
Этот приём — один из многих, чтобы сделать код более чистым и понятным. В следующих статьях разберём постепенно и все остальные.