Опубликовано в журнале Новый Мир, номер 1, 2005
Заметки о программировании
Сеть создали и продолжают создавать инженеры и программисты. И поскольку я на протяжении двух с половиной десятков лет тесно связан с программистской работой, то хочу сказать несколько слов о ней и о людях, которые ее делают.
А начну я со старого анекдота. Впрочем, само представление о “старости” и “юности” во всем, что касается цифрового мира, существенно отличается от мира реального. В информационной вселенной время течет несравнимо быстрее. Два года — это уже эпоха. По этим меркам анекдот относится ко времени компьютерных динозавров — годам, наверное, восьмидесятым.
Сын приходит к отцу-программисту и спрашивает:
— Папа, а почему Солнце каждый день восходит на востоке и заходит на западе?
Отец отрывается от дисплея, смотрит на сына долго и недоверчиво:
— Ты проверял?
— Да, — отвечает мальчик.
— Подтверждается?
— Да, — отвечает мальчик.
— Только ничего не трогай!
Конечно, программисты люди немного сдвинутые, немного не от мира сего. Конечно, они витают в каких-то заоблачных высях и вещи, для обычных людей ясные и внятные, для программиста — как гром среди ясного неба. В общем, как это ни странно, в этом вполне обиходном представлении о профессии много истины. Хотя и программисты есть всякие, и некоторые даже носят галстук.
Наш герой был гениальным программистом и был занят своими гениальными мыслями. Когда сын обратился к нему с вопросом, он, как честный человек и добросовестный профессионал, решил ответить точно и по существу. И поэтому сразу начал строить модель, описывающую движение Земли вокруг Солнца. С первого взгляда задача казалась довольно простой. Есть массивное тело — Солнце, и другое — Земля, тело гораздо меньшей массы — движется вокруг него по орбите, которая описывается законом всемирного тяготения. Тела можно считать материальными точками, орбита устойчива… (Вот здесь-то и остановился бы в своих размышлениях любой нормальный человек, но не наш гений.) “Стоп, — подумал он, — но ведь есть еще и Луна”. Система начала усложняться. Хорошо, учтем поправки, которые вносит масса Луны. Система получившихся уравнений уже не решается точно. Модель начала подрагивать. Это программиста насторожило. Но ведь есть же еще и планеты. Нужно учесть еще их массивное движение и влияние на Землю и друг на друга. Дальше стало еще хуже. Необходимо учесть движение комет и других блуждающих тел, а оно принципиально нерегулярно. Голова закипела. Земля, которая летела по своей орбите, как “мерседес” по автобану, в уточненной модели тащилась, как старый латаный “зилок” по проселочной дороге, жутковато кренясь от сложных и переменчивых гравитационных воздействий. Внезапно программист понял, что он не может доказать устойчивость полученной модели. Более того, на больших временнбых промежутках она скорее всего устойчива и не будет. Его очень удивило, почему Солнечная система за миллиарды лет своего существования не развалилась. “Господи! — подумал программист. — Каким бы гениальным программистом Ты ни был, Ты не мог не сделать ошибок в такой навороченной программе! Есть же порог сложности! И все это гигантское нагромождение модулей и интерфейсов обязательно должно дать сбой! Даже от малюсенького толчка, например от того, что мальчик возьмет со стола яблоко”. И тогда он строго посмотрел на сына и, стараясь не повышать голос, сказал:
— Только ничего не трогай!
Нужно ли выяснять, кто такой программист и что такое программирование? Может быть, и нет. Программист программирует — пишет текст на формальном языке, объясняет менеджеру, что делать надо так-то и так-то, а если, мол, не так — значит, ложь и профанация. Менеджер — управляет: ставит задачу, согласует интерфейсы, воспитывает программиста — чтобы не зарывался в частности и не срывал сроки, пытается максимально прояснить у заказчика, чего же этот заказчик, в конце концов, хотел. Заказчик никак не возьмет в толк, почему такие простые и ясные вещи, как его задачи, никак не обретут ту форму и законченность, которая ему изначально очевидна. Все эти люди пытаются добиться только одного — создать программный код, который был бы удобен, устойчив, эффективен и делал именно то, что должен делать.
И никому из этих людей не интересно, что такое программирование. Не создание определенного пакета, над которым они работают, а программирование как специфический род деятельности. Увы.
Исключения крайне редки, но они все-таки есть. Одно из них — верю, что не единственное, — это статья академика Андрея Ершова “Человеческий фактор в программировании” <http://www.softpanorama.org/Articles/ershov72.html>.
Статья датирована 1972 годом. Что произошло в программировании и в цифровом мире за тридцать с лишним лет, трудно себе представить, я не берусь. И тем не менее. “Попытки осмыслить ситуацию с индустрией производства программного обеспечения довольно редки, и одна из немногих удачных попыток принадлежит академику Aндрею Eршову. Его статья „Человеческий фактор в программировании” является одной из немногих статей „советского периода” развития программирования в России, вызвавших в свое время значительный резонанс на Западе”, — пишет в кратком вступлении к републикации в Softpanorama Bulletin (Jan. — March, 1998) Николай Безруков. Отмечая глубокую давность статьи Ершова, он добавляет: “Тем не менее многие положения этой статьи до сих пор звучат удивительно актуально”. С чем я полностью согласен.
Ершов обращает внимание на необходимость учитывать эстетическое начало программирования и крайнюю нежелательность того, что он называет “конвейерным программированием”, подходом к организации работы, который подавляет творческое начало. Ершов пишет: “Конвейерный метод в программировании может либо убить интеллектуальную компоненту в труде программиста, либо вызвать неврозы… Представьте себе человека, обязанного 8 часов в день, 5 дней в неделю, 50 недель в году решать одни кроссворды, и вы поймете, что такое программист, специализирующийся, например, на написании редактирующих программ. Одним словом, раскрепление людей по элементарным операциям в многомодульной системе — далеко не простая задача”. Свою главную мысль Ершов формулирует так: “…я подхожу к тому, чтобы сформулировать центральный тезис моей речи. Он состоит в утверждении, что программирование обладает богатой, глубокой и своеобразной эстетикой, которая лежит в основе внутреннего отношения программиста к своей профессии, являясь источником интеллектуальной силы, ярких переживаний и глубокого удовлетворения. Корни этой эстетики лежат в творческой природе программирования, его трудности и общественной значимости”.
Не все надежды Ершова, высказанные в его замечательной работе, оправдались. Эпоха всеобщей компьютерной грамотности не наступила. Программирование не стало всеобщим занятием и, видимо, не станет. Аналогия между умением писать и читать на естественном языке и умением программировать на формальном, та аналогия, на которой так настаивал Ершов, не стала реальностью. Видно, у этого есть очень глубокие причины, связанные с формальностью языка программирования и содержательностью языка естественного. Программирование не стало менее элитарным занятием за тридцать лет. Просто в некоторых случаях удалось найти общие решения, которые благодаря простоте интерфейсов позволили уйти от трудоемкого процесса создания формального кода. Но общие решения найдены не для всех задач, а если учитывать то, что область приложений непрерывно расширяется, всегда будут такие, которые не укладываются в существующие рамки, а значит, снова и снова нам придется писать программы. Безусловно, за тридцать лет кардинально изменилась сама среда программирования, языки и операционные системы. Но по-прежнему остались формальный язык и неформальный реальный мир, который не описывается формальными конструкциями в общем виде. И именно этот неформальный мир и противостоит области формальной свободы, в которую программист пытается его погрузить снова и снова и не оставляет своих попыток, несмотря на неразрешимость этой задачи.
Ежедневно сотни миллионов людей садятся на свое рабочее место и загружают Excel или другое аналогичное приложение. Практически никого из них не интересует, почему при клике мыши по иконке с нарисованной дискетой происходит сохранение файла. Ну, происходит и происходит. А как же иначе? Из каждой сотни пользователей, может быть, десять или меньше знают, что вместо того, чтобы кликать по иконке, можно выполнить макрос на Visual Basic, например ActiveWorkbook.Save, то есть выполнить простую формальную программу. Еще меньшее количество способно написать короткую программку, которая разбросает все листы электронной таблицы по разным файлам. И уж совсем редкий человек напишет новый объект.
Есть принципиальная разница между “дружественным” интерфейсом пакета (сколь угодно сложного) и самой простенькой программой. Связь формальных команд и последующих действий, которые происходят при выполнении этих команд, по крайней мере неочевидна. Чтобы почувствовать эту связь, чтобы научиться ее использовать, нужно обладать особым набором навыков. Нужно оторваться от содержания создаваемого документа и взглянуть на него как на некоторый формальный объект, то есть ответить на вопрос: что совпадает при создании всех текстов? Нужно заглянуть за кулисы. Программист — это тот человек, который чувствует себя за кулисами комфортно.
Если его устраивают предлагаемые возможности пакета, он просто воспользуется ими. Но его не остановит ситуация, которая поставит пользователя в тупик, — ситуация, когда этих возможностей недостаточно. Тогда он создаст возможность, а для этого ему понадобится спуститься на уровень ниже, от клика мыши к макросу, от существующего набора объектов к тому или иному инструментальному языку — С++ или Java. Но самым важным шагом является именно переход от графического интерфейса к формальному языку. Это — инициация.
Не все возможности языка можно реализовать с помощью сколь угодно изощренного графического интерфейса. Необходимо помнить, что разница между конструкцией языка (например, вложенными операторами “если”) и вызовами любой последовательности функций пакета из выпадающего меню очень близка к разнице между использованием переменных и наборов констант. Язык гибок и почти неограниченно изменчив. Он описывает через свои конструкции бесконечно много вариантов. А меню — меню и есть. Его, конечно, можно поменять, например расширить, но для этого нужно как раз опуститься на более низкий уровень, то есть понять, что и как мы присоединяем к работающей программе.
Если мы работаем с естественным языком, одни слова — глубоко содержательные объекты — объясняются с помощью других слов — таких же содержательных объектов. Интерпретаций бесконечно много, и полной определенности и однозначности все равно нельзя добиться. Если мы работаем с языком формальным, у этой лестницы спуска к языкам все более низкого уровня есть точная нижняя грань — это ассемблер, чьи команды реализованы в “железе”. Этим формальный язык принципиально отличен от естественного. В этом-то и есть его “плодотворная односторонность” (выражение Лидии Гинзбург).
Программист — это прежде всего человек, который чувствует себя свободно в формальном пространстве, человек, который оперирует однозначно определенными объектами. Этим он отличается, например, от писателя или даже от лингвиста, пытающегося построить формальную схему естественного языка. Лингвист строит формальную схему, но описывает ее неформально и прилагает к неформальному объекту. А программист начинает и заканчивает формальными конструкциями.
И оказывается, что формальный мир обладает своей глубокой красотой. Ее очень непросто почувствовать. Чтобы это произошло, необходимо отнестись к программе как к самостоятельной ценности и цельности, а не как к одному из модулей в огромном пакете. Но делать это необходимо, чтобы добиться от программы последней завершенности и чистоты. Ершов пишет: “…очень важным эстетическим принципом программирования является его высочайшая требовательность к законченности продукта. Конечно, это характерно для многих инженерных профессий. Однако программирование и здесь идет дальше. Хотя в мультимодульных программных конгломератах это свойство почти исчезает, на уровне индивидуальной работы всегда существует поразительный контраст между почти сделанной и полностью сделанной работой. Эта стопроцентность программирования — источник его трудности и в то же время глубочайшего удовлетворения работающей программой”.
Когда приходит ощущение завершенности работы над модулем? Можно ответить — никогда не приходит, и это не так далеко от истины. Но есть моменты, когда программист видит, что “Это — хорошо”. Это ощущение и есть ощущение законченной работы. Ни целесообразность, ни отсутствие ошибок при систематическом тестировании, ни верность интерфейсным соглашениям этого ощущения не дают. Ощущение того, что программа завершена, дает только чувство красоты.
Я очень хорошо помню свои чувства, которые испытал, когда заработала моя первая программа и на экране появились первые сообщения и запросы. Это был ни с чем не сравнимый восторг. Первая мысль: “Она все это делает сама”, и тут же другая: “Это я ее всему научил”.
Ощущение самостоятельности созданного тобой, его свободы и независимости от создателя — это чувство кажется мне самым важным, которое может пережить программист. Это — творчество.