+38 (097) 099-97-97 JAVA ТРЕНИНГИ
JAVA ТРЕНИНГИ

Как писать вредоносный код



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

Код, который вы напишете, будет так сложен в поддержке, что у Джавистов, которые придут после вас, даже простейшее изменение займет годы оплачиваемого труда!

Более того, внимательно следуя этим правилам, вы сохраните и своё рабочее место, так как все будут бояться вашего кода и бежать от него…

…Впрочем, всему своя мера. Код не должен выглядеть сложным в поддержке — подобное напишет любой дурак. Код должен быть таковым. Иначе это заметят, и код будет переписан с нуля. Вы не можете такого допустить. Эти советы учитывают такую возможность. Да здравствует дзен.

Это вольный пересказ статьи "Как писать неподдерживаемый код"


Соглашения

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

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

Он рассматривает ваш код как бы через трубочку от туалетной бумаги. Это не даёт ему общей картины, он ищет тот небольшой фрагмент, который ему необходимо изменить. По крайней мере, он надеется, что этот фрагмент будет небольшим.

На что он попытается опереться в этом поиске — так это на соглашения, принятые в программировании, об именах переменных, названиях функций и методов…

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

…Правильно! Следуйте соглашениям «в общем», но иногда — нарушайте их. Тщательно разбросанные по коду нарушения соглашений, с одной стороны, не делают код явно плохим при первом взгляде, а с другой — имеют в точности тот же и даже лучший эффект, чем явное неследование им!




Краткость — сестра таланта!

Пишите «как короче», а не как понятнее. «Меньше букв» — уважительная причина для нарушения любых соглашений.

Ваш верный помощник — возможности языка, использованные неочевидным образом.

Обратите внимание на тернарный оператор '?', например:

i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

Разработчик, встретивший эту строку и попытавшийся понять, чему же всё-таки равно i, скорее всего, придёт к вам за разъяснениями. Смело скажите ему, что короче — это всегда лучше. Посвятите и его в пути ниндзя. Не забудьте вручить Дао дэ цзин.




Именование

Существенную часть науки о создании неподдерживаемого кода - искусство выбора имён.




Однобуквенные переменные

Называйте переменные коротко: a, b или c.

В этом случае никто не сможет найти её, используя функцию «Поиск» текстового редактора.

Более того, даже найдя — никто не сможет «расшифровать» её и догадаться, что она означает.




Не используйте i для цикла

В тех местах, где однобуквенные переменные общеприняты, например, в счетчике цикла — ни в коем случае не используйте стандартные названия i, j, k. Где угодно, только не здесь!

Остановите свой взыскательный взгляд на чём-нибудь более экзотическом. Например, x или y. Или более изощрённо, всегда вместо i используйте k (как оригинально!).

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

В этом случае заметить, что переменная — счетчик цикла, без пролистывания вверх, невозможно.




Русские слова и сокращения

Если вам приходится использовать длинные, понятные имена переменных — что поделать.. Но и здесь есть простор для творчества!

Назовите переменные «калькой» с русского языка или как-то «улучшите» английское слово.

В одном месте напишите int zakazy, в другом int zakazi, в третьем int orders, в четвёртом — int odr… Это действительно великолепно работает и очень креативно!

Количество ошибок при поддержке такого кода увеличивается во много раз.




Будьте абстрактны при выборе имени

Лучший кувшин лепят всю жизнь.

Высокая музыка неподвластна слуху.

Великий образ не имеет формы.

Лао-цзы


При выборе имени старайтесь применить максимально абстрактное слово, например, obj, data, value, item, elem и т.п.

Идеальное имя для переменной: data. Используйте это имя везде, где можно. В конце концов, каждая переменная содержит данные, не правда ли?

Но что делать, если имя data уже занято? Попробуйте value, оно не менее универсально. Ведь каждая переменная содержит значение.

Занято и это? Есть и другой вариант.

Называйте переменную по типу: obj, num, arr…

Насколько это усложнит разработку? Как ни странно, намного!

Казалось бы, название переменной содержит информацию, говорит о том, что в переменной — число, объект или массив… С другой стороны, когда непосвящённый будет разбирать этот код — он с удивлением обнаружит, что информации нет!

Ведь как раз тип легко понять, запустив отладчик и посмотрев, что внутри. Но в чём смысл этой переменной? Что за массив/объект/число в ней хранится? Без долгой медитации над кодом тут не обойтись!

Что делать, если и эти имена кончились? Просто добавьте цифру: item1, item2, elem5, data1..






Похожие имена

Только истинно внимательный программист достоин понять ваш код. Но как проверить, достоин ли читающий?

Один из способов — использовать похожие имена переменных, например, data и date. Бегло прочитать такой код почти невозможно. А уж заметить опечатку и поправить её… Ммммм… Мы здесь надолго, время попить чайку.




А.К.Р.О.Н.И.М

Используйте сокращения, чтобы сделать код короче. Например se (Sub Element), mc (Money Counter) и другие. Если вы обнаружите, что путаетесь в них сами — героически страдайте, но не переписывайте код. Вы знали, на что шли.




Хитрые синонимы

Очень трудно найти чёрную кошку в тёмной комнате, особенно когда её там нет.

Конфуций


Чтобы было не скучно — используйте похожие названия для обозначения одинаковых действий.

Например, если метод показывает что-то на экране — начните его название с display.. (скажем, displayElement), а в другом месте объявите аналогичный метод как show.. (showFrame).

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

По возможности, договоритесь с членами своей команды. Если Вася в своих классах использует display.., то Валера — обязательно render.., а Петя — paint...

…И напротив, если есть две функции с важными отличиями — используйте одно и то же слово для их описания! Например, с print... можно начать метод печати на принтере printPage, а также — метод добавления текста на страницу printText.

А теперь, пусть читающий код думает: «Куда же выводит сообщение printMessage?». Особый шик — добавить элемент неожиданности. Пусть printMessage выводит не туда, куда все, а в файл.






Словарь терминов — это фигня!

Ни в коем случае не поддавайтесь требованиям написать словарь терминов для проекта. Если же он уже есть — не следуйте ему!

Пусть читающий ваш код программист напрасно ищет различия в helloUser и welcomeVisitor и пытается понять, когда что использовать. Вы-то знаете, что на самом деле различий нет, но искать их можно о-очень долго.

Для обозначения посетителя в одном месте используйте user, а в другом visitor, в третьем — просто u. Выбирайте одно имя или другое, в зависимости от функции и настроения.

Это воплотит сразу два ключевых принципа ниндзя-дизайна — сокрытие информации и подмена понятий!




Повторно используйте имена

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

В методе старайтесь обойтись только теми переменными, которые были переданы как параметры.

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

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

Продвинутый вариант этого подхода — незаметно (!) подменить переменную на нечто похожее, например:


1 void ninjaMethod(Object elem) {
2  // 20 строк кода, работающего с elem
3
4  elem = elem.clone();
5
6 // еще 20 строк кода, работающего с elem
7 }



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

Регулярные встречи с этим приемом на практике говорят: защититься невозможно. Эффективно даже против опытного ниндзи.




Покажите вашу любовь к разработке

Пусть все видят, какими замечательными сущностями вы оперируете! Имена superElement, megaFrame и niceItem при благоприятном положении звёзд могут привести к просветлению читающего.

Действительно, с одной стороны, кое-что написано: super.., mega.., nice.. С другой — это не несёт никакой конкретики. Читающий может решить поискать в этом глубинный смысл и замедитировать на часок-другой оплаченного рабочего времени.




Перекрывайте внешние переменные

Находясь на свету, нельзя ничего увидеть в темноте.

Пребывая же в темноте, увидишь все, что находится на свету.

Гуань Инь-цзы


Почему бы не использовать одинаковые переменные внутри и снаружи метода? Это просто и не требует придумывать новых имён.


1 User user = authenticateUser();
2
3 void render() {
4   User user = ...
5   ...
6   ...
7   ... // <-- программист захочет внести исправления сюда, и..
8   ...
9 }


Зашедший в середину метода render программист, скорее всего, не заметит, что переменная user «уже не та» и использует её… Ловушка захлопнулась! Здравствуй, отладчик.






Мощные методы!

Не ограничивайте действия меода тем, что написано в его названии. Будьте шире.

Например, метод validateEmail(String email) может, кроме проверки e-mail на правильность, выводить сообщение об ошибке и просить заново ввести e-mail.

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

Объединение нескольких смежных действий в один метод защитит ваш код от повторного использования.

Представьте, что другому разработчику нужно только проверить адрес, а сообщение — не выводить. Ваш метод validateEmail(String email), который делает и то, и другое, ему не подойдёт. Работодатель будет вынужден оплатить создание нового.




Внимание.. Сюр-при-из!

Есть методы, название которых говорит о том, что они ничего не меняют. Например, isReady, checkPermission, findTags.. В трактатах это называется «отсутствие сторонних эффектов».

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

Удивление и ошеломление, которое возникнет у вашего коллеги, когда он увидит, что метод с названием на is.., check.. или find... что-то меняет — несомненно, расширит его границы разумного!

Ещё одна вариация такого подхода — возвращать нестандартное значение.

Ведь общеизвестно, что is.. и check.. обычно возвращают true/false. Продемонстрируйте оригинальное мышление. Пусть вызов checkPermission возвращает не результат true/false, а объект с результатами проверки! А что, полезно.

Те же, кто попытается написать проверку if (checkPermission(..)), будут удивлены результатом. Ответьте им: «надо читать документацию!». И перешлите эту статью.




Заключение

Все советы выше пришли из реального кода… И в том числе от разработчиков с большим опытом.

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





Олесь Крижановский
× Ваш комментарий будет опубликован после модерации Спасибо!
× Слишком много комментариев за короткий период времени Пожалуйста, попробуйте позже
контакты

Записаться на ближайший тренинг можно с помощью формы.

отправить
Курсы java Киев, Курсы по программированию на Java Киеве
Показать сообщение про успешную отправку
Спасибо за заявку!
Заполните форму и мы вам перезвоним
отправить
Заполните форму и начните учить Java правильно
Выберите курс
записаться
jon.com.ua