𝚋𝚊𝚍𝚟𝚒𝚋𝚎𝚜 𝚏𝚘𝚛𝚎𝚟𝚎𝚛
33 subscribers
410 photos
64 videos
4 files
84 links
Download Telegram
спать по часу - это прекрасно
спать по часу - не просыпаться
я не буду пить таблетки
ты не сможешь меня спасти
если вдруг больше не бодр, не счастлив
Это всё правда, только отчасти
и хочется внимания
я не вижу смысла врать
мне хорошо, хоть это опасно
и все-таки родился одиннадцатый wu-tang
ion even care if my kicks dirty af, no polish no flex, jus raw street vibe rn, look like i been runnin thru life no brakes fr
This media is not supported in your browser
VIEW IN TELEGRAM
Привет.

лестница ада или так называемая пирамида if-ов — это одна из самых распространенных проблем, с которой сталкивается почти каждый разработчик, особенно в самом начале своего пути. звучит вроде бы смешно и даже немного громко, но когда ты открываешь такой код в реальном проекте, ощущение действительно похоже на ад. перед глазами начинается длинное путешествие по вложенным условиям, каждое из которых зависит от предыдущего, и чтобы добраться до конца, приходится буквально продираться сквозь цепочку логики, которая теряется на полпути. это не только мешает понимать происходящее, но и делает поддержку почти невозможной, ведь любое изменение в верхнем условии может поломать все, что написано ниже.

для наглядности давай посмотрим на конкретный пример. возьмем fastify — это довольно известный и популярный фреймворк для node.js, который часто используют для написания серверов и api. допустим, у нас есть простой хэндлер для авторизации пользователя. если писать его без особых правил и просто вкладывать проверки одну в другую, получится нечто вроде вот этого:

fastify.post('/login', async (request, reply) => {
const { username, password } = request.body

if (username) {
if (password) {
const user = await findUser(username)
if (user) {
if (user.isActive) {
if (user.password === password) {
return { message: 'ok' }
} else {
return reply.code(401).send({ error: 'wrong password' })
}
} else {
return reply.code(403).send({ error: 'user not active' })
}
} else {
return reply.code(404).send({ error: 'user not found' })
}
} else {
return reply.code(400).send({ error: 'password required' })
}
} else {
return reply.code(400).send({ error: 'username required' })
}
})

на первый взгляд может показаться, что всё логично: мы проверяем каждое условие и аккуратно идем дальше. но если присмотреться внимательнее, становится ясно, что это не код, а настоящая «матрёшка» из if-ов. каждое новое условие уводит нас всё глубже, и в какой-то момент мозг просто перестает удерживать весь контекст. где начинается проверка имени пользователя, где заканчивается проверка активности, почему одно вложено в другое — на все эти вопросы приходится отвечать прямо во время чтения, и это утомляет.

проблема в том, что подобный код очень тяжело читать, а ещё тяжелее поддерживать. чтобы внести небольшое изменение, приходится понимать весь каскад условий. любое новое требование превращается в головную боль, ведь вставить дополнительную проверку — это значит ещё больше увеличить глубину вложенности. чем больше логики накапливается, тем страшнее выглядит хэндлер, и рано или поздно от такой структуры захочется просто сбежать.

и вот тут возникает вопрос: зачем мы сами себе создаем такие проблемы? есть же куда более простое и элегантное решение. оно называется ранние возвраты или guard clauses. принцип очень понятный: не нужно углубляться в код, если условие не выполнено. просто проверяешь сразу, и если что-то не так, возвращаешь ошибку и выходишь. не нужно держать в голове всю пирамиду, всё идет линейно сверху вниз.

давай перепишем тот же хэндлер, но уже правильно, с использованием guard clauses.

fastify.post('/login', async (request, reply) => {
const { username, password } = request.body

if (!username) {
return reply.code(400).send({ error: 'username required' })
}

if (!password) {
return reply.code(400).send({ error: 'password required' })
}

const user = await findUser(username)
if (!user) {
return reply.code(404).send({ error: 'user not found' })
}

if (!user.isActive) {
return reply.code(403).send({ error: 'user not active' })
}

if (user.password !== password) {
return reply.code(401).send({ error: 'wrong password' })
}

return { message: 'ok' }
})


взгляни, как сильно изменилось восприятие. теперь у нас нет многослойной конструкции, где каждое условие прячется под другим. логика читается сверху вниз как рассказ.
сначала проверяем одно, потом другое, потом третье. если что-то не так — сразу возвращаем ответ, не идем дальше и не добавляем лишние уровни. это и есть сила guard clauses.

и здесь важно заметить, что такое упрощение кода — это не про «сделать красиво ради красоты». это про уважение к читаемости, к поддержке и вообще к жизни проекта. подумай сам: сегодня написал страшный кусок кода и забыл о нем, а завтра откроешь его снова и будешь сам себя проклинать, потому что уже не помнишь, зачем так делал. а если код написан линейно и чисто, то он будет понятен и через месяц, и через год, и даже другим разработчикам, которые будут работать над проектом после тебя.

еще один момент, который стоит учитывать, когда речь идет о fastify: этот фреймворк позволяет подключать схемы валидации прямо к маршрутам. это значит, что часть проверок можно вынести из кода вообще, и они будут выполняться автоматически. например, можно сразу задать, что в запросе обязательно должны быть поля username и password. тогда проверять их наличие в хэндлере не придется. это дополнительный уровень защиты от «лестницы ада», потому что меньше условий — значит меньше поводов углубляться в ненужные проверки.

и в конце хочу сказать главное: лестница ада — это не шутка и не редкость, это реально частая ошибка, которую допускают почти все. но если вовремя заметить проблему и начать переписывать код с guard clauses и линейной логикой, можно избежать огромного количества боли в будущем. чистый код — это не модный термин из книжек, это основа нормальной разработки. чем аккуратнее ты пишешь, тем дольше живет твой проект, и тем проще тебе самому и твоей команде его поддерживать.
вспоминаю каким был я года 3 назад