Чаще всего, когда возникает вопрос о том как улучшить навыки разработки, стандартный ответ: почитать про чистый код, выучить новые языки программирования, посмотреть проекты где реализованы лучшие практики и т.д. Но есть другой способ - пойти от обратного, и попробовать написать код максимально ужасно. Написав по-настоящему плохой код можно в конце концов понять, как писать хороший. Можно небрежно и на скорую руку сделать работу кое-как, но этого будет недостаточно. При условии, что уже есть представление о том, как писать хорошо, очень сложно сознательно писать плохо.
Другого человека можно легко запутать, ведь он не знает ход ваших мыслей. Гораздо сложнее обыграть самого себя, чтобы уже через несколько дней было невозможно разобраться в том, что реально происходит и откуда все эти баги. В этой игре вы и есть ваш самый главный противник. Поэтому попробовать такой челлендж будет интересно как новичкам, так и опытным разработчикам, ведь у опытных разработчиков могут быть все более комплексные ухищрения.
Disclaimer: Ни в коем случае не пробовать на рабочих проектах. Автор статьи не несет никакой ответственности за любой причиненный ущерб.
Усыпить бдительность
Надо стараться писать код, который будет усыплять бдительность. Кроме всего прочего, плохой код плох тем, что сходу понять, что он написан ужасно не так уж и просто. Если бы это было очевидно, в нормальной команде его бы не пропустили на код ревью или впоследствии сразу же переписали. Такие примитивные способы, как наименование переменных одной буквой или аббревиатурами не подходят. Они сразу вызывают подозрение, что тут что-то не так. А хорошие наименования, обозначающие немного другое - это уже интересней. Например, для обозначения переменной, которая показывает, является ли число четным использовать вместо isEven просто even. Можно давать максимально абстрактные названия, это тоже добавит сложности при последующем чтении кода.
Еще один очень хороший способ усыпить бдительность - покрыть код тестами, но не полностью. Мы по умолчанию склонны думать, что если код покрыт тестами, то там вероятность ошибки меньше, поэтому стоит использовать эту слабость. Можно оставить какие то экстремальные варианты кода не покрытыми тестами в надежде на то что рано или поздно это выстрелит.
Научиться провоцировать ошибки в runtime
Если код пишется на языке без статической типизации, то тут все достаточно просто. Но в случае, когда есть проверка на типы, линтер и статический анализ кода вызов ошибки при исполнении может потребовать каких то знаний. Стоит поискать способы вызвать ошибки в runtime, в любом языке их достаточно. Для примера используя TS можно ошибку в runtime вызвать так:
type Person = { id: string };
const person: Person = { id: 'obc23z' };
const credential: { id: number | string } = person;
credential.id = 1;
// TypeError: person.id.toUpperCase is not a function
const personId = person.id.toUpperCase();
Забыть про оптимизацию
Увидев цикл в цикле который работает в цикле у любого возникнут вопросы. Но это можно обойти, если использовать вместо циклов рекурсию. Прелесть рекурсии в том, что даже те, кто хорошо знают динамическое программирование не всегда сходу могут посчитать алгоритмическую сложность выполняемой задачи. Вспомните пример с вычислением числа Фибоначчи - если решать ее в лоб можно на несколько столетий пойти пить кофе.
Из более очевидного, на бэке можно все сортировки, фильтры выполнять in memory. Забыть установить индексы в БД либо напротив, поставить индексы на все поля.
Вызывать утечку памяти
Это очень полезный навык, потому что на тестовых данных приложение, вероятно, будет работать, но через некоторое время у пользователя все начинает тормозить. Утечкой памяти называют ситуацию, когда объект, который должен был быть удален после того, как стал не нужен не удаляется и не освобождает память операционной системе. В JS/TS вызвать утечку памяти очень легко - можно выполнять какое то действие в setInterval и при этом забыть условия останова циклически выполняемой функции. Можно создавать eventListener-ы, которые будут прослушивать события все время, пока работает приложение. Использовать замыкания, чтобы создать циклическую зависимость и т.д.
Возможно, сейчас сложится иллюзия, что проблема в самом JS, в несовершенстве языка и платформы, но это не так. Полагаю, во всех языках можно вызвать утечку памяти без особых усилий. В C# достаточно переменные объявить статическими, излишне кэшировать данные при обращении к неуправляемым ресурсам, “забыть” использовать using, и приложение начнет тормозить или даже через некоторое время перестанет работать.
Использовать сложные паттерны
Книга “Приемы объектно-ориентированного проектирования. Паттерны проектирования” для многих стала откровением. Почти каждый кто прочитал книгу, пробовал везде, где нужно и не нужно применять новые паттерны. Можно использовать сложные уже существующие паттерны, и даже попробовать придумать свои.
Оставить дыры в безопасности
Современные фреймворки и библиотеки уже имеют достаточно хорошую защиту. Если какая то функция небезопасна разработчики пытаются нас об этом предупредить. Например, если используется react, можно использовать dangerouslySetInnerHTML. Но нам прямым текстом говорят, что этот метод не безопасен, поэтому его использование вызовет подозрение. Но если применить библиотеку, которая под капотом использует такую конструкцию, никаких вопросов не возникнет. Мало кто смотрит на исходный код используемых библиотек. Если проект написан достаточно давно и, возможно, даже заброшен, у него может быть масса звезд в гитхабе и при этом присутствовать множество известных на сегодня уязвимостей.
Использовать технологии не по назначению
Самый банальный пример: попробовать использовать не реляционные базы данных как реляционные. Например MongoDB вместо PostgreSQL для хранения табличных данных. И по этой таблице реализовать пагинацию, сортировку, фильтры. При малом количестве записей все будет работать замечательно. Но при количестве записей около 100 тысяч приложение уже будет сильно тормозить. А если попробовать перейти на последнюю страницу mongodb выдаст ошибку out of memory.
Итог:
Способов написать ужасный код много, гораздо больше чем способов написать хороший код: можно вызвать состояние гонки, использовать нюансы языка, которые мало кто знает и помнит, реализовывать антипаттерны. Каждый может сходу придумать что-то свое. В данной статье приведены лишь самые простые способы писать плохой код.
Основной навык, который приобретается путем сознательного написания плохого кода - это внимательность к своим и чужим ошибкам. В процессе этого, возможно, расширится багаж знаний и глубина понимания используемых технологий. Знание того, как именно можно сделать глупые или хитроумные ошибки будет полезным для любого программиста. И, кроме всего прочего, это будет интересным упражнением для мозга.
Комментарии (5)
Racheengel
22.07.2022 01:05+1Вот хуже, когда приходишь на фирму, а там код именно как в этой статье написан, по всем канонам. Да ещё и главные писатели уволились, а продукт расширять надо. А переписать заново "долго и некому, ну может в новом году" (с) шеф.
no404error
22.07.2022 02:59-2Можно гордиться "плохим кодом", потому, что он "хороший код" для конкретных реализаций.
Абсурд? Но вы же сами написали:
Самый банальный пример: попробовать использовать не реляционные базы данных как реляционные. Например MongoDB вместо PostgreSQL для хранения табличных данных.
Использовать "что-то" вместо "чего-то", как пример и с утверждением:
И по этой таблице реализовать пагинацию, сортировку, фильтры. При малом количестве записей все будет работать замечательно.
А вам не пришло в голову, что некоторые "методы" работают быстрее если они, с точки зрения логики и даже рекомендаций, неоптимальны?
Типичный пример это TMTPascal, где такого - вагон. Он быстрый, он удобный и, что самое главное, актуальный. Структуры вроде IF/FOR там работают медленнее чем простые переходы при определенном порядке значений. Профит до офигенных значений. Код в итоге превращается в полное говно, но работает и главное - работает очень быстро.
kai3341
24.07.2022 16:55В мире и так слишком много говнокода. Не надо его плодить, особенно осознанно
JordanCpp
При написании хорошего кода, говнят по края. Что же можно придумать, если намеренно юзать советы из статьи? Статья полезна, как не надо делать.
Sandreykin Автор
Спасибо, согласен, примерно так это и задумывалось. Часто бывает так, что в принципе нет понимания как можно написать плохой код кроме как действительно сделать это безалаберно. Но если поставить себе целью специально написать что-то плохо можно много чего нового узнать. И это полезно.