Обучение без размышлений — это напрасный труд; мысль без обучения опасна.
Программисты-ниндзя прошлого использовали эти приемы, чтобы обострить ум сопровождающих код.
Гуру проверки кода ищут их в тестовых задачах.
Начинающие разработчики иногда используют их даже лучше, чем программисты-ниндзя.
Прочтите их внимательно и узнайте, кто вы — ниндзя, новичок, а может, код-ревьюер?
Обнаружена ирония
Многие пытаются идти по пути ниндзя. Немногим это удается.
Сделайте код максимально коротким. Покажи, какой ты умный.
Пусть тонкие особенности языка помогут вам.
Например, взгляните на этот тернарный оператор '?'
:
// взято из известной библиотеки JavaScript я = я? я <0? Math.max(0, len + i) : i : 0;
Круто, правда? Если вы так напишете, разработчик, который встретит эту строку и попытается понять, каково значение i
будет весело проводить время. Тогда придём к тебе в поисках ответа.
Скажите им, что короче всегда лучше. Посвятите их на путь ниндзя.
Дао скрывается в бессловесии. Только Дао хорошо начато и хорошо завершено.
Другой способ сократить код — повсюду использовать однобуквенные имена переменных. Например, a
, b
или c
.
Короткая переменная исчезает в коде, как настоящий ниндзя в лесу. Никто не сможет найти его с помощью «поиска» редактора. И даже если кто-то это сделает, он не сможет «расшифровать», что означает имя a
или b
.
…Но есть исключение. Настоящий ниндзя никогда не будет использовать i
в качестве счетчика в цикле "for"
. Где угодно, но не здесь. Посмотрите вокруг, там еще много экзотических букв. Например, x
или y
.
Экзотическая переменная в виде счетчика цикла особенно хороша, если тело цикла занимает 1-2 страницы (увеличьте его, если можете). Тогда, если кто-то заглянет глубоко внутрь цикла, он не сможет быстро выяснить, что переменная с именем x
является счетчиком цикла.
Если правилами команды запрещено использование однобуквенных и расплывчатых названий – сокращайте их, делайте аббревиатуры.
Так:
list
→ lst
.
userAgent
→ ua
.
browser
→ brsr
.
…и т. д
Только тот, у кого действительно хорошая интуиция, сможет понять такие имена. Постарайтесь все сократить. Только достойный человек должен иметь возможность поддерживать разработку вашего кода.
Большая площадь без углов
Огромное судно готово в последний раз,
Великая нота – разреженный звук,
Великий образ не имеет формы.
Выбирая имя, старайтесь использовать максимально абстрактное слово. Например, obj
, data
, value
, item
, elem
и так далее.
Идеальное имя для переменной — data
. Используйте его везде, где только можете. Действительно, каждая переменная содержит данные , верно?
…Но что делать, если data
уже заняты? Попробуйте value
, оно тоже универсально. В конце концов, переменная в конечном итоге получает значение .
Назовите переменную по ее типу: str
, num
…
Дайте им попробовать. Юный посвященный может задаться вопросом – действительно ли такие имена полезны ниндзя? Действительно, они есть!
Конечно, имя переменной все еще что-то значит. Он говорит, что находится внутри переменной: строка, число или что-то еще. Но когда посторонний попытается понять код, он удивится, увидев, что на самом деле никакой информации нет! И в конечном итоге не сможет изменить ваш хорошо продуманный код.
Тип значения легко узнать при отладке. Но в чем смысл переменной? Какую строку/число он хранит?
Без хорошей медитации разобраться просто невозможно!
…А что, если таких имен больше нет? Просто добавьте число: data1, item2, elem5
…
Только по-настоящему внимательный программист сможет понять ваш код. Но как это проверить?
Один из способов — использовать похожие имена переменных, например date
и data
.
Смешайте их, где сможете.
Быстрое чтение такого кода становится невозможным. А когда опечатка... Эммм... Застряли надолго, пора пить чай.
Дао, о котором можно рассказать, — это не вечное Дао. Имя, которое можно назвать, не является вечным именем.
Использование похожих названий для одних и тех же вещей делает жизнь более интересной и демонстрирует публике ваш творческий потенциал.
Например, рассмотрим префиксы функций. Если функция отображает сообщение на экране – начните ее с display…
, например displayMessage
. А затем, если другая функция отображает на экране что-то еще, например имя пользователя, начните ее с show…
(например, showName
).
Намекните, что между такими функциями есть тонкая разница, хотя ее нет.
Заключите договор с товарищами-ниндзя по команде: если Джон начнет «показывать» функции с display...
в своем коде, то Питер сможет использовать render..
, а Энн — paint...
. Обратите внимание, насколько интереснее и разнообразнее стал код.
…А теперь хет-трик!
Для двух функций с важными различиями используйте один и тот же префикс!
Например, функция printPage(page)
будет использовать принтер. А функция printText(text)
выведет текст на экран. Пусть незнакомый читатель хорошенько подумает над одноименной функцией printMessage
: «Куда она помещает сообщение? На принтере или на экране?». Чтобы сделать его по-настоящему блестящим, printMessage(message)
должен вывести его в новом окне!
Когда целое разделено, части
нужны имена.
Имен уже достаточно.
Надо знать меру.
Добавляйте новую переменную только в случае крайней необходимости.
Вместо этого повторно используйте существующие имена. Просто напишите в них новые значения.
В функции старайтесь использовать только переменные, передаваемые в качестве параметров.
Из-за этого будет очень сложно определить, что именно сейчас находится в переменной. А также откуда оно взялось. Цель – развитие интуиции и памяти человека, читающего код. Человеку со слабой интуицией пришлось бы анализировать код построчно и отслеживать изменения в каждой ветке кода.
Продвинутый вариант подхода — скрыто (!) заменить значение чем-то похожим в середине цикла или функции.
Например:
функция ninjaFunction(elem) { // 20 строк кода, работающего с elem элем = клон (элем); // еще 20 строк, теперь работаем с клоном элемента! }
Коллега-программист, желающий работать с elem
во второй половине функции, будет удивлен… Только во время отладки, изучив код, они узнают, что работают с клоном!
Встречается в коде регулярно. Смертельно эффективен даже против опытного ниндзя.
Поставьте подчеркивания _
и __
перед именами переменных. Например _name
или __value
. Было бы здорово, если бы вы знали их значение. Или, лучше, добавьте их просто для развлечения, вообще без особого смысла. Или разные значения в разных местах.
Вы убиваете двух кроликов одним выстрелом. Во-первых, код становится длиннее и менее читабельным, а во-вторых, коллега-разработчик может потратить много времени, пытаясь понять, что означают подчеркивания.
Умный ниндзя ставит подчеркивания в одном месте кода и обходит их в других местах. Это делает код еще более хрупким и увеличивает вероятность ошибок в будущем.
Пусть все увидят, насколько великолепны ваши существа! Такие имена, как superElement
, megaFrame
и niceItem
наверняка просветят читателя.
Действительно, с одной стороны что-то написано: super..
, mega..
, nice..
Но с другой стороны – это не вносит никаких подробностей. Читатель может решить поискать скрытый смысл и помедитировать час-два своего оплачиваемого рабочего времени.
Когда на свету, в темноте ничего не видно.
В темноте можно увидеть все при свете.
Используйте одинаковые имена для переменных внутри и снаружи функции. Как просто. Никаких попыток придумать новые имена.
пусть пользователь = аутентификацияПользователь(); функция рендеринга() { пусть пользователь = другое значение(); ... ...много строк... ... ... // <-- здесь программист хочет работать с пользователем и... ... }
Программист, который зайдет внутрь render
, вероятно, не заметит, что локальный user
затеняет внешнего.
Затем они попытаются работать с user
предполагая, что это внешняя переменная, результат authenticateUser()
… Ловушка захлопнулась! Привет, отладчик…
Есть функции, которые выглядят так, будто ничего не меняют. Подобно isReady()
, checkPermission()
, findTags()
… Предполагается, что они выполняют вычисления, находят и возвращают данные, ничего не меняя за их пределами. Другими словами, без «побочных эффектов».
Действительно красивый трюк — добавить к ним, помимо основной задачи, «полезное» действие.
Выражение ошеломленного удивления на лице вашего коллеги, когда он увидит функцию с названием is..
, check..
или find...
что-то меняющее – обязательно расширит ваши границы разума.
Еще один способ удивить — вернуть нестандартный результат.
Покажите свое оригинальное мышление! Пусть вызов checkPermission
возвращает не true/false
, а сложный объект с результатами проверки.
Те разработчики, которые попытаются написать if (checkPermission(..))
, зададутся вопросом, почему это не работает. Скажите им: «Читайте документацию!». И дайте эту статью.
Великое Дао течёт повсюду,
и слева и справа.
Не ограничивайте функцию тем, что написано в ее названии. Будьте шире.
Например, функция validateEmail(email)
может (помимо проверки правильности адреса электронной почты) показать сообщение об ошибке и попросить повторно ввести адрес электронной почты.
Дополнительные действия не должны быть очевидны из названия функции. Настоящий программист-ниндзя сделает их неочевидными и из кода.
Объединение нескольких действий в одно защищает ваш код от повторного использования.
Представьте себе, что другой разработчик хочет только проверить электронную почту и не выводить никаких сообщений. Ваша функция validateEmail(email)
которая выполняет и то, и другое, им не подойдет. Поэтому они не нарушат вашу медитацию, спросив что-нибудь об этом.
Все «советы» выше взяты из реального кода… Иногда написаны опытными разработчиками. Возможно, даже более опытный, чем вы ;)
Следуйте некоторым из них, и ваш код станет полон сюрпризов.
Следуйте многим из них, и ваш код станет по-настоящему вашим, никто не захочет его менять.
Следуйте всем, и ваш код станет ценным уроком для молодых разработчиков, ищущих знаний.