Кодеры за работой. Размышления о ремесле программиста
Кодеры за работой. Размышления о ремесле программиста читать книгу онлайн
Программисты — люди не очень публичные, многие работают поодиночке или в небольших группах. Причем самая важная и интересная часть их работы никому не видна, потому что происходит у них в голове. Питер Сейбел, писатель-программист, снимает покров таинственности с этой профессии. Он взял интервью у 15 величайших профессионалов: Кена Томпсона, создателя UNIX, Верни Козелла, участника первой реализации сети ARPANET, Дональда Кнута, Гая Стила, Саймона Пейтон-Джонса, Питера Норвига, Джошуа Блоха, Брэда Фицпатрика, создателя Живого Журнала, и других. Все они «подсели» на программирование еще в школе. Тогда, на заре зарождения отрасли, лишь в немногих учебных заведениях читались курсы по компьютерным наукам. Поэтому будущим гуру приходилось покорять профессиональные вершины самостоятельно, но всех их отличает творческое горение и полная самоотдача любимому делу.
Вы узнаете, что они думают о будущем программирования и как сами научились программировать, как, по их мнению, нужно проектировать ПО, как выбор языка программирования влияет на продуктивность и можно ли облегчить выявление труднонаходимых ошибок.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Сейбел: Что касается операторов утверждений — насколько формально вы к ним подходите? Кто-то использует стандартное утверждение: «Я считаю, что в этом месте кода некоторое условие должно быть истинным». А кто-то мыслит более формально: у функций есть предусловия, постусловия и есть глобальные инварианты. Какова ваша позиция?
Завински: Я точно не думаю об этом в контексте математического доказательства корректности. Скорее я за стандартные утверждения. Конечно же, всегда полезно, получив входные данные в функции, хотя бы приблизительно понимать, какие у них ограничения. Может ли это быть пустая строка? Что-то в таком духе.
Сейбел: Тестирование — тема, весьма близкая к отладке. В Netscape была специальная группа обеспечения качества или вы все тестировали сами?
Завински: И то и другое. Мы все время запускали свои программы — это лучший способ проверки качества на месте. Но была и группа обеспечения качества, у которой были формальные тесты. И каждый раз перед выпуском новой версии они все проверяли по списку. Перейти на такую-то страничку, щелкнуть там-то. Вы должны увидеть это. Или не должны увидеть.
Сейбел: А как насчет тестов на уровне разработчика, таких как модульные тесты?
Завински: Нет, у нас такого не было. Для некоторых вещей я делал нечто похожее. У синтаксического анализатора дат для почтовых заголовков был огромный набор сценариев тестирования. В те дни мало кто обращал внимание на стандартизацию, поэтому в заголовках могла приходить всякая ерунда. И что бы там ни было, пользователям не нравится, когда их почта сортируется неправильно. Поэтому я собрал целую кучу примеров, создал тесты и получил громадный список плоховато отформатированных дат и чисел, в которые, как я считал, эти даты должны преобразовываться. Каждый раз, внося изменения в код, я запускал тесты, и некоторые из них падали. Так должен я соглашаться с ними или нет?
Сейбел: Переросло ли это в какую-то форму автоматического тестирования?
Завински: Нет, когда я писал такие модульные тесты для своего кода, они запускались в основном лишь тогда, когда я сам запускал их. Потом мы немного занимались этим, когда работали над проектом Grendel, переписывая почтовый клиент на Java, поскольку там гораздо легче писать модульные тесты при разработке новых классов.
Сейбел: Оглядываясь назад, как вы считаете, ваша команда пострадала от этого или нет? Упростилась бы или ускорилась разработка, если бы вы были дисциплинированнее в вопросах тестирования?
Завински: Не думаю. Мне кажется, это бы только замедляло нас. Можно долго говорить о том, как все делать правильно с первого раза. Первоначально мы были зациклены на скорости. Нам нужно было выпустить продукт, пусть даже несовершенный. Мы могли бы выпустить его позже, и его качество было бы выше, но к тому времени нас мог бы кто-нибудь опередить.
Довольно часто говорят, что дело пойдет быстрее при наличии модульных тестов, меньших модулей и тому подобное. Все это хорошо звучит в теории. При неспешном темпе разработки это действительно отличный вариант. Но когда тебе говорят: «Нам нужно сделать это с нуля за шесть недель», — приходится чем-то жертвовать, иначе не справиться. И я выбрасываю то, что не является абсолютно критичным. Модульные тесты не критичны. Пользователь не будет жаловаться на то, что у вас нет модульных тестов. Это ваше личное дело.
Не хочу, чтобы все решили, будто я считаю тесты ерундой. Нет. Это всего лишь вопрос приоритетов. Вы пытаетесь написать хорошую программу или пытаетесь закончить к следующей неделе? Сделать то и другое одновременно не получится. У нас в Netscape была такая шутка: «Мы стопроцентно преданы качеству. Мы собираемся выпустить продукт самого высокого, насколько у нас получится, качества к 31 марта».
Сейбел: Отсюда другая тема — сопровождение программного обеспечения. Как вы разбираетесь в коде, который не сами писали?
Завински: Я просто беру его и читаю.
Сейбел: С чего вы начинаете? Читаете его последовательно, с первой страницы?
Завински: Когда как. Чаще всего приходится изучать, как использовать новую библиотеку или набор инструментов. Если повезет, будет даже какая-нибудь документация. Есть некий API. Разбираешься с отдельным фрагментом, чтобы понять, как он работает, или выясняешь, как что-то реализовано. Так и прокладываешь себе путь через все это. С такими инструментами, как Emacs, можно начать снизу. Из чего состоят списочные ячейки (cons cells)? Как это выглядит? От этого можно танцевать. Иногда знакомство с системой построения позволяет понять, как все это сочетается. Мне всегда казалось, что, для того чтобы погрузиться в кусок кода, нужно взять некоторую задачу и попытаться ее решить.
С такими инструментами, как Emacs, можно взять существующий модуль и распотрошить его. Так, вот кусок кода. Вычленяем часть, которая действительно что-то делает, и получаем шаблон. Теперь мы знаем, на что похож компонент этой системы, и можем вставлять туда свои куски кода. Это как разобрать его по косточкам.
Сейбел: В Emacs вы в конце концов переписали компилятор байт-кода и части байт-кода виртуальной машины. Мы уже говорили о том, что значительно приятнее что-то переписать заново, чем исправлять, но это не всегда подходит. Не понимаю, как вы перешли эту черту? Вы решили переписать компилятор целиком, потому что это проще, чем исправить только некоторые его части? Или просто подумали: «Ух ты! А здорово будет написать компилятор!»
Завински: Так уж вышло, что в результате компилятор был переписан полностью. Я начал с внесения исправлений и попыток оптимизации. Но в конце концов в нем не осталось ничего от первоначального варианта. Я использовал тот же API, пока в нем не отпала необходимость. По-моему, компилятор байт-кода вышел отлично, отчасти потому, что это был изолированный модуль с единственной «точкой входа»: скомпилировать и сохранить.
Конечно, многое из того, что я добавил в Lucid Emacs, было не столь полезным. На самом деле, многие мои действия объяснялись желанием приблизить все это к Лисп-машинам и к более привычным для меня версиям Emacs и средам разработки под Лисп. И я приложил много усилий, чтобы Лисп в Emacs был более совершенным: например, чтобы использовались объекты-события, а не списки чисел. Использовать списки чисел вместо объектов-событий — примитив и безвкусица. Теперь понятно, что эти изменения были одной из главных проблем, поскольку приводили к несовместимости с библиотеками сторонних разработчиков.
Сейбел: И вы, конечно, не знали о скором появлении двух разновидностей Emacs [14].
Завински: Разумеется. Но и без того уже были две версии Emacs — 18 и 19. Так или иначе, проблема совместимости все равно бы возникла. Оглядываясь назад, я понимаю, что если бы осознавал последствия внесенных мной изменений, то сделал бы все по-другому. Или потратил бы больше времени на то, чтобы старый вариант тоже работал. Как-то так.
Сейбел: Вы уже упоминали о написании легко читаемого кода, что непосредственно касается сопровождения. Так что же делает код легко читаемым?
Завински: Конечно же комментарии. Запись предположений и того, что код делает. Если речь идет о создании структуры данных, то описание ее устройства. Я много раз убеждался, что это полезно. Это особенно полезно при написании кода на Perl, где все обстоит примерно так: это хеш-таблица, а значения представляют собой ссылки на списки, поскольку структуры данных в Perl — такая вот ерунда. Нужно ли использовать стрелку вправо (->), чтобы добраться до этого? Думаю, такие примеры не помешают.
Я всегда советовал писать больше комментариев, но меня раздражает, когда комментарий представляет собой перефразированное имя функции. Функция называется pushstack (добавить элемент в стек), а комментарий — «добавление элемента в стек». Большое спасибо.