Programming
Perfect code
April 2014 17

Грабли, на которые не стоит наступать

From Sandbox
От переводчика: Это перевод статьи авторства Джоэля Спольски (Joel Spolsky). Через 2 года эта статья уже сможет получить автомобильные права в США, а еще через два — и не только там. Да, ей 14 лет (а точнее 14 лет и 11 дней), но актуальности она не потеряла ни грамма. Я регулярно вижу, как программисты (да и я сам, временами) порываются наступить на эти грабли. Тот факт, что я не нашел ее перевода на Хабре, вполне может свидетельствовать о том, что я плохо искал. Об ошибках перевода прошу сообщать в ЛС

UPD: Оказывается перевод статей Джоэля, в т. ч и этой, есть еще в бумажном издании «Джоэл о программировании»

Наконец выходит первая публичная бета-версия Netscape 6.0. Версии 5.0 не существует. Предыдущий мажорный релиз — версия 4.0 — был выпущен почти три года назад. Три года — это невероятно большой срок в мире интернета. Все это время в Netscape сидели и беспомощно наблюдали за тем, как уменьшается их доля рынка.

Это немного подло с моей стороны критиковать их за столь долгое ожидание между релизами. Они ведь не специально это сделали, правда?

Неправда! Именно так они и сделали. И этим они совершили единственную самую большую стратегическую ошибку, которую когда-либо может сделать софтверная компания.

Они решили переписать код с нуля.

Netscape не была первой компанией, которая сделала такую ошибку. Borland совершила ее при покупке Arago, решив превратить ее в dBase for Windows — проект, который потребовал столько времени, что все вкусняшки достались Microsoft Access; и потом они совершила ее еще раз, переписав Quattro Pro с нуля и поразив всех тем, как мало программа умела. Microsoft сама почти повторила эту же ошибку при попытке переписать Word for Windows с нуля в обреченный проект под названием Pyramid, который был свернут, выброшен и забыт. На счастье Microsoft, работа над старым кодом не прекращалась, и у них было что выпускать, так что все это обернулось финансовой катастрофой, но не стратегической.

Мы — программисты. А программисты в душе — архитекторы, и первое, что они хотят сделать, когда попадают на дело, — пройтись бульдозером по всему и сделать что-то грандиозное. Мы не в восторге от последовательных улучшений: подкрутить, подправить.

Есть коварная причина, по которой программисты всегда хотят выкинуть весь существующий код и начать писать заново. Они думают, что старый код — это бардак. А вот и интересное наблюдение: скорее всего они ошибаются. Причина, по которой они думают, что код ужасен, кроется в основном, фундаментальном законе программирования:

Читать код сложнее, чем его писать

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

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

Почему же бардак?

«Ну», — скажет он, «глянь вот на эту функцию. Она две страницы в длину! Тут почти все лишнее. Да я даже не знаю зачем здесь половина этих API-вызовов.»

Перед выходом нового менеджера таблиц для Windows от Borland пресса зацитировала до дыр похвальбы Филиппа Кана — основателя компании — о том, насколько Quattro Pro будет круче, чем Microsoft Excel, так как он был переписан с нуля. Полностью новый код! Как будто код ржавеет.

Идея о том, что новый код лучше старого, явно абсурдна. Старый код использовался. Он протестирован. Множество багов было найдено и они были исправлены. И с этим все в порядке. Код не плодит баги просто валяясь на жестком диске. Как раз наоборот! Программное обеспечение — это что, старый Dodge Dart, который ржавеет просто простаивая в гараже? Это что, плюшевый мишка, который плохо выглядит, если не сделан исключительно из нового материала?

Вернемся обратно к двухстраничной функции. Да, я знаю, это простая функция для отображения окна, но она обросла мусором и прочим барахлом, и никто не знает почему. Ну так я скажу почему: это фиксы багов. Этот кусок исправляет баг, который случился у Нэнси, когда она пыталась установить всё на машину без IE. Этот — тот баг, который происходит при нехватке памяти. А этот — когда файл находится на дискете, а юзер ее выдернул посреди всего. Вот этот вот вызов LoadLibrary ужасен, но благодаря нему код работает на старых версиях Windows 95.

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

Когда выбрасываешь код и пишешь его заново, ты выбрасываешь весь этот багаж знаний. Все эти пофикшеные баги. Годы работы программистов.

Ты выбрасываешь свое преимущество на рынке. Ты даришь два или три года своим конкурентам, а это, поверь мне, много времени в контексте разработки ПО.

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

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

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

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

Первая — проблемы архитектуры. Код неотрефакторен. Код, отвечающий за сетевые соединения, вдруг выбрасывает из ниоткуда собственные диалоговые окна; это должно обрабатываться в коде UI. Такие проблемы могут быть исправлены по одной: аккуратным рефакторингом и изменением интерфейсов. Это может сделать один программист работая аккуратно и внедряя свои изменения целиком, никому не мешая. Даже довольно внушительные изменения архитектуры можно сделать без выбрасывания кода. В проекте Juno мы однажды провели несколько месяцев переделывая архитектуру: просто перемещая все вокруг, подчищая все, создавая осмысленные базовые классы и интерфейсы между модулями. Но мы делали это аккуратно и с текущим кодом, мы не вносили новых багов и не выбрасывали работающий код.

Вторая проблема, по которой программисты считают своей код бардаком, — неэффективность. Считалось, что у Netscape плохой код рендеринга. Но это затрагивало только небольшую часть проекта, которую можно оптимизировать или даже переписать. Но не надо переписывать всё. При оптимизации ради скорости 1% работы дает 99% результата.

И третье — код может быть просто невероятно отвратительным. Однажды я работал над проектом, в котором всерьез использовался тип данных FuckedString. В другом проекте договорились начинать имена свойств с "_", но позже решили перейти к более стандартному «m_». Поэтому половина функций начиналась с "_", а половина с «m_», и это было отвратительно. Честно, это проблемы, которые решаются пятиминутным написанием макросов в Emacs, а не переписыванием с нуля.

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

Старая мантра "делай, чтобы выбросить" очень опасна в применении к масштабному коммерческому проекту. Когда экспериментируешь с кодом, можно выпилить функцию, написанную две недели назад, в связи с находкой лучшего алгоритма. Тут все в порядке. Можно отрефакторить класс, чтобы его было проще использовать. Тут тоже все в порядке. Но выбросить всю программу — это опасная ошибка, и если бы Netscape был под наблюдением компании с опытом в индустрии ПО, они, возможно, не выстрелили бы себе в ногу с таким рвением.
+140
73k 375
Comments 68
Top of the day