[Перевод] Миллион строк плохого кода
«No pain, no gain», как гласит древняя восточная мудрость. И даже если мудрость не древняя и не восточная, лично для меня самый ценный жизненный опыт чаще всего был и самым болезненным. Недавний пост Дэвида Робинсона — аспиранта, занимающегося программированием в стенах Принстонского университета — посвященный код ревью, не только поднял важный вопрос повседневного быта каждого, кому волей (или неволей) приходится передавать свой опыт другим. Оригинальный текст был относительно «беззубым», однако, пост перестал быть томным после того, как в комментариях появился Джон Кармак.Это история о плохом коде, который однажды написал ваш покорный слуга.
На одном из первых курсов университета я писал программу на Java, которая должна была читать файл весом в 6 MB в строку (этим файлом был геном бактерии в формате FASTA). Выглядел мой код следующим образом:
BufferedReader reader = new BufferedReader (new FileReader (file)); String line = null; String text = »;
while ((line = reader.readLine ()) != null) { text = text + line; } Построение строки при помощи серии конкатенаций подобным образом крайне неэффективно — у меня, без преувеличения, уходило около 40 минут на чтение файла (с тех пор я узнал несколько способов получше). Самое главное — после чтения файла весь оставшийся алгоритм в программе отрабатывал секунд за 10. Два дня я так и работал: делал изменения в коде, запускал программу и успевал посмотреть целый эпизод LOST, прежде чем программа завершала выполнение. «Черт, на двенадцатой строчке ошибка! Опять все по-новой…«После множества повторных запусков я наконец подумал «наверняка должен быть лучший способ сделать это». Я выяснил, что можно написать цикл на Perl, который сможет считать геном менее чем за одну секунду (при этом на Perl я умел программировать не лучше, чем на Java — просто повезло). Итак, я сел и написал скрипт на Perl, который читал файл, собирал его в одну строку и выводил ее. Затем я сделал так, что моя программа на Java вызывала скрипт на Perl через командную строку, захватывала вывод и сохраняла его в строку.Если бы у меня сохранилась эта программа, то я бы напечатал ее исходный код и повесил в рамку на стену, чтобы почаще себе напоминать о том, что никогда и никого не буду ругать за написанный им «плохой» код.
Рассказать об этом случае из моей жизни меня вдохновил свежий комикс с XKCD про «качество кода»:
Комикс кроме как «злым» не назовешь — опытный программист не дает ни одного полезного совета, только проводит гиперболические аналогии. Но что больше всего зацепило мой взгляд, так это ответ пациента — «Хорошо, я почитаю руководство по кодинг стайлу». Отреагирует ли так живой человек, если кто-то будет настолько груб к нему? Разве ответ будет похож не на «Хорошо, это был последний раз когда я показал тебе свой код», или даже «Хорошо, думаю я должен завязать с программированием»? Проблема присутствует и в научных исследованиях. Есть много причин, по которым ученые публикуют свои статьи без прикладывания к ним кода (и они вполне объяснимы), но первую позицию в их списке обычно занимает смущение: «мой код слишком уродлив для того, чтобы отдавать его кому-то». Те, кто стремятся пристыдить других за код, в этом вопросе не слишком-то помогают!
Известный совет начинающим писателям гласит: «Каждый из нас держит в себе миллион плохих строк. Прежде, чем этот миллион выльется наружу, пытаться написать что-то хорошее бесполезно. Так идите и пишите!». Я вспомнил о нем, когда читал дискуссию, разгоревшуюся по поводу приведенного выше XKCD:
The only way to write good code is to write tons of shitty code first. Feeling shame about bad code stops you from getting to good code
— Hadley Wickham (@hadleywickham) 17 апреля 2015
Когда вы, опытный программист, в следующий раз захотите пристыдить кого-нибудь за его код, попробуйте мысленно вернуться к собственному миллиону строк кода. Представьте, что кто-нибудь осудил вас так же, как и я себя выше. Продолжили бы вы просить о помощи? Осилили бы вы свою дорогу в миллион строк? Комментарий Джона Кармака Не надо путать слова «написавший этот код идиот» и «этот код дерьмо» — между ними есть существенная разница. Комикс как раз о последнем. Предполагаю, что сделано это сознательно. Атака на автора вряд ли принесет какую-то пользу, но должна существовать возможность строго критиковать сам код. В реальной жизни, у многих авторов не получается отделять себя от своей работы, однако умение проделывать это — ценный навык.Предоставленные сами себе, большинство людей демонстрирует непробиваемую способность игнорировать свои недостатки, и это вредит их профессиональному росту. Небольшой стыд часто становится позитивной мотивацией. Мне стыдно за огромное количество из того кода, что я написал за последний год. У меня в голове есть мысли насчет причин, почему все получилось так, как получилось, — некоторые из них представляют собой оправдания, но часть из них — это чистой воды «WTF я думал вообще, когда писал это?». И если вы не чувствуете небольшой вины за ваши последние работы, то, вполне возможно, вам будет полезно, если кто-то укажет вам на проблемы — в том плане, что этот человек сможет пробиться сквозь ваши «защитные механизмы».
Я был бы счастлив, если бы кто-нибудь «зарылся» во весь тот код, что я написал для Oculus Mobile SDK. Уверен, что по большей части этим читателем рано или поздно стану я сам, и по большей части буду только кивать головой и соглашаться с написанным; однако, я уверен, что смогу вынести из этого что-то полезное, и это благотворно повлияет на мою дальнейшую работу.
>> Вы в Oculus делаете код ревью для каждого коммита?
Нет. У нас есть некоторые подвижки в этом направлении; мне интересно будет увидеть, что из этого получится. На нас все еще сильно сказывается давление темпа работы над стартапом.
>> Ваш комментарий к статье выглядит так, будто макака прокатилась по клавиатуре, а вы потом только прошлись для виду автокорректом… ну как, прозвучало не слишком уж полезно, правда? Думаю, что вы путаете излишнюю жесткость с серьезной критикой. Заметили, что моя последняя фраза не такая обидная, и в то же время принесла толку больше, чем первая?
Обычно тактичные и полезные комментарии работают лучше всего, но бывают случаи, что необходим некоторый минимум «активационной энергии» для того, чтобы комментарий произвел действие на человека.
>> Делали ли вы ревью кода, написанного другими разработчиками в id в прошлом?
Неформально, и тогда мне этого хватало. Мне не нравится заниматься ревьюированием кода; возможно, по этой причине я высоко ценю критику.
Пусть Джон и признается, что отчасти не сторонится в жизни строгих комментариев, ему далеко до Линуса Торвальдса, щедро пересыпающего свои письма личными оскорблениями, а выступления — фразами в духе «Меня не интересуете вы, я беспокоюсь о технологии и ядре — вот что для меня действительно важно» и утверждениями, что «никто не услышит вас, если вы собираетесь быть мягким».