Кодеры за работой. Размышления о ремесле программиста
Шрифт:
Сейбел: Большинство лисперов, вероятно, думают, что замыкания там убогие, лямбда-выражения весьма ограниченные.
Стил: Это правда. Однако Гвидо приходилось идти на компромисс между ясностью, возможностью реализации и так далее. И все равно получился интересный набор свойств. Я сделал бы по-другому, но он работал для определенного пользовательского сообщества. Я понимаю, почему он в каждом случае поступил так, а не иначе, и уважаю его выбор. Haskell - красивый язык, я люблю его, хотя использую мало.
Сейбел: Итак, любя Haskell, вы сейчас проектируете язык, но Fortress -
Стил: Сейчас в Haskell используются монады: монада ввода/вывода, монада транзакционной памяти. Есть теория, что это очень функционально; может, это и правда помогает в работе. Но с другой стороны, кажется, что язык становится все более императивным. Как там говорил Белый Рыцарь из “Зазеркалья”? “Но я обдумывал свой план, как щеки мазать мелом, а у лица носить экран, чтоб не казаться белым” [67] . Монады для меня - как раз такой экран: сначала вы вытаскиваете ввод/вывод, потом пытаетесь его скрыть обратно - и в итоге непонятно, есть побочные эффекты или нет.
67
Пер. Н. Демуровой.
Скажу вот что: примерно раз в месяц у меня возникает чувство, что в работе с Fortress надо было бы идти со стороны Haskell к Фортрану и Java, а не брать Фортран и Java и двигаться в сторону Haskell. Проектируя библиотеки для Fortress, мы все больше применяем функциональный подход - и все чаще встречаем трудности в создании эффективных параллельных структур данных.
Сейбел: Вы пишете много прозы, этот род деятельности вам также интересен. Как по-вашему, писать прозу и код - занятия одного порядка или нет?
Стил: Скорее разного: я четко сознаю, что у читателя прозы иная система обработки данных, чем у компьютера. И я не могу, скажем, в той же мере использовать рекурсию. Правда, для утонченных читателей я порой прибегаю к этому приему. Но всегда ясно сознаю, как читатель будет обрабатывать текст в уме и понимать его.
Иногда я очень беспокоюсь, когда пишу прозу, - с кодом я волнуюсь куда меньше. Это из-за неоднозначности слов. Мне все время кажется, будто меня поймут не так. И я провожу много времени, пытаясь отточить стиль моей прозы, употребляю конструкции, которые сложно понять двояко.
У меня есть любимый скетч из передачи “Saturday Night Live” - тот, где Эд Эснер изображает сотрудника АЭС, который уезжает в отпуск на две недели. Перед уходом он говорит: “Всем пока! Помните, в ядерном реакторе не может быть слишком много теплоносителя”. И дальше минуты три все обсуждают, что же он хотел сказать.
Сейбел: Итак, вы видите очевидный контраст между текстами для человека и текстами для компьютера. Но ведь многие, как Кнут, указывают, что написанный вами код обращен и к человеку — не меньше, чем к компьютеру.
Стил: О, это так.
Сейбел: Значит, в этом плане программисту полезно писать прозу?
Стил: Конечно. Работая над кодом, я все время думаю: поймет ли компьютер, чего я от него хочу? Скорее даже так: поймет ли он меня однозначно? А не в смысле, что совсем не поймет. Часто сказать что-то правильно можно разными способами. И тут я начинаю переживать
Это опять же компромисс: если важна эффективность, мы прибегаем к разным уловкам. Но тогда оказывается сбитым с толку человек. И надо добавлять комментарии или как-то еще делать код читаемым. Обычно выбор имен переменных и организация кода - забота скорее о читателе, о форматировании, которое безразлично компьютеру, но облегчает чтение человеку.
Сейбел: По мере того как языки улучшаются или хотя бы становятся дружественными к программисту - в сравнении с временами ассемблера и перфокарт, - избегать ошибок в программах вроде бы становится легче. Есть компиляторы, сигнализирующие об ошибках, и так далее. Так можно ли отдать предпочтение - пусть небольшое - читаемости кода перед правильностью? Как говорят разработчики на Haskell: “Если ваша программа на Haskell выполняет проверку типов, можно спать спокойно”.
Стил: Думаю, это страшное заблуждение. В пропущенных через компилятор программах всегда слишком много ошибок, чтобы спать спокойно. А если есть ошибки, они собьют с толку не только компьютер, но и человека, читающего код.
Программирование - глубоко неестественный вид деятельности, и ему надо как следует учиться. Люди привыкли, что их слушатели сами восстанавливают лакуны в речи. И с компиляторами мы обращаемся в какой-то мере так же. Говоря: “Мне нужна переменная с именем f оо”, - вы не заботитесь о регистре имени. Люди неточны, часто неряшливы в своей речи. Но когда мы даем команды машине, детали важны, потому что мелкая погрешность может изменить ход всего процесса.
Мне кажется, люди привыкли к использованию рекурсии в ограниченном виде - кажется, это показал Ноам Хомский. Но на деле люди редко углубляются больше чем на три уровня, а если и углубляются, то обычно в стиле хвостовой рекурсии. Понимание рекурсии есть сложнейшее искусство. А ведь рекурсия - один из самых мощных инструментов программиста, если его как следует освоить. И поэтому заботиться о корректности надо всегда.
Сейбел: Тем не менее многие пытались разработать языки или системы, дающие возможность написать программу непрограммисту. Считаете ли вы эти попытки обреченными на неудачу - ведь дело не в правильности синтаксиса, а в том, что программирование неестественно по природе.
Стил: Да. И, кроме того, люди сосредоточены на главном, они не думают о пограничных случаях, о сложных случаях, о маловероятных случаях. А именно в таких случаях начинаются разногласия - как сделать правильно.
Иногда я спрашиваю студента: “Что будет в таком-то случае?” - “То-то и то-то”. И тут же кто-нибудь вскакивает: “Нет, должно быть вот так!” Вот такие вещи и надо отражать в программной спецификации.
Неслучайно для описания процесса программирования мы пользуемся терминами из арсенала магии. Мы говорим: что-то произошло как по волшебству или автоматически. Думаю, это оттого, что заставить машину сделать нужную тебе вещь - почти то же самое, что добиться исполнения желания.
Посмотрите: героям волшебных сказок достаточно придумать желание, махнуть рукой - и вот оно выполнено. И, конечно, сказки полны поучительных ситуаций: герой забыл учесть пограничный случай - и из-за этого случилось что-то нехорошее.