С некоторым обучением!

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

Другими словами, мы все видели ужасный код, и в то время он, вероятно, был плохим, потому что вам приходилось либо поддерживать его, либо как-то с ним взаимодействовать.

Но не сегодня, сэр! Сегодня мы будем смеяться ... То есть учиться на ошибках прошлого. Вроде, как бы, что-то вроде.

Итак, я вошел в r / badcode и, поплавав какое-то время, мне удалось получить 7 драгоценных камней, которыми я собираюсь поделиться с вами сегодня.

Итак, приступим!

Старый добрый пустой IF

Взгляните на нашу первую красавицу:

Когда начать? Ну, обо всем по порядку, я думаю, мы должны похвалить использование оператора строго равенства, чтобы проверить, действительно ли значение name было null или нет.

При этом поздравления на этом заканчиваются, потому что, как только вы видите всю логику, возникает несколько проблем с кодом:

  1. Первым на меня бросился пустой блок IF. И он набросился на меня, потому что я видел это сотни раз. Ненавижу сталкиваться с этим, неужели так сложно поместить прямо противоположное выражение внутри IF и избавиться от пустого блока? И хотя в этом случае нет, но если логическое выражение было настолько сложным, что получить обратное было немного головной болью, вы всегда можете заключить его в круглые скобки и поставить перед ним префикс !, и все готово.
  2. Блок IF следит за тем, чтобы мы не пытались приветствовать кого-то, кто на самом деле не называет нам своего имени (по крайней мере, на вид). Эта проблема? Что условие, учитывая то, как оно конкретно сравнивается с null, будет пропускать undefined и пустую строку, фактически оно также пропускает строку, состоящую из пробелов. Если бы условие было if(!name), мы могли бы обнаружить больше ложных значений, таких как пустая строка или undefined.
  3. Наконец, мы не можем игнорировать уязвимость системы безопасности, указанную в последней строке. С сайта MDN:

Установка значения innerHTML удаляет всех потомков элемента и заменяет их узлами, созданными путем анализа HTML, указанного в строке htmlString.

Это мое выделение, и оно призвано показать вам, в чем заключается проблема. Все, что мы помещаем в innerHTML, будет проанализировано . Итак, мы открываем дверь для XSS-атаки, при которой наш злоумышленник может назвать себя чем-то вредоносным, например: <img src="../fake.image.path" onerror="{inser your evil javascript here}" />Fernando, и этот код будет запускать некоторый JavasScript каждый раз, когда мое имя появляется в любом месте экрана.

Почему? Потому что этот код не очищает ввод пользователя. Помните детей, никогда не доверяйте пользователю, каждый раз, когда вы используете его ввод, сначала очищайте его, проверяйте наличие тегов HTML и следуйте рекомендациям OWASP.

Доведение читаемого кода до крайности

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

В нашем следующем потрясающем примере кода превращение однострочного кода в читаемый код слишком далеко:

Да, работает. И магические числа - это большой запрет для написания кода, но в данном случае эти числа не были ТАКОЙ магией, если честно. Учитывая, что он имел дело с методом Date.now(), было довольно очевидно, что код вычитал время из текущего времени. Таким образом, это был вопрос объяснения того, что он должен был делать, это можно было решить, добавив хороший комментарий вверху, объясняющий именно это.

Вместо этого решение превратило трудночитаемую строку кода в блок кода, который не читается слишком долго. Что, кстати, идет немного дальше исходной строки, позволяя даже выразить, сколько дней вы хотите вычесть, используя переменную daysToGoBack (что не было напрямую доступно при первом вычислении).

Помните, что дети с читаемым кодом не так поступают.

Как бы вы назвали это?

Мне просто было довольно сложно дать имя этому:

Судя по источнику, похоже, что задание по информатике пошло не так. Название этой функции Python подразумевает, что она пытается вычислить частоту каждой буквы внутри переменной encripted_message. Но, боже мой, это не путь.

Можете ли вы представить себе лицо этого ученика, когда он поймет, что в сообщении есть заглавные буквы? Что, если он также охватывает числа? И, черт возьми, не заставляйте меня принимать несколько кодировок.

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

Так много проблем всего в нескольких строках

Следующий приходит к нам от человека, который на самом деле не знает, как массивы и асинхронность работают в JavaScript. Либо тот, либо этот человек пытался быть очень осторожным… что-то пошло не так? Я больше не знаю ...

Четыре строки кода - это все, что нужно, чтобы сделать 2 (или 3, в зависимости от того, как вы на это смотрите) ошибки. Это должен быть рекорд.

Давайте распакуем эту красоту:

  1. Давайте избавимся от очевидных вещей: здесь нет асинхронного кода. Так зачем использовать await и async? Лучше меня, если только этот человек не надеялся добавить дополнительные асинхронные вызовы внутри map, это не имеет смысла.
  2. Зачем определять пустой массив, который вы заполняете результатом map, чтобы сразу же начать вручную добавлять по одному элементу с помощью метода push?
  3. И в этом случае зачем использовать map для перебора элементов вашего массива? Не в этом суть метода, вы получили forEach за это.

То есть, это можно было записать как let ids = ut_ids.map(ut => ut.UserTestID). Хороший однострочный текст, который на самом деле понятен.

Помните, время от времени освежайте свои методы массива, они всегда полезны и не добавляйте async/await, если вам действительно не нужно иметь дело с асинхронным поведением. Имейте в виду, что последний бит не вредит коду, он просто режет глаза, но, тем не менее, в этом нет никакого смысла, поэтому его не должно быть.

Когда все важно, то на самом деле ничего не стоит.

Мы привыкли это слышать в отношении приоритетов, которые ставят наши менеджеры, верно? Иногда они все хотят, чтобы все было как можно скорее, потому что все имеет приоритет 1.

Но в данном случае мы переносим это страдание в браузер, проверьте:

Верно, Chrome, теперь ты чувствуешь то же, что и я!

Вероятно, именно эта мысль приходила в голову разработчику, когда писал этот прекрасный образец CSS-арта.

Либо это, либо, как многие, вероятно, могут предположить, это также может быть сгенерированный код, основным ключом к разгадке которого является имя класса CSS. По сути, принуждение каждого из этих параметров быть !important гарантирует, что пользователь не сможет случайно их перезаписать.

И хотя это может быть чрезмерным использованием !important, я уверен, что вы уже были в этом раньше. Как в основном back-end разработчик, я могу иметь дело с правилами специфичности CSS, пока я их изучал и говорил «ебать это дерьмо, я сделаю это !important здесь и здесь, там, это работает сейчас ».

Я могу относиться. Однако, если вы работаете с CSS каждый день и полагаетесь на этот трюк для достижения цели, вы можете прочитать эту статью и узнать о правилах специфичности и о том, как избежать столь частого использования !important.

Повторный код? Я не вижу повторяющегося кода

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

Судя по всему, этот разработчик создавал классический калькулятор. Я помню, как когда-то делал свои на C, но это почти то же самое. Вы вводите два числа и операцию, затем просто выполняете расчет и показываете результат. После того, как он заработал для одного, его легко распространить на другие, и в данном случае это было настолько тривиально, что этот разработчик просто продублировал все это.

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

А теперь давайте разберемся с этим немного дальше:

  • Этот человек использует одни и те же переменные для num1 и num2, которые являются глобальными, кстати, это уже ужасная практика.
  • Внутри каждого блока case они определяют 2 новые переменные, и, поскольку они используют let, им нужно использовать разные имена, поскольку их область действия - это весь оператор switch, поэтому в противном случае возникнет конфликт имен.

Вместо этого они могли бы определить 2 переменные внутри calculate функции с let, но на уровне функции, и использовать их внутри каждого case блока. Фактически, все остальное, что повторяется внутри каждого case, может быть извлечено либо до switch, либо после (после выполнения операции). Оставляем фактическую switch на обработку только решения о том, какую функцию вызывать.

Кроме того, поскольку все операции принимают 2 аргумента, переключатель можно было бы переписать следующим образом:

Это возможно, потому что в JS мы можем назначать ссылки на функции переменным, а затем просто вызывать их динамически. Это очень удобно.

Наконец, я морально обязан сказать, что весь оператор switch является излишним для этого сценария, гораздо более чистое решение использовало бы такой литерал объекта:

Конечно, вы также захотите проверить, действительна ли операция, прежде чем вызывать ее, но я оставлю это вам в качестве упражнения :).

И, наконец, помните, дети: не используйте глобальные переменные, а наркотики не применяйте.

Вот почему я ненавижу JAVA

Конечно, этот последний может быть немного предвзятым из-за моих личных предпочтений, но все же вы не можете сказать мне, что это «ОК код»:

Честно говоря, как может одна строка кода, и в то же время такая простая, быть такой ужасной. Я просто, почему ты, правда !?

И хотя вы могли бы сказать «ну, Фернандо, я не знаю, в чем проблема, я прекрасно могу это прочитать». Необходимость в таком синтаксисе - это то, что затем может сгенерировать что-то вроде этого:

Я просто не могу понять, как языку нужно просить вас определить тип переменной, чтобы позже использовать ТОЧНО то же имя для ее создания. Действительно:

TYPE myVarName = new TYPE()

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

Но если вы можете этого избежать, используйте что-нибудь другое.

Это ИТ на сегодняшний день, нет глубокого понимания того, что означает кодирование, или большого урока, который можно извлечь из этого. Я просто хотел, чтобы вы увидели, что чтение плохого кода тоже может быть забавным при правильном контексте :)

Приятного вам жуткого октября!