Недавно я получил приглашение от крупной (и растущей) компании, производящей аппаратуру. В течение многих лет его традиционная линейка продуктов была высококачественным аналоговым оборудованием, но со временем цифровые компоненты стали играть более важную роль. Руководству компании было известно о более или менее неизбежном погружении в область программного обеспечения (с чем компания ранее не сталкивалась), было известно о существовании многих ее подводных камней, хотя и не имея четкого понимания их; тогда меня пригласили объяснить руководству компании, что такое дизайн программного обеспечения, почему это так дорого и т.д.
Имея много других обязательств, я пока не знаю, смогу ли я принять приглашение, но, независимо от этого, вызов абсолютно радует меня. Я не только программировал более 25 лет, но с самого начала и до сегодняшнего дня я занимался этим, даже в периоды, когда сотрудничал с проектировщиками оборудования, разработчиками машин, тестерами прототипов и т.д. Я думаю, что знаю среднего разработчика цифрового оборудования и его проблемы достаточно хорошо, чтобы осознать его непонимание того, почему проектирование программного обеспечения так сложно. Объяснить ему сложность разработки программного обеспечения достаточно трудно (почти так же трудно, как объяснить это чистому математику), объяснить же это группе дизайнеров с их опытом и профессиональной гордостью за высококачественное аналоговое оборудование — добавляет особый вкус к брошенному вызову! Размышляя о встрече и осознавая, что даже если я приму приглашение, у приглашающих не будет исключительных прав на мои объяснения, я решил взять ручку и бумагу. Отсюда и этот текст.
* * *
На экономический вопрос "Почему программное обеспечение такое дорогое?" не менее экономический ответ может быть «Потому что его делают с дешевой рабочей силой». Почему так? Потому что его внутренние трудности широко и сильно недооценены. Итак, давайте сконцентрируемся на «Почему разработка программного обеспечения так сложна?». Часть моего ответа будет в том, что с недостаточно образованным персоналом сложности избежать невозможно, с адекватно образованными разработчиками программного обеспечения это возможно, но, безусловно, останется трудным. Я хотел бы подчеркнуть, с самого начала, что текущие проблемы в разработке программного обеспечения могут быть объяснены выявленной недостаточной компетентностью программистов только частично. Я хотел бы отметить это с самого начала, потому что это объяснение, хотя и не редкое, слишком поверхностное.
Это понятно: для менеджера аппаратного обеспечения должно быть очень неприятно производить то, что он справедливо считает надёжной машиной с великолепным соотношением цена/производительность, и после этого наблюдать, что к тому времени, когда клиент получает всю систему, эта система полна ошибок и его производительность упала ниже худших ожиданий её разработчика. И помимо того, что ему приходится проглатывать то обстоятельство, что разработчики программного обеспечения испортили его продукт, он, как ожидается, ещё смирится с тем, что, хотя он с каждым годом работает все более и более эффективно, группа разработчиков программного обеспечения гордится своей некомпетентностью за счет ежегодного увеличения бюджетов. Без дальнейших объяснений с нашей стороны мы, программисты, должны простить ему его выплёскиваемую горечь, потому что, обвиняя нас в некомпетентности, он грешит невежеством... И пока мы не были в состоянии объяснить природу наших проблем ясно, мы не можем винить его за невежество!
* * *
Сравнение между миром аппаратного обеспечения и миром программного обеспечения кажется хорошим введением для разработчика оборудования в проблемы его коллеги-программиста.
Разработчик оборудования должен смоделировать дискретную машину по существу аналоговыми средствами. В результате разработчик аппаратного обеспечения должен задуматься о задержках, искажениях сигналов, включении и выключении, перекосе часов, рассеянии тепла, охлаждении и электропитании, а также обо всех остальных проблемах технологии и производства. Создание из аналоговых компонентов подразумевает, что «допуски» являются очень важным аспектом спецификаций его компонентов; его контроль качества в основном носит статистический характер, и, когда все сказано и сделано, обеспечение качества, по сути, является вероятностным утверждением. Тот факт, что при нынешних стандартах качества вероятность правильной работы очень и очень высока, не должен позволять нам забыть о её вероятностной природе: очень высокую вероятность не следует путать с уверенностью (в математическом смысле), и поэтому совершенно уместно, чтобы ни один элемент оборудования не поставлялся без тестирования. По мере того, как технология все больше и больше раздвигается до предела (и так происходит постоянно), и допуски становятся все более и более узкими, контроль этих допусков становится основной проблемой для производителей аппаратного обеспечения. По сравнению с разработчиком аппаратного обеспечения, который постоянно борется с непослушной природой, разработчик программного обеспечения живет на небесах, поскольку он строит свои артефакты из нулей и единиц. Ноль — это ноль, а единица — это единица: в его строительных блоках нет никакой неясности, и общее инженерное представление о том, что что-то находится «в пределах допуска», здесь просто не применимо. В этом смысле программист действительно работает в небесной среде. Гипотетический стопроцентный схемотехник, который сводит проблемы проектирования и строительства к проблемам контроля допуска, должен быть слепым к проблемам программирования: как только он правильно смоделировал дискретную машину, все действительно сложные проблемы были решены, не так ли?
Чтобы объяснить миру аппаратного обеспечения, почему программирование все ещё создает проблемы, мы должны обратить внимание на несколько других отличий. В общих чертах мы можем рассматривать «разработку» как преодоление разрыва, как создание структуры из данных компонентов; до тех пор, пока «целевая структура» и «исходные компоненты» не изменятся, мы можем повторно использовать старый дизайн. Дело в том, что нам нужно постоянно проектировать, потому что они меняются. Здесь, однако, разработчики аппаратного и программного обеспечения столкнулись с совершенно разными, почти противоположными типами вариаций, изменений и разнообразия.
Для разработчика аппаратного обеспечения наибольшие изменения произошли в «исходных компонентах»: пока машины были спроектированы, ему приходилось догонять новые технологии, у него никогда не было времени, чтобы полностью ознакомиться с его исходным материалом, потому что до того, как он достиг этой стадии, новые компоненты, новые технологии появились на сцене. По сравнению с резким изменением его «исходных компонентов», его «целевая структура» практически не изменилась: все время он переделывал и перепроектировал одни и те же несколько машин.
Для программиста различия и разнообразие находятся на другом конце: цель разработчика оборудования — отправная точка программиста. «Исходные компоненты» программиста были на удивление стабильны, в глазах некоторых — даже удручающе! FORTRAN и COBOL, столь модные до сих пор, имеют возраст более четверти столетия! Программисты находят разнообразие на другой стороне пропасти, через которую строит мост: они сталкиваются с набором «целевых структур» большого разнообразия. Даже очень большого разнообразия; потому что здесь мы нашли отражение того, что сегодняшнее оборудование действительно заслуживает названия «общего назначения».
В течение последнего десятилетия разработчики программного обеспечения вели почти религиозную дискуссию о разработке «снизу вверх» и «сверху вниз». Раньше это было «снизу вверх»: я думаю, что теперь религия «сверху вниз» имеет большинство в качестве своих приверженцев. Если мы примем обоснованный принцип, согласно которому, когда мы сталкиваемся с многосторонней проблемой, мы должны сначала исследовать область нашей самой большой неопределенности (поскольку решение знакомых проблем может быть отложено с меньшим риском), мы можем интерпретировать преобразование программирования от «снизу вверх» до «сверху вниз» как медленное признание того обстоятельства, что наибольшее разнообразие для программиста находится на другой стороне пропасти.
Помимо того, что программист находится по ту сторону пропасти, вариации и разнообразие, с которыми он сталкивается, являются более неограниченными. Для понимания его исходных компонентов разработчик аппаратного обеспечения должен в крайнем случае прибегнуть к физике и электронике: для понимания своей целевой задачи и разработки решающих её алгоритмов разработчик программного обеспечения находит соответствующую теорию чаще всего недостаточной. Однако то, насколько вредным может быть отсутствие адекватной теории, раскрывается медленно.
С первыми машинными приложениями, которые были научно-техническими, таких трудностей не было: проблема, которая должна быть решена, была с научной точки зрения прекрасно понятна, и численная математика была доступна для обеспечения алгоритмов и их обоснования. Дополнительное кодирование, которое необходимо выполнить, например, для преобразования между десятичной и двоичной системами счисления и для программных загрузчиков, было настолько тривиальным, что хватало здравого смысла.
С тех пор мы снова и снова видели, что из-за отсутствия соответствующей теории проблемы решались со здравым смыслом, а здравого смысла оказалось недостаточно. Первые компиляторы были сделаны в пятидесятых годах без какой-либо приличной теории для определения языка, для синтаксического анализа и т.д., и они были полны ошибок. Теория разбора и тому подобное появилась позже. Первые операционные системы были созданы без должного понимания синхронизации, дэдлоков, опасности "голода" и т.д., и они страдали от недостатков, которые в прошлом были предсказуемы. Необходимая теория, опять же, пришла позже.
На практике люди поняли, что для некоторых проблем здравый смысл не является достаточным умственным инструментом. Проблема состоит в том, что к тому времени, когда необходимая теория была разработана, преднаучный, интуитивный подход уже утвердился и, несмотря на свою патентную недостаточность, искоренить его труднее, чем хотелось бы думать. Здесь я должен критически прокомментировать практику управления, которая не редкость среди производителей компьютеров, а именно: выбрать в качестве руководителя проекта кого-то, имеющего практический опыт работы в более раннем аналогичном проекте: если более ранний проект был решен с помощью преднаучных методов, то это может произойти и с новым проектом, даже если соответствующая теория уже доступна.
Вторым следствием такого положения вещей является то, что одной из наиболее важных способностей разработчика программного обеспечения, стоящей перед новой задачей, является способность судить, достаточно ли существующей теории и здравого смысла, или нужна какая-то новая интеллектуальная дисциплина, которую нужно разрабатывать в первую очередь. В последнем случае важно не начинать кодирование до того, как появится необходимый фрагмент теории. Сначала подумай! Я вернусь к этой теме позже, учитывая её последствия для управления.
* * *
Позвольте мне теперь попытаться дать вам, по аналогии и на примере, необходимый образ мышления.
Поскольку IBM украла термин «структурированное программирование», я больше им не пользуюсь, но я читал лекции на эту тему в конце шестидесятых в MIT. Ключевым моментом моего сообщения было то, что (большие) программы были объектами, не имеющими прецедента в нашей истории культуры, и что наиболее близким аналогом, о котором я мог подумать, была математическая теория. И я проиллюстрировал это на аналогии между леммой и подпрограммой: лемма доказывается независимо от того, как она будет использоваться, и используется независимо от того, как она была доказана; аналогично подпрограмма реализуется независимо от того, как она будет использоваться, и используется независимо от того, как она была реализована. Оба были примерами «разделяй и властвуй»: математический аргумент разбит на части в теоремах и леммах, программа аналогично разбита на процессы, подпрограммы, кластеры и т.д.
Между тем я знаю, что аналогия распространяется на способы, которыми развиваются математические теории и программы. Я недавно услышал, что Дана С. Скотт описала разработку математической теории как экспериментальную науку, экспериментальную в том смысле, что адекватность и полезность новых обозначений и концепций определялись экспериментально, а именно: при попытках их использовать. Теперь это очень похоже на то, как команда разработчиков пытается справиться с концептуальными проблемами, с которыми она сталкивается.
Когда проект завершён, нужно уметь говорить об этом осмысленно, но окончательный дизайн вполне может быть чем-то вроде структуры, о которой раньше не говорили. Поэтому команда разработчиков должна придумать свой собственный язык, чтобы говорить об этом, она должна открыть для себя проясняющие дело концепции и придумать для них хорошие имена. Но они не могут ждать, чтобы сделать это, пока проект не будет завершен, потому что ему нужен язык в процессе проектирования! Это старая проблема курицы и яйца. Я знаю только один способ избежать этой бесконечной регрессии: придумать язык, который вам нужен в некоторой степени, где вы не совсем уверены, и проверить его адекватность, пытаясь использовать его, поскольку при использовании новые слова будут получать свои значения.
Позвольте привести один пример. В первой половине шестидесятых годов я разработал (как часть мультипрограммной системы) подсистему, функция которой заключалась в том, чтобы абстрагироваться от разницы между первичным и вторичным хранилищем: единицу, в которой информация должна была перетасовываться между уровнями хранения, называли «страницей». Когда мы изучали нашу первую проектировку, оказалось, что мы можем рассматривать это только в качестве первого приближения, поскольку соображения эффективности заставили нас присвоить подмножеству страниц в первичном хранилище особый статус. Мы назвали их «святыми страницами», идея в том, что, если священная страница в первичном хранилище гарантирована, доступ к ним можно ускорить. Это была хорошая идея? Мы должны были определить «священные страницы» таким образом, чтобы мы могли доказать, что их число будет ограничено. В конце концов мы пришли к очень точному определению, какие страницы будут "святыми", которые удовлетворяли бы всем нашим требованиям логики и эффективности, но во время всех этих обсуждений понятие «святой» медленно развивалось в нечто точное и полезное. Первоначально, например, я помню, что «святость» была логическим атрибутом: страница была "священной" или нет. В конечном итоге у страниц появился «счетчик святости», и первоначальный логический атрибут стал вопросом, был ли "счетчик святости" положительным или нет, страница была "священной" или нет.
Если бы во время этих обсуждений незнакомец вошел бы в нашу комнату и слушал нас в течение пятнадцати минут, он сделал бы замечание «Я не верю, что вы знаете, о чём говорите». Наш ответ был бы: «Да, вы правы, и именно поэтому мы говорим: мы пытаемся выяснить, о чём именно мы должны говорить».
Я описал эту сцену довольно подробно, потому что я её очень хорошо помню и потому, что считаю её довольно типичной. В конце концов, вы придёте к очень формальному и чётко определённому продукту, но этому возможному рождению предшествует период беременности, в течение которого новые идеи испытываются, отбрасываются или развиваются. Это единственный известный мне способ, при котором разум может справиться с такими концептуальными проблемами. Из опыта я узнал, что в тот период беременности, когда должен быть создан новый жаргон, абсолютное владение родным языком является абсолютным требованием для всех участников. Программист, который говорит небрежно, это просто катастрофа. Отличное владение родным языком — мой первый критерий отбора для будущего программиста; хороший вкус в математике является вторым важным критерием. (Если повезет, они часто идут рука об руку).
У меня была третья причина для описания рождения понятия «святой» в некоторой степени. Несколько лет назад я узнал, что это не просто романтика, не просто приятное воспоминание о проекте, который нам всем понравился: наш опыт лежал в основе этого вопроса. Я узнал об этом, когда хотел (в качестве упражнения для себя) дать полную формальную разработку рекурсивного синтаксического анализатора для простого языка программирования, определённого в терминах примерно пяти или шести синтаксических категорий. Единственным способом, которым я смог достичь правильного формального подхода, было введение новых синтаксических категорий! Эти новые синтаксические категории характеризуют символьные последовательности, которые в исходном языке программирования бессмысленны для анализа, но необходимы для понимания и обоснования алгоритма синтаксического анализа в разработке. Мое формальное упражнение было очень полезным, не потому, что оно дало хороший синтаксический анализатор, а потому, что в хорошей, формальной словесной форме оно продемонстрировало необходимость в разработке программного обеспечения, которую требует изобретение: новые синтаксические категории были образцовыми для понятий, которые должны быть изобретёнными до конца, понятия, которые не имеют смысла по отношению к первоначальной постановке задачи, но необходимы для понимания решения.
* * *
Я надеюсь, что вышесказанное дает вам некоторое представление о задаче программиста. Имея дело с проблемами разработки программного обеспечения, я также должен посвятить слово или два феномену плохого управления при разработке программного обеспечения. Это прискорбно, но плохие управленцы в этой области существуют, и, хотя они и плохие, у них достаточно сил, чтобы разрушить проект. Я читал лекции по всему миру программистам, работающим в самых разных организациях, и у меня сложилось сильное впечатление, что плохой управленец — это почти повсеместное явление. Одна из самых распространённых реакций аудитории в дискуссии после лекции: «Как жаль, что нашего менеджера здесь нет! Мы не можем объяснить ему это, но от вас он, возможно, принял бы это. Мы хотели бы работать так, как вы описали, но наш менеджер, который этого не понимает, не позволит нам". Я сталкивался с этой реакцией так часто, что могу только сделать вывод, что в среднем ситуация действительно плохая. (У меня был худший опыт работы в банке, и некоторые правительственные организации были не лучше).
В связи с плохими менеджерами я часто описывал свой опыт работы в качестве лектора в IBM, потому что он был таким ярким. Незадолго до того, как я пришел, оформитель интерьера переделал аудиторию, и тем самым заменил старомодную доску на экран и проектор. В результате мне пришлось выступать в тускло освещённой комнате с моими солнцезащитными очками, чтобы не ослепнуть полностью. Я мог просто видеть людей в первых рядах.
Эта лекция была одним из самых ужасных событий в моей жизни. С помощью нескольких удачно выбранных примеров я проиллюстрировал методы решения проблем, которые я мог сформулировать в то время, показал, с одной стороны, свободу разработчика, а с другой — формальную дисциплину, необходимую для её контроля. Но видимая аудитория была абсолютно безразлична: мне казалось, что я обращаюсь к аудитории марионеток, сделанных из жевательной резинки. Это было для меня пыткой, но я знал, что это была хорошая лекция, и с упрямой решимостью я делал свою работу до конца.
Когда я закончил и включили свет, я был удивлён громкими аплодисментами... из невидимых задних рядов! Затем оказалось, что у меня была очень смешанная аудитория, восхищенные программисты в задних рядах и в первых рядах их руководители, которые были крайне раздражены моей работой: открыто отображая количество «изобретений», я представил задачу программирования ещё более «неуправляемой», чем они уже опасались. С их точки зрения, я сделал очень плохую работу. Именно тогда я сформулировал для себя вывод, что плохие руководители рассматривают программирование в первую очередь как проблему управления, потому что они не знают, как им управлять.
Эти проблемы менее распространены в тех организациях (я знаю несколько программных компаний), где руководство состоит из компетентных, опытных программистов (а не банкира с колониальным опытом, но всё ещё слишком молодого, чтобы уйти на пенсию). Одна из проблем, вызванных непонимающим руководителем, заключается в том, что он считает, что его подчиненные должны создавать код: они должны решать проблемы, и для этого они должны использовать код. По сей день у нас есть организации, которые измеряют «производительность программистов» по «количеству строк кода, производимых в месяц»; это число действительно может быть подсчитано, но они записывают его не с той стороны бухгалтерской книги, так как мы должны говорить о «количестве потраченных строк кода».
Фактическое кодирование требует большой осторожности и безошибочного таланта для точности; это трудоёмкий процесс, и поэтому его следует отложить до тех пор, пока вы не будете уверены в том, что программа, которую вы собираетесь кодировать, действительно является программой, к которой вы стремитесь. Я знаю одну очень успешную фирму по разработке программного обеспечения, в которой, как правило, принято, что для одногодичного проекта кодирование не разрешается начинать до девятого месяца! В этой организации они знают, что конечный код — не более чем залог вашего понимания. Когда я сказал их директору, что моей главной задачей при обучении студентов информатике было научить их думать в первую очередь, а не торопиться с программированием, он просто сказал: «Если вам это удастся, вы на вес золота». (Я не очень тяжёлый).
Но, очевидно, многие управленцы создают хаос, препятствуя мышлению и побуждая своих подчиненных «производить» код. Позже они жалуются на то, что 80 процентов их рабочей силы связаны с «обслуживанием программ», и винят в этом программную технологию, а не самих себя. Это уж слишком для плохого руководителя в сфере программного обеспечения. (Все это хорошо известно, но время от времени нужно повторять).
* * *
Другое глубокое различие между мирами аппаратного и программного обеспечения представлено различными ролями тестирования.
Когда 25 лет назад разработчик логики приготовил схему, его следующие действия заключались в том, чтобы построить и испытать её, а если она не сработала, он бы исследовал несколько сигналов своим осциллографом и настроил конденсатор. И когда она работала, он менял напряжения от источника питания 10-процентным колебаниям, настраивал и т.д., пока у него не было схемы, которая работала бы правильно во всем диапазоне условий, к которым он стремился. Он сделал продукт, из которого он мог «видеть, что он работал во всем диапазоне». Конечно, он не пробовал это для «всех» точек диапазона, но в этом не было необходимости, поскольку из общих соображений непрерывности стало ясно, что достаточно было проверить схему в очень ограниченном числе условий, вместе «охватывающих» весь ассортимент.
Этот итеративный процесс разработки методом проб и ошибок воспринимался настолько само собой разумеющимся, что он также был принят в обстоятельствах, в которых предположение о непрерывности, которое оправдывает всю процедуру, является недействительным. В случае стуктуры с дискретным «пространством производительности», такой как программа, допущение непрерывности является недопустимым, и в результате итеративный процесс проектирования методом проб и ошибок, следовательно, принципиально неадекватен. Хороший разработчик программного обеспечения знает это; он знает из наблюдения, что если в рассмотренных делах его программа дала правильный результат, то он не может экстраполировать, что его программа в порядке; поэтому он пытается математически доказать, что его программа соответствует требованиям.
Простое предположение о существовании среды, в которой традиционный процесс разработки метода проб и ошибок неадекватен и где, следовательно, требуется математическое доказательство, неприятно для тех, для кого математические доказательства находятся за пределами их умственного понимания. В результате предложение встретило значительное сопротивление, даже среди программистов, которые должны знать лучше. Не удивительно, что в мире аппаратного обеспечения признание потенциальной неадекватности процедуры тестирования всё ещё очень редко.
Некоторые разработчики аппаратного обеспечения начинают беспокоиться, но, как правило, не потому, что осознают фундаментальную неадекватность подхода к тестированию, а только потому, что «настройка» стала настолько дорогой с момента появления технологии LSI. Но даже без этого финансового аспекта они уже должны волноваться, потому что в то же время значительная часть их проектной деятельности происходит в дискретной среде.
Недавно я услышал историю о машине (это не о дизайне машины Берроуза, к счастью). Это была многопроцессорная установка, которая была ускорена добавлением подчиненного хранилища, но ее разработчики сделали это дополнение плохо: когда два процессора работали одновременно на одном и том же слове, машина с зависимым хранилищем реагировала иначе, чем версия без этого. После нескольких месяцев эксплуатации произошёл сбой системы, вызванный именно этой ошибкой проектирования. Тестируя, вы просто не можете надеяться обнаружить такую ошибку, которая становится очевидной по совпадению. Очевидно, что эта машина была разработана людьми, которые не имели ни малейшего представления о программировании. Один компетентный программист из этой команды разработчиков предотвратил бы эту ошибку: как только вы усложняете проектирование многопроцессорной установки введением дополнительного хранилища, обязательство доказать (вместо того, чтобы просто верить без убедительных доказательств), что после введения зависимого хранилища машина всё ещё соответствует своей первоначальной функциональной спецификации, это очевидно для компетентного программиста. (Такое доказательство, по-видимому, также не представляет каких-либо фундаментальных или практических трудностей). Убедить разработчиков оборудования в том, что они перешли в среду, в которой их традиционные экспериментальные методы проектирования и контроля качества больше не являются адекватными, является одной из основных проблем обучения в этой области.
Я назвал это «основным», потому что пока оно не выполнено, разработчики оборудования не поймут, за что отвечает разработчик программного обеспечения. В традиционных инженерных традициях завершённый проект является законченным продуктом разработчика: вы создаете структуру и, о чудо, она работает! Если вы не верите этому, просто попробуйте, и вы увидите, что «это работает». В случае стуктуры с дискретным пространством исполнения единственной подходящей реакцией на наблюдение, при котором она «сработала» в рассматриваемом случае, является: «И что?». Единственное убедительное доказательство того, что такое устройство с дискретным рабочим пространством соответствует его требованиям, включает математическое доказательство. Серьезная ошибка — думать, что продукты программиста — это программы, которые он пишет; программист должен выдвигать заслуживающие доверия решения, и он должен производить и представлять их в форме убедительных аргументов. Эти аргументы составляют твердое ядро его продукта, и письменный текст программы является только сопроводительным материалом, к которому применимы его аргументы.
* * *
Многие программные проекты, выполненные в прошлом, были слишком сложными и, следовательно, полны ошибок и исправлений. Главным образом следующие два обстоятельства были ответственны за это:
- резкое увеличение скорости процессора и объема памяти, из-за чего казалось, что мы ограничены только небесами; только после создания ряда катастрофически сложных систем нам стало ясно, что наши ограниченные мыслительные способности стали узким местом;
- мир, который в своем стремлении применить эти замечательные новые машины стал чрезмерно амбициозным; многие программисты поддались давлению, чтобы расширить свою доступную технологию программирования за её пределы; это не было очень научным поведением, но, возможно, выход за пределы был необходим для определения позиции этого предела.
Оглядываясь назад, мы можем добавить две другие причины: из-за недостатка опыта программисты не знали, насколько вредна сложность, и, во-вторых, они также не знали, какой сложности обычно можно избежать, если хорошо подумать. Возможно, это помогло бы, если бы аналогия между разработкой программного обеспечения и математической теорией была широко признана ранее, потому что всем известно, что даже для одной теоремы первое обнаруженное доказательство редко бывает лучшим: более поздние доказательства часто на несколько порядков проще.
Когда Ч.Э.Р. Хоар пишет (как он делал это в начале этого года) «... порог моей терпимости к сложности намного ниже, чем был раньше», он отражает двойственное развитие: более глубокое осознание опасности сложности, но также повышенный стандарт элегантности. Осознание опасности сложности сделало большую простоту похвальной целью, но сначала это был полностью открытый вопрос, может ли эта цель быть достигнута. Некоторые проблемы могут не соответствовать элегантным решениям, но, как представляется, существует огромное количество доказательств того, что многое из того, что было сделано в программировании (и в вычислительной технике в целом), может быть существенно упрощено. Многочисленные истории о 30-строчных решениях, придуманных так называемым профессиональным программистом (или даже учителем программирования!) могут быть сведены к программе из 4 или 5 строк.
Обучить поколение программистов с гораздо более низким порогом терпимости к сложности и научить их искать действительно простое решение — это вторая важная интеллектуальная задача в нашей области. Это технически сложно, потому что вам нужно привить некоторые из управленческих способностей и хороший вкус математика. Это психологически тяжело в среде, которая путает любовь к совершенству с претензией на совершенство и, обвиняя вас в первом, обвиняет вас и в последнем.
Как мы можем убедить людей в том, что в программировании простота и ясность, короче говоря, то, что математики называют «элегантностью», — это не излишняя роскошь, а решающий вопрос, который определяет успех или провал? Я ожидаю помощи из экономических соображений. В противоположность ситуации с аппаратным обеспечением, где повышение надёжности обычно приходится оплачивать более высокой ценой, в случае программного обеспечения ненадёжность является самым большим фактором, влияющим на увеличение стоимости. Это может показаться парадоксальным, но надёжная (и, следовательно, простая) программа намного дешевле в разработке и использовании, чем (сложная и, следовательно, ненадёжная). Этот «парадокс» должен заставить нас не придавать слишком большой вес возможной аналогии между разработкой программного обеспечения и более традиционными инженерными дисциплинами.
Plataanstraat 5
5671 AL Nuenen
Нидерланды проф.др.Эдсгер В.Дейкстра
Научный сотрудник из компании "Burrought"
