|
||||
|
Глава 19 «Мифический человеко-месяц» двадцать лет
Для чего понадобилось юбилейное двадцатое издание? Самолет гудел в ночи, направляясь к Лагардии. Облака и сумрак скрыли все интересное для глаза. Документ, который я читал, был неинтересным. Однако мне не было скучно. Сидящий рядом попутчик читал «Мифический человеко-месяц», и я ожидал, когда словом или жестом он выдаст свое впечатление. В конце концов, когда мы уже выруливали к выходу, я не выдержал: — Как вам эта книга? Советуете прочесть? — Хм, в ней нет ничего, чего я не знал бы раньше. Я решил не представляться. Почему «Мифический человеко-месяц» выжил? Почему с ним до сих пор считаются в современной практике программирования? Почему его читательская аудитория выходит за пределы сообщества программистов-разработчиков, а книга порождает статьи, цитаты и письма не только разработчиков программ, но и юристов, врачей, психологов, социологов? Каким образом книга, написанная 20 лет назад об опыте разработки программ, имевшем место 30 лет назад, может до сих пор быть актуальной и даже полезной? Согласно одному из объяснений, которые можно услышать, разработка программного обеспечения как дисциплина не получила нормального и правильного развития. В поддержку этой точки зрения часто указывают на несоответствие роста производительности труда программистов и эффективности производства компьютеров, выросшей в тысячи раз за последние два десятилетия. Как объясняется в главе 16, аномалия состоит не в замедленном развитии программирования, а в беспрецедентном в истории человечества взрыве компьютерных технологий. В целом, причина этого в постепенном переходе производства компьютеров из сборочного производства в обрабатывающее, из трудоемкого производства в капиталоемкое. Разработка же аппаратного и программного обеспечения, в отличие от производства, остается по своей сути трудоемкой. Второе часто выдвигаемое объяснение гласит, что «Мифический человеко-месяц» лишь случайно касается разработки программного обеспечения, а в основном он написан о групповой разработке чего бы то ни было. Доля правды в этом есть. В предисловии к изданию 1975 года сказано, что управление программным проектом имеет больше сходства с любым другим управлением, чем изначально считается большинством программистов. Я до сих пор так считаю. История человечества — это пьеса, в которой сюжеты постоянны, сценарии медленно меняются с развитием культуры, а декорации меняются непрерывно. Поэтому в ХХ веке мы узнаем себя в Шекспире, Гомере и Библии. Поэтому в той мере, в какой «МЧ-М» написан о людях, он устаревает медленно. Каковы бы ни были причины, книгу продолжают покупать и присылают мне замечания, которые я ценю. Меня часто спрашивают: «Как вы считаете, в чем вы тогда ошиблись? Что устарело в наши дни? Что действительно новое появилось в мире разработки программ?» Эти четкие вопросы вполне законны, и я постараюсь ответить на них. Не в таком, правда, порядке, но по группам тем. Прежде всего, посмотрим, что было верным в момент написания и осталось таковым до сих пор. Центральный аргумент: концептуальная целостность и архитектор Концептуальная целостность. Чистый и элегантный программный продукт должен представить своим пользователям согласованную идеальную модель приложения, стратегий осуществления приложения и тактики пользовательских интерфейсов, используемой при задании действий и параметров. Концептуальная целостность продукта в восприятии пользователя является важнейшим фактором, влияющим на простоту использования. (Есть, конечно, и другие факторы. Важным примером является единообразие пользовательского интерфейса в приложениях для Macintosh. Более того, можно создать согласованные интерфейсы, являющиеся тем не менее, совершенно неуклюжими. Например MS-DOS.) Есть многочисленные примеры элегантных программных продуктов, созданных одним или двумя людьми. Так делается большая часть чисто интеллектуальных продуктов, таких как книги или музыкальные произведения. Однако во многих промышленных областях процессы разработки продукта не могут осуществляться на основе столь простого подхода к концептуальной целостности. Конкуренция вынуждает к спешке. Во многих современных технологиях конечный продукт обладает большой сложностью, и проектирование неизбежно требует многих человеко-месяцев труда. Для программных продуктов характерны как сложность, так и напряженность графика, обусловленная конкуренцией. Таким образом, всякий достаточно большой или срочный продукт, требующий усилий многих людей, сталкивается со специфической трудностью: результат должен концептуально согласовываться с разумом одиночного пользователя и в то же время проектироваться усилиями нескольких разумов. Как организовать проектирование, чтобы достичь такой концептуальной целостности? Это центральный вопрос «МЧ-М». Один из его тезисов гласит, что существуют качественные различия между управлением большими и маленькими программными проектами — лишь в силу числа работающих над ними голов. Для достижения согласованности необходимы обдуманные и даже героические действия. Архитектор. С четвертой по шестую главу я доказываю, что самое важное — назначить одного человека архитектором продукта, ответственным за все его стороны, воспринимаемые пользователем. Архитектор формирует и имеет в своем владении общедоступную идеальную модель продукта, с помощью которой пользователю будет объяснено его применение. В ее состав входит подробное указание всех его функций и средств вызова и управления. Архитектор также действует в интересах пользователя при поиске компромисса между функциями, техническим характеристиками, размером, стоимостью и выполнением графика работ. Выполнение этой задачи требует полной занятости, и только в очень маленьких группах может быть совмещено с должностью руководителя. Архитектора можно сравнивать с режиссером, а менеджера — с продюсером кинокартины. Отделение архитектуры от разработки и реализации. Чтобы сделать возможным осуществление архитектором своей главной задачи, необходимо отделить архитектуру, т.е. определение продукта в восприятии пользователя, от его разработки. Архитектура и разработка определяют четкую грань между разными частями задачи проектирования, и по каждую сторону этой грани лежит большая работа. Рекурсивность архитектуры. В очень больших проектах одному человеку не справиться со всей архитектурой, даже если он избавлен от всех забот, связанных с разработкой. Поэтому главный архитектор системы должен разбить целое на подсистемы. Границы подсистем должны быть проведены так, чтобы интерфейсы между ними были минимальны и легче всего строго определяемы. Тогда у каждой части может быть свой архитектор, подчиняющийся главному архитектору системы в отношении архитектуры. Очевидно, при необходимости этот процесс может быть продолжен рекурсивно. Сегодня я убежден более чем когда-либо. Концептуальная целостность является важнейшим условием качества продукта. Наличие системного архитектора есть важнейший шаг в направлении концептуальной целостности. Эти принципы ни в коей мере не ограничиваются разработкой программного обеспечения, а справедливы при проектировании любой сложной конструкции, будь то компьютер, самолет, стратегическая оборонная инициатива или система глобальной навигации. После преподавания в более чем 20 лабораториях разработки программного обеспечения я стал настаивать, чтобы группы учащихся, даже из четырех человек, выбирали менеджера и отдельно — архитектора. Разделение функций в таких маленьких группах может показаться несколько чрезмерным требованием, но, по моим наблюдениям, это оправдано и способствует достижению успеха. Эффект второй системы: функциональность и угадывание частоты Проектирование для больших групп пользователей. Одним из последствий революции, произведенной персональными компьютерами, является все возрастающее, по крайней мере в области обработки деловых данных, вытеснение заказных программ коробочными программными пакетами. Более того, стандартные программные пакеты продаются сотнями тысяч и даже миллионами экземпляров. Системные архитекторы программ, поставляемых вместе с машиной, всегда должны были создавать проект, ориентированный на большую аморфную массу пользователей, а не на отдельное определенное приложение в одной компании. Теперь такая задача встает перед очень многими архитекторами. Парадокс состоит в том, что спроектировать инструмент общего назначения, нежели специализированный, гораздо труднее именно потому, что нужно придать вес различающимся потребностям разных пользователей. В погоне за функциональностью. Архитектор инструмента общего назначения, такого, например, как электронная таблица или текстовый редактор, подвержен сильному соблазну перегрузить продукт функциями предельной полезности ценой снижения производительности и даже простоты использования. Вначале привлекательность предлагаемых возможностей кажется очевидной. Расплата производительностью становится очевидной лишь при системном тестировании. Утрата простоты использования коварно подкрадывается по мере того, как небольшими порциями добавляются новые функции, а руководства пользователя все более разбухают.[1] Соблазн особенно велик в отношении долгоживущих массовых продуктов, развивавшихся на протяжении ряда поколений. Миллионы покупателей требуют сотен новых возможностей. Всякая просьба свидетельствует о наличии спроса на рынке. Часто архитектор первоначальной системы уже ушел в поход за новой славой, и архитектура оказалась в руках людей с меньшим опытом взвешенного представления общих интересов пользователей. В недавней рецензии на Microsoft Word 6.0 сказано: «Переполнен возможностями; обновление замедлено перегруженностью… Кроме того, Word 6.0 занимает много места и медленно работает.» С неудовольствием отмечается, что Word 6.0 занимает 4 Мбайт памяти и сообщается, что из-за богатых дополнительных функциональных возможностей «даже Macintosh IIfx едва пригоден для выполнения Word 6».[2] Определение группы пользователей. Чем крупнее и аморфнее группа предполагаемых пользователей, тем более необходимо явно ее определить, если вы намерены достичь концептуальной целостности. У каждого члена группы проектировщиков наверняка есть неявный мысленный образ пользователя, и все образы будут отличаться друг от друга. Поскольку представление архитектора о пользователе явно или подсознательно оказывает влияние на все архитектурные решения, важно, чтобы команда проектировщиков пришла к единому общему образу. Для этого необходимо составить список признаков предполагаемых пользователей, указав в нем: • кто они такие, • что им нужно, • что, по их мнению, им нужно, • чего они хотят. Частоты. Для любого программного продукта каждая характеристика пользователя представляет собой распределение со множеством возможных значений и соответствующими частотами. Как архитектору получить эти частоты? Изучение этой слабо очерченной популяции представляется сомнительным и дорогостоящим занятием.[3]С годами я пришел к убеждению, что архитектор должен угадать или, если вам больше нравится, постулировать полный набор признаков и значений вместе с частотами для создания полного, явного и общего для всех описания группы пользователей. Такая непривлекательная процедура имеет ряд полезных последствий. Во-первых, при стремлении точно угадать частоты архитектор вынужден очень тщательно обдумать, какова возможная группа пользователей. Во-вторых, при фиксации частот возникает обсуждение, полезное для всех участников и выявляющее различия в образах пользователя, имеющихся у разных проектировщиков. В-третьих, явное присвоение частот содействуют пониманию того, какие решения какими свойствами группы пользователей обусловлены. Даже такой неформальный анализ чувствительности приносит пользу. Когда обнаруживается, что очень важные решения зависят от некоторых специфических предположений, оказывается уместным получить более точные численные оценки. (Разработанная Джеффом Конклином (Jeff Conklin) система позволяет формально и точно прослеживать принятие проектных решений и документировать их основания.[4]Мне не приходилось ею пользоваться, но думаю, что она должна быть очень полезна.) Подводя итоги: установите предположительные признаки группы пользователей. Гораздо лучше ошибаться, но выражаться ясно, чем выражаться туманно. Как насчет эффекта второй системы? Один наблюдательный ученый заметил, что «Мифический человеко-месяц» рекомендовал на случай неудачи для всякой новой системы планировать поставку второй версии (см. глава 11), которая в главе 5 характеризуется как таящая наибольшие опасности. Я вынужден был признать, что он меня «поймал». Противоречие скорее лингвистическое, чем реальное. «Вторая» система, описываемая в главе 5, — это вторая система, выпускаемая в развитие предыдущей с привлечением дополнительных функций и украшений. «Вторая» система в главе 11 — это вторая попытка разработки первой выпускаемой системы. Она разрабатывается в условиях всех ограничений, накладываемых графиком, способностями и неведением, характерными для новых проектов — ограничений, навязывающих дисциплину умеренности. Триумф интерфейса WIMP Одним из наиболее впечатляющих явлений в программировании за последние двадцать лет был триумф интерфейса, состоящего из окон, значков, меню и указателей (Windows, Icons, Menus, Pointers — WIMP). Сегодня он настолько широко известен, что не требует описания. Впервые эту идею представили публике Дуг Энглебарт (Doug Englebart) с группой коллег из Стэндфордского научно-исследовательского института на Объединенной компьютерной конференции Запада в 1968 году.[5]Оттуда идеи перекочевали в исследовательский центр Xerox в Пало-Альто, где они реализовались на персональной рабочей станции Alto, разработанной Бобом Тейлором (Bob Taylor) с сотрудниками. Их подхватил Стив Джобс для компьютера Apple Lisa — слишком медленного для осуществления своих восхитительных концепций простоты использования. Эти концепции Джобс затем воплотил в коммерчески успешном Apple Macintosh в 1985 году. Позднее они были приняты в Microsoft Windows для IBM PC и его клонов. Мой пример будет базироваться на версии для Мака.[6] Концептуальная целостность через метафору. WIMP является отличным примером пользовательского интерфейса, обладающего концептуальной целостностью, достигаемой принятием знакомой идеальной модели — метафоры рабочего стола, и ее тщательного последовательного развития для использования воплощения в компьютерной графике. Например, из принятой метафоры непосредственно следует сложно осуществимое, но правильное решение о перекрытии окон вместо расположения их одно рядом с другим. Возможность менять размер и форму окон является последовательным расширением, дающим пользователю новые возможности, обеспечиваемые носителем — компьютерной графикой. У реальных бумаг на столе нельзя так же легко менять размер и форму. Буксировка непосредственно вытекает из метафоры; выбор значков с помощью курсора является прямой аналогией захвата предметов рукой. Значки и вложенные папки являются точными аналогами документов на столе, как и мусорная корзина. Идеи вырезания, копирования и вставки точно имитируют операции, которые мы обычно осуществляем с документами на столе. Следование метафоре столь буквально, а развитие настолько последовательно, что пользователей-новичков решительно коробит, когда перетаскивание значка дискеты в мусорную корзину приводит к извлечению дискеты из дисковода. Если бы интерфейс не был столь единообразно последовательным, эта (довольно неприятная) непоследовательность так бы не раздражала. В каких местах интерфейс WIMP вынужден далеко отойти от метафоры рабочего стола? Наиболее заметны два отличия: меню и работа одной рукой. На реальном рабочем столе с документами осуществляют действия, а не приказывают кому-то или чему-то осуществить их. А когда кому-то дается указание совершить действие, команда обычно не выбирается из списка, а письменно или устно подается в виде глагола в повелительном наклонении: «пожалуйста, подшейте это в папку», «пожалуйста, найдите предыдущие письма» или «пожалуйста, передайте это Мэри для принятия мер». К сожалению, надежная интерпретация команд в свободном формате на английском языке, будь они в устном или письменном виде, находится за пределами наших сегодняшних возможностей. Поэтому проектировщики интерфейса на два шага отошли от непосредственных действий пользователя с документами. Они мудро взяли имевшийся на обычном рабочем столе образец выбора команд — отпечатанную «сопроводиловку», в которой пользователь производит выбор из ограниченного меню команд со стандартной семантикой. Эту идею они превратили в горизонтальное меню с вертикально опускающимися подменю. Подача команд и проблема двух курсоров. Команды являются повелительными предложениями, в них всегда есть и обычно имеется прямое дополнение. Для любого действия нужно задать глагол и существительное. Метафора указания говорит, что для одновременного задания двух предметов нужно иметь на экране два разных курсора, управляемых своими мышами, одной — в правой руке, другой — в левой. В конце концов, на физическом столе мы обычно работаем двумя руками. (Однако одна рука часто придерживает вещи на месте, что на компьютерном рабочем столе происходит по умолчанию.) Мозг, конечно, приспособлен к действиям двумя руками: мы систематически используем две руки при вводе с клавиатуры, езде на автомобиле, приготовлении пищи. Увы, и одна мышь была большим достижением для изготовителей компьютеров. Коммерческих систем, поддерживающих одновременные действия с двумя курсорами мышей, по одному для каждой руки, нет.[7] Разработчики интерфейса смирились с реалиями и сделали проект для одной мыши, приняв синтаксическое соглашение, что первым отмечается (выбирается) существительное. Затем указывают на глагол, пункт меню. При этом в значительной мере утрачивается простота использования. Когда я наблюдаю за пользователями, просматриваю видеозапись их действий или зарегистрированные компьютером перемещения курсора, то всегда обращаю внимание на то, что одному курсору приходится выполнять работу двух: выбрать объект в окне на рабочем столе; выбрать глагол в меню; найти другой объект или вновь отыскать прежний; снова опустить меню (часто, то же самое) и выбрать глагол. Курсор мечется взад-вперед, от пространства данных к пространству меню, всякий раз теряя полезную информацию о том, где он находился в этом пространстве в прошлый раз — в целом, неэффективный процесс. Великолепное решение. Даже если бы электроника и программы могли без труда работать одновременно с двумя активными курсорами, остаются сложности с топологией пространства. На рабочем столе в метафоре WIMP в действительности есть пишущая машинка, и в физическом пространстве реального стола необходимо поместить реальную клавиатуру. Клавиатура плюс два коврика для мышей займут немалую часть пространства в пределах досягаемости рук. Так почему бы проблему клавиатуры не обратить себе на пользу, почему не использовать обе руки — одной рукой задавая на клавиатуре глаголы, а другой рукой выбирая существительные с помощью мыши? Теперь курсор будет оставаться в пространстве данных и пользоваться тем, что последовательные существительные выбираются близко одно от другого. Реальная эффективность, реально большие возможности пользователя. Мощность функций или простота использования. Однако при таком решении теряется то, что делает использование меню таким простым для новичков: меню представляет список альтернативных глаголов, допустимых в каждом конкретном состоянии. Можно купить коробку, принести ее домой и начать работать, не читаю инструкцию, зная лишь, для чего она куплена и экспериментируя с различными глаголами в меню. Одна из сложнейших задач, стоящих перед архитекторами — это найти соотношение между мощностью функций и простотой использования. Нужно ли проектировать программу в расчете на новичка и случайного пользователя или строить ее с мощными функциями для профессионала? Идеальное решение – обеспечить и то, и другое концептуально согласованным образом, что достигается при помощи интерфейса WIMP. У часто используемых глаголов меню есть клавишные эквиваленты из одной клавиши + командной клавиши, которые обычно легко ввести левой рукой одним аккордом. Например, в Маке командная клавиша () находится как раз под клавишами Z и X, поэтому самые частые действия кодируются как Постепенный переход от новичка к опытному пользователю. Такая двойная система задания командных глаголов не только отвечает потребности новичка в легком обучении и потребности опытного пользователя в эффективном использовании, но и позволяет каждому пользователю плавно перейти из одного режима в другой. Буквенные обозначения, называемые клавишами сокращенного набора, показываются в меню рядом с глаголами, поэтому в случае неуверенности пользователь может раскрыть меню, чтобы проверить буквенный эквивалент, вместо выбора пункта меню. Каждый новичок запоминает сначала сокращенный набор для своих частых операций. Он может попробовать любое сокращение, в котором не уверен, поскольку отменяет любое ошибочное одиночное действие. С другой стороны, он может справиться в меню относительно допустимых команд. Новички очень часто опускают меню, опытные пользователи — редко, а тем, которые находятся посередине, лишь от случая к случаю понадобится выбирать из меню, поскольку они уже знают клавиши, которые вызывают большинство осуществляемых ими операций. Мы, проектировщики программного обеспечения, слишком привыкли к этому интерфейсу, чтобы оценить его элегантность и мощь. Успех прямого включения как средства навязывания архитектуры. Интерфейс Мака примечателен еще в одном отношении. Без всякого принуждения разработчики сделали его стандартом для разных приложений, включая большинство из тех, которые описаны сторонними организациями. Поэтому пользователь приобретает концептуальную согласованность на уровне интерфейса не только для программ, поставляемых вместе с машиной, но и для всех других приложений. Этот подвиг создатели Мака осуществили, встроив интерфейс в ПЗУ, в результате чего разработчикам проще и быстрее пользоваться существующим, чем создавать свои идиосинкразические интерфейсы. Это естественное стремление к единообразию возобладало настолько широко, что стало стандартом де-факто. Естественные стремления были поддержаны полной приверженностью со стороны менеджеров и существенным принуждением со стороны Apple. Независимые рецензенты в журналах, поняв огромное значение межпрограммной концептуальной целостности, также подкрепили естественные стремления, безжалостно критикуя продукты, не удовлетворяющие этому интерфейсу. Это отличительный пример технологии, рекомендованной в главе 6 для достижения единообразия путем поощрения других сторон непосредственно включать в свои продукты имеющийся код вместо разработки новых программ согласно имеющимся спецификациям. Судьба WIMP: устаревание. Несмотря на все достоинства, по моему мнению, интерфейс WIMP через поколение станет достоянием истории. Указание курсором останется способом задания существительных при управлении нашими компьютерами. Для выражения глаголов станет использоваться речь. Такие инструменты, как Voice Navigator для Маков и Dragon для PC, уже предоставляют такую возможность. Не разрабатывайте программ на выброс, каскадная модель неверна! В главе 11 дается радикальный совет: «планируйте выбросить первую программу, вам все равно придется это сделать». Сейчас я считаю это ошибочным — не в силу чрезмерного радикализма, но в силу чрезмерной упрощенности. Самой большой ошибкой этой концепции является косвенное принятие классической последовательности — в виде каскада — модели создания программы. Эта модель происходит от структуры диаграммы Гранта для поэтапного процесса, которую часто изображают, как на рисунке 19.1. В классической статье 1970 года Винтон Ройс (Winton Royce) усовершенствовал последовательную модель путем: • добавления некоторой обратной связи с предшествующими этапами; • ограничения обратной связи только непосредственными предшественниками, чтобы исключить вызываемые ими издержки и задержки в выполнении графика. Он предвосхитил «МЧ-М», рекомендовав разработчикам «делать работу дважды»[8]. Глава 11 — не единственная, на которую повлияла каскадная модель. Она проходит через всю книгу, начиная с правила планирования в главе 2. Это практическое правило отводит 1/3 времени на планирование, 1/6 — на написание программ, 1/4 — на тестирование компонентов и 1/4 — на системное тестирование. Рис. 19.1 Каскадная модель создания программы Основное заблуждение каскадной модели состоит в предположениях, что проект проходит через весь процесс один раз, архитектура хороша и проста в использовании, проект осуществления разумен, а ошибки в реализации устраняются по мере тестирования. Иными словами, каскадная модель исходит из того, что все ошибки будут сосредоточены в реализации, а потому их устранение происходит равномерно во время тестирования компонентов и системы. «Планируйте на выброс» действительно резко нападает на это заблуждение. Ошибка не в диагнозе, а в лекарстве. Сейчас я предположил, что первую систему можно отбросить или перепроектировать не всю целиком, а по частям. Хорошо, если это так, но при этом не затрагивается корень проблемы. В каскадной модели системное тестирование, а следовательно и тестирование пользователем, отодвигается в конец процесса создания программы. Поэтому есть шанс обнаружить крайние неудобства для пользователя, или неприемлемые технические характеристики, или опасную уязвимость к ошибкам или злонамеренным действиям пользователя лишь в самом конце разработки. Изучение спецификаций при альфа-тестировании нацелено на раннее обнаружение таких ошибок, но ничто не может заменить непосредственных пользователей. Вторым недостатком каскадной модели является предположение, что система строится сразу вся целиком для тестирования с начала до конца после того, как завершены все проектные разработки, большая часть написания программ и значительная часть тестирования компонентов. К несчастью, каскадная модель, это преобладавшее в 1975 году представление о программных проектах, была включена в DOD-STD-2167 — спецификацию Министерства обороны для любого военного программного обеспечения. По этой причине она просуществовала долгое время после того, как большая часть думающих практиков осознала ее неадекватность и отказалась от нее. К счастью, в МО позднее поняли истину.[9] Необходимо двигаться против течения. Опыт и идеи из каждой расположенной ниже по течению части процесса создания программы, как энергичный лосось, должны прыгать вверх по течению, иногда сразу через несколько этапов, и воздействовать на деятельность наверху. Проектные разработки покажут, что некоторые предусмотренные архитектурой возможности ухудшают технические характеристики, и потому архитектура должна быть переработана. Программирование при реализации выявит, что некоторые функции непомерно увеличивают требования к памяти, поэтому нужно внести изменения в архитектуру и разработку. Поэтому вполне может потребоваться осуществить несколько итераций цикла архитектура-разработка, прежде чем начать какую-либо программную реализацию. Модель пошагового создания лучше: последовательное уточнение Построение каркаса с начала до конца. Гарлан Миллз (Harlan Mills), работающий в системе с разделением времени, давно уже рекомендует строить основной цикл опроса системы реального времени с вызовами подпрограмм (заглушками) для всех функций (рис. 19.2), но пустыми подпрограммами. Откомпилируйте его, протестируйте, и он будет идти цикл за циклом, буквально ничего не делая, но делая это без ошибок.[10] Рис. 19.2 На следующем шаге мы навешиваем модуль ввода (возможно, примитивный) и модуль вывода. Voila! Работающая система, делающая нечто, возможно, неинтересное. Теперь, функция за функцией, мы строим и добавляем модули. На каждом шаге мы имеем работающую систему. При достаточном трудолюбии на каждом шаге мы имеем отлаженную, протестированную систему. (По мере роста системы растет и тяжесть повторного тестирования всех новых модулей по всем прежним контрольным примерам.) После того как на примитивном уровне каждая функция работает, мы улучшаем или переписываем один модуль за другим, пошагово наращивая систему. Иногда для надежности мы переписываем исходный движущий цикл, а возможно, и его интерфейсы с модулями. Поскольку в любой момент времени у нас есть работающая система: • можно очень рано начать тестирование пользователями; • можно принять стратегию разработки в соответствии с бюджетом, полностью защищающую от перерасхода времени или средств (возможно, за счет сокращения функциональности). В течение 22 лет я преподавал в лаборатории программной инженерии Университета штата Северная Каролина, иногда вместе с Дэвидом Парнасом. На этих занятиях бригады, обычно состоявшие из четырех человек, в течение одного семестра должны были построить некоторую реальную прикладную программную систему. Примерно посередине этого срока я стал преподавать инкрементную разработку. Я был поражен, какой возбуждающий эффект на моральный дух группы оказывает первая картинка на экране, первая работающая система. Семейства Парнаса. Дэвид Парнас был главным властителем дум в программотехнике в течение всего этого 20-летнего периода. Всем известна его идея скрытия информации. Менее известна очень важная идея Парнаса о проектировании программного продукта как семейства взаимосвязанных продуктов.[11]Он требует, чтобы проектировщик имел в виду как дальнейшее развитие, так и новые версии продукта и определял их функциональные или межплатформенные различия так, чтобы строить дерево родственных продуктов (рис. 19.3). Рис. 19.3 Фокус при проектировании такого дерева состоит в том, чтобы ближе к корню поместить те решения, изменение которых наименее вероятно. Такая стратегия проектирования повышает повторную используемость модулей. Еще важнее, что ее можно расширить, включая не только поставляемые продукты, но и последовательные промежуточные версии, созданные по стратегии инкрементируемых сборок. В этом случае продукт развивается через промежуточные стадии с минимумом возврата назад. Подход Microsoft: «ежевечерняя сборка». Джеймс Маккарти (James McCarthy) описал мне процесс, использовавшийся им и другими в Microsoft. Это пошаговое наращивание, доведенное до логического конца. Он пишет: Сделав первую поставку, новые версии мы поставляем с дополнительными функциями, по сравнению с существующим работающим продуктом. Почему должен быть иным процесс первоначальной сборки? С момента достижения нами первой вехи (у первой поставки три промежуточных вехи) мы каждый вечер заново собираем разрабатываемую систему (и прогоняем контрольные примеры). Цикл сборки становится ритмом жизни проекта. Каждый вечер одна или более бригад программистов, проводящих тестирование, регистрируют модули с новыми функциями. После каждой сборки у нас есть работающая система. Если сборка оказывается неудачной, мы останавливаем весь процесс, пока ошибка не будет найдена и исправлена. В любой момент все в группе знают положение дел. Это действительно тяжело. Требуется выделение больших ресурсов, но это управляемый процесс, прослеживаемый и понятный. Он вызывает у команды доверие к себе. А доверие определяет мораль, эмоциональное состояние. Такой процесс удивляет и даже шокирует разработчиков в других организациях. Один из них говорит: «Я взял себе за правило делать сборку каждую неделю, но ежедневная сборка, я думаю, потребует слишком много труда.» И это, возможно, верно. Например, в Bell Northern Research собирают систему, состоящую из 12 миллионов строк, раз в неделю. Инкрементная сборка и быстрое макетирование. Поскольку инкрементная разработка позволяет рано начать тестирование реальными пользователями, в чем ее отличие от быстрого макетирования? Мне кажется, что они связаны, но различаются. Одним можно пользоваться без другого. Харел дает полезное определение макета: (версия программы, которая) отражает только проектные решения, принятые в процессе подготовки концептуальной модели, а не решения, вызванные соображениями реализации.[12] Можно построить макет, который вовсе не является частью продукта, развивающегося в направлении поставки. Например, можно создать макет интерфейса, за которым стоит не реально работающая программа, а лишь конечный автомат, заставляющий его имитировать прохождение состояний. Можно даже макетировать и тестировать интерфейсы методом волшебника изумрудного города, когда спрятанный человек имитирует отклик системы. Такое макетирование может быть весьма полезным для быстрого получения обратной связи от пользователя, но оно находится совершенно в стороне от тестирования продукта, который готовится к поставке. Аналогично, разработчики могут попробовать построить вертикальный срез продукта, в котором полностью реализован весьма ограниченный набор функций, чтобы заранее пролить свет на те места, где могут таиться опасности для производительности продукта. В чем состоит различие между сборкой на первой вехе в процедуре Microsoft и быстрым макетом? В функциях. Продукт с первой вехи может иметь такую ограниченную функциональность, что ни для кого не будет представлять интереса. Готовность продукта к поставке определяется завершенностью в предоставлении полезного набора функций и своим качеством, уверенностью в надежной работе. Парнас был прав, а я — нет в отношении сокрытия информации В главе 7 я противопоставляю две точки зрения на то, в какой мере каждый участник команды может иметь право или поощряться к знанию проектов и текстов программ, созданных коллегами. Во время проекта Operating System/360 мы решили, что все программисты должны видеть весь материал, т.е. у каждого программиста была рабочая тетрадь проекта, которая к концу насчитывала свыше 10000 страниц. Харлан Миллз убедительно доказывал, что «программирование должно быть открытым процессом», что предоставление всей работы на общее обозрение способствует контролю качества как благодаря давлению со стороны коллег, заставляющему работать хорошо, так и благодаря тому, что коллеги действительно находят промахи и ошибки. Этот взгляд резко противоречит мнению Дэвида Парнаса о том, что программные модули должны быть инкапсулированы, с хорошо определенными интерфейсами, а внутренность таких модулей должна быть частной собственностью программиста, невидимой снаружи. Программисты эффективнее всего работают, будучи ограждены от внутренностей чужих модулей.[13] В главе 7 я заклеймил идею Парнаса как «рецепт катастрофы». Парнас был прав, а я ошибался. Сегодня я убежден, что ограничение информации, часто осуществляемое теперь методами объектного программирования, является единственным способом поднять уровень программных разработок. Используя другие методы, можно действительно попасть в беду. Согласно методике Миллза программисты могут получить подробности семантики интерфейсов, с которыми они работают, узнав, что находится «по ту сторону». Укрывание этой семантики может быть причиной системных ошибок. С другой стороны, методика Парнаса способствует устойчивости при внесении изменений и больше подходит к стратегии проектирования, предполагающей изменения в будущем. В главе 16 утверждается следующее: • большая часть роста производительности разработки программного обеспечения обеспечена устранением второстепенных трудностей, таких как неудобные языки программирования и медленная оборачиваемость пакетной обработки; • легких решений в этом направлении практически не осталось; • радикального прогресса можно добиться, разрешив существенные сложности моделирования сложных концептуальных конструкций. Самое очевидное на этом пути — признать, что программы составляются из концептуальных блоков, значительно более крупных, чем отдельные операторы языков высокого уровня: подпрограмм, или модулей, или классов. Если мы сумеем ограничить проектирование и построение программ задачей соединения вместе и параметризации таких блоков из ранее созданных наборов, то радикально повысим концептуальный уровень и избавимся от огромного объема работ и широких возможностей для ошибок, существующих на уровне отдельных операторов. Данное Парнасом определение модулей с сокрытием информации было первым открытым шагом в этой критически важной программе исследований и идейным провозвестником объектно-ориентированного программирования. Он определил модуль как программный объект с собственной моделью данных и собственным набором операций. Доступ к его данным может быть осуществлен только через имеющиеся в нем операции. Следующий шаг явился вкладом нескольких исследователей: развитие модулей Парнаса в абстрактный тип данных, из которого можно производить много объектов. Абстрактный тип данных обеспечивает единообразный способ представления и задания интерфейсов модулей, а также дисциплину доступа, которую легко осуществлять. Третий шаг, объектно-ориентированное программирование, вводит важное понятие наследования, при котором классы (типы данных) по умолчанию имеют атрибуты своих предков в иерархии классов.[14]То, что мы рассчитываем получить от объектно-ориентированного программирования, происходит, в сущности, от первого шага, инкапсуляции модулей, плюс идея заранее подготовленных библиотек модулей или классов, спроектированных и протестированных с целью повторного использования. Многие предпочли проигнорировать тот факт, что такие модули не просто программы, а программные продукты в том смысле, который разъяснен в главе 1. Напрасно рассчитывать на успешное повторное использование модулей, не оплачивая начальные издержки на разработку качественных программных модулей: обобщенных, надежных, протестированных и документированных. Объектно-ориентированное программирование и повторное использование обсуждались в главах 16 и 17. Насколько мифичен человеко-месяц? Модель и данные Бёма В течение ряда лет были выполнены многочисленные количественные исследования производительности труда программистов и влияющих на нее факторов, особенно соотношений между обеспеченностью персоналом и графиком работ. Наиболее обстоятельное исследование сделано Барри Бёмом (Barry Boehm) на основании примерно 63 проектов, в основном в аэрокосмической области, из них около 25 – в TRW. Его работа «Экономика разработки программного обеспечения» содержит не только результаты, но и ряд полезных моделей затрат с нарастающей сложностью. Хотя несомненно, что применяемые в моделях коэффициенты различны для обычных космических программ и для программ, создаваемых в аэрокосмической области по правительственным стандартам, все же его модели подкрепляются огромным количеством данных. Я думаю, что книга будет полезным классическим трудом и через поколение. Полученные им результаты уверенно подкрепляют содержащееся в МЧ-М утверждение о том, что соотношение между численностью занятых и временем выполнения проекта далеко не линейное, что человеко-месяц действительно является мифической мерой производительности. В частности, он считает:[15] • Существует оптимальное, с точки зрения затрат, время выполнения графика для первой поставки: T = 2,5 (ЧМ)1/3. То есть оптимальное время в месяцах изменяется как кубический корень предполагаемого объема работ в человеко-месяцах — формула, полученная из оценки размера и других факторов в его модели. Следствием является кривая, дающая оптимальную численность занятых. • Кривая стоимости медленно растет, если запланированный график длиннее оптимального. Работа занимает все отведенное для нее время. • Кривая стоимости резко растет, если запланированный график короче оптимального. • Практически ни один проект невозможно завершить быстрее, чем за[3]Л расчетного оптимального графика вне зависимости от количества занятых в нем! Этот примечательный результат дает менеджеру программного проекта солидное подкрепление, когда высшее руководство требует принятия невозможного графика. Насколько верен закон Брукса? Были даже проведены тщательные исследования закона Брукса (намеренно упрощенного), согласно которому выделение дополнительных людей для отстающего графика проекта лишь задерживает его выполнение. Лучше всего это сделано Абдель-Хамидом (Abdel-Hamid) и Мадником (Madnick) в честолюбивой и ценной книге «Динамика программного проекта: интегрированный подход».[16]В книге разработана количественная модель динамики проекта. Глава о законе Брукса более подробно вникает в то, что происходит при различных допущениях относительно того, кого добавляют, и когда. Чтобы исследовать это, авторы развивают собственную тщательную модель программного проекта среднего размера, предполагая, что у вновь добавляемых людей есть кривая обучения, и учитывая дополнительные издержки на общение и обучение. Они приходят к выводу, что «добавление новых людей к запаздывающему проекту всегда приводит к его удорожанию, но не всегда к более позднему завершению» (курсив авторов). В частности, увеличение численности работников в начале проекта гораздо безопаснее, чем в конце, поскольку добавление новых людей всегда вызывает отрицательный эффект, для компенсации которого требуются недели. Штуцке (Stutzke) предлагает более простую модель для проведения аналогичных исследований, и с тем же результатом.[17]Он проводит подробный анализ процесса и издержек, связанных с привлечением новых работников, явным образом учитывая отвлечение наставников от непосредственной работы над проектом. Он проверял свою модель на реальном проекте, в котором численность работником была удвоена, благодаря чему удалось уложиться в первоначальный график, несмотря на отставание в середине. Он рассматривает альтернативы добавлению новых работников, особенно сверхурочную работу. Наибольшую ценность представляют его многочисленные практические советы о том, как привлекать новых работников, обучать их, обеспечивать инструментарием и т.д., чтобы минимизировать отрицательный эффект увеличения персонала. Особенно достойно внимания его замечание, что дополнительно привлекаемые на поздних стадиях проекта работники должны быть игроками команды, стремящимися войти в игру и вписаться в процесс, а не пытаться изменить или усовершенствовать сам процесс! Штуцке считает, что дополнительная тяжесть обмена информацией в крупном проекте имеет второй порядок малости, и не включает ее в свою модель. Не вполне ясно, учитывают ли ее Абдель-Хамид и Мадник, и если да, то как. Ни в одной из моделей не учитывается то обстоятельство, что работа должна быть перераспределена — процесс, который для меня часто оказывался нетривиальным. «Крайне упрощенная» формулировка закона Брукса становится более полезной, будучи дополнена этими тщательно сделанными надлежащими оговорками. Подытоживая, я продолжаю придерживаться исходного утверждения как приближения к истине нулевого порядка, практического правила, предупреждающего менеджеров о неразумности инстинктивной попытки вытянуть запаздывающий проект. Кадры решают все (или почти все) Некоторые читатели удивляются, что большая часть рассуждений МЧ-М посвящена административным сторонам программной инженерии, а не многочисленным техническим проблемам. Такой перекос частично вызван той ролью, которую я играл в IBM Operating System/360 (теперь MVS/370). Если смотреть глубже, это происходит от убеждения, что качество людей, занятых в проекте, их организация и администрирование имеют гораздо большее значение для успеха, чем инструменты, которыми они пользуются, или применяемые ими технические решения. Последующие исследования подкрепили мою уверенность. Модель COCOMO Бёма признает, что качество команды является важнейшим фактором ее успеха, практически вчетверо более важным, чем следующий за ним по значимости. Большинство научных исследований по программной инженерии сосредоточилось на инструментах. Я люблю хороший инструмент и жажду его. Тем не менее отрадно видеть продолжение исследовательских программ в отношении заботы о людях, их роста и поддержки, а также развития управления разработкой программного обеспечения. Человеческий фактор. Крупным достижением последних лет стала книга Демарко (DeMarco) и Листера (Lister) «Человеческий фактор: продуктивные проекты и программы», изданная в 1987 году. В основе ее лежит положение о том, что «главные проблемы в нашей работе по природе своей не столько технологические, сколько социологические». Она изобилует такими жемчужинами, как «задача менеджера не заставить людей работать, а сделать так, чтобы они могли работать». В ней говорится о таких прозаических вещах, как помещение, мебель, совместное питание команды. Демарко и Листер приводят реальные данные из своего «Программирования военных игр», которые показывают поразительную корреляцию между производительностью программистов из одной и той же организации, а также между характеристиками рабочих мест и уровнем продуктивности и наличия ошибок. В помещениях наиболее продуктивных программистов тише, они более личные, лучше защищены против непрошеного вторжения, и они просто больше… Понимаете ли вы, что покой, пространство и уединенность способствуют лучшей работе ваших теперешних работников или (с другой стороны) способствует привлечению и сохранению лучших работников?[18] Я искренне рекомендую эту книгу всем моим читателям. Передача проектов. Демарко и Листер уделяют большое внимание спаянности команды, неуловимому, но важному качеству. Я думаю, что непонимание администрацией спаянности служит причиной той готовности, с которой, как я наблюдал, в компаниях, расположенных на нескольких площадках, проекты передаются из одной лаборатории в другую. В своей практике я наблюдал, возможно, с полдюжины передач проекта, и ни одна из них не была успешной. Можно с успехом передавать задания. Но во всех случаях попытки передать проект новая команда фактически начинала сначала, несмотря на наличие хорошей документации, некоторого продвижения в проекте и некоторых людей из передающей команды. Я думаю, что разрушение спаянности прежней команды приводит к выкидышу проекта, находящегося в эмбриональном состоянии, и осуществлению его с начальной точки. Сила отказаться от власти Если согласиться, что, как я неоднократно доказывал на протяжении этой книги, творчество исходит от личностей, а не организационных структур и процессов, тогда главная задача менеджера программного проекта — создать организационную структуру и рабочий процесс, способствующий творчеству и инициативе, а не подавляющие их. К счастью, эта проблема присуща не только программным организациям, и над ней работали многие большие умы. Е. Ф. Шумахер (E. F. Schumacher) в классической работе «Малое прекрасно: экономика ради людей» предлагает теорию организации предприятий, максимизирующую творческую активность и радость работников. В качестве первого принципа он выдвигает «принцип вспомогательной функции» из энциклики Quadragesimo Anno папы Пия XI: Передача большему и вышестоящему сообществу того, что могут делать меньшие и нижестоящие организации является несправедливостью и в то же время серьезным злом и нарушением правильного порядка. Ибо всякая общественная деятельность по сути своей должна предоставлять помощь членам социальной группы, а не разрушать и поглощать их… Тем, кто управляет, следует быть уверенными, что чем лучше среди различных сообществ сохраняется дифференцированный порядок в соблюдении принципа второстепенной функции, тем крепче будет власть и эффективность в обществе, тем более счастливым и процветающим государство.[19] Шумахер приводит разъяснение: Принцип второстепенной функции учит нас, что власть и эффективность центра увеличатся, если будут тщательно охраняться свобода и ответственность более низких формирований, а в итоге организация в целом будет «более счастливой и процветающей». Как можно добиться такой организации? … Большая организация должна состоять из множества полуавтономных единиц, которые можно назвать квази-фирмами. Каждая из них должна обладать значительной свободой, чтобы предоставить наилучшие возможности для творчества и предприимчивости… Каждая из квазифирм должна иметь свой учет прибылей и потерь, а также балансовый отчет.[20] К числу наиболее замечательных достижений программной инженерии принадлежат первые этапы практического осуществления таких организационных идей. Прежде всего, микрокомпьютерная революция создала новую программную индустрию с сотнями вновь возникших фирм, которые изначально малы и отмечены энтузиазмом, свободой и творчеством. Сейчас индустрия меняется по мере поглощения мелких фирм крупными. Посмотрим, поймут ли крупные фирмы важность сохранения творческой активности мелких, поглощаемых ими. Еще более примечательно, что высшее руководство ряда крупных фирм предприняло меры по передаче власти вниз отдельным командам, работающим над программными проектами, что сближает их с квази-фирмами Шумахера по структуре и ответственности. Результаты вызвали удивление и удовлетворение. Джим Маккарти из Microsoft описывал мне свой опыт эмансипации команд: У каждой бригады (30-40 человек) есть свой набор разрабатываемых объектов, свой график и даже свои правила разработки, реализации и поставки. В бригаде есть специалисты в четырех или пяти областях, в том числе реализации, тестировании и документировании. Бригада сама улаживает разногласия по пустякам, начальник не вмешивается. Не боюсь переоценить важность перемещения власти, когда бригада самостоятельно несет ответственность за свои достижения. Эрл Уилер (Earl Wheeler), бывший руководитель программных разработок IBM, поделился со мной своим опытом делегирования вниз полномочий, бывших в течение долгого времени сосредоточенными у администрации управления IBM. Ключевым порывом последних лет стало делегирование полномочий вниз. Это было чудом! Улучшились качество, продуктивность, моральный дух. У нас небольшие бригады без централизованного управления. Бригады сами определяют правила производственного процесса, но они испытывают давление со стороны рынка. И это давление заставляет их самих искать способы решения проблем. Общение с отдельными членами бригад показывает, конечно, и удовлетворение от передачи полномочий и свободы, а также более сдержанную оценку того, в какой мере контроль действительно ослаблен. Тем не менее, достигнутая степень передачи полномочий являет шаг в правильном направлении. Получаемые выгода точно те, которые предсказывались Пием XI: в результате делегирования полномочий центр усиливает свою реальную власть, а организация в целом становится более счастливой и процветающей. Какой самый большой сюрприз? Миллионы компьютеров Все компьютерные гуру, с которыми я разговаривал, признают, что для них были неожиданностью микрокомпьютерная революция и ее порождение — производство коробочных программных продуктов. Вне сомнения, это самое значительное событие за два десятилетия после выхода МЧ-М. Оно имеет многочисленные последствия для программной инженерии. Микрокомпьютерная революция изменила характер использования компьютеров. Шумахер сформулировал проблему более 20 лет назад: Чего мы действительно хотим от ученых и технологов? Я отвечу так: нам нужны методы и оборудование, которые: • достаточно дешевы, чтобы быть доступными практически каждому; • пригодны для небольших приложений; • соответствуют потребности человека в творческой деятельности.[21] Это как раз те замечательные свойства, которые микрокомпьютерная революция дала компьютерной промышленности и ее потребителям, которыми теперь стала широкая публика. Средний американец может сегодня позволить себе не только собственный компьютер, но и набор программных средств, для покупки которого 20 лет назад потребовалось бы королевское жалованье. Каждую из целей, поставленных Шумахером, стоит рассмотреть отдельно. Представляет также интерес, в какой мере они достигнуты — особенно последняя. В одной области за другой обычным людям и профессионалам становятся доступны все новые средства самовыражения. Отчасти, развитие в других областях происходит так же, как в создании программ — благодаря устранению побочных трудностей. Побочные ограничения на рукописи накладывались длительностью и стоимостью перепечатывания для внесения исправлений. Работу объемом в 300 страниц иногда приходилось перепечатывать каждые три или шесть месяцев, а в перерыве чиркать в рукописи. Трудно было оценить влияние внесенных изменений на общий ход мысли и ритм слов. Сейчас чудесным образом рукописи стали постоянно меняющимися.[22] Аналогичную изменчивость компьютер придал многим другим материалам: картинам художников, планам построек, чертежам механизмов, музыкальным сочинениям, фотографиям, кинофильмам, слайдовым презентациям, мультимедийным работам и даже электронным таблицам. В каждом случае при ручном способе изготовления для того, чтобы увидеть изменения в контексте, требовалось копирование больших неизменных частей. Теперь, независимо от материала, мы можем пользоваться такими же выгодами, какие работа в режиме разделения времени принесла в программирование: возможность редактирования и мгновенной оценки результата без потери хода мысли. Творческие возможности усилились также благодаря новым гибким вспомогательным инструментам. Один пример — сочинение прозы, при котором мы пользуемся проверкой орфографии, грамматики, стилистическими подсказками, системами библиографии и замечательной возможностью одновременно видеть страницы в окончательно отформатированном виде. Мы еще не оценили значения мгновенного доступа к энциклопедиям и безграничным ресурсам всемирной паутины для использования писателем импровизированного поиска. Самое главное, обретенная изменчивость материала упрощает изучение многих в корне различных возможностей, когда творческая работа только обретает форму. Вот другой пример, когда порядок величины в количественном параметре — в данном случае, времени, необходимом для внесения изменений, — производит качественный скачок в подходе к задаче. Инструменты для черчения позволяют проектировщикам зданий за час творческой работы исследовать гораздо больше вариантов. Подключение компьютеров к синтезаторам и программы, позволяющие автоматически записывать или проигрывать ноты, значительно облегчают фиксацию бренчания по клавишам. Цифровая обработка фотографий, как в Adobe Photoshop, позволяет в течение считанных минут провести эксперименты, для которых потребовались часы работы в фотолаборатории. Электронные таблицы позволяют легко исследовать десятки альтернативных сценариев типа «что, если». Наконец, благодаря вездесущести персональных компьютеров создается совершенно новый материал. Гипертексты, предложенные Ванневаром Бушем в 1945 году, осуществимы только с помощью компьютеров.[23]Мультимедийные презентации и опыты были сложнейшими задачами — слишком много хлопот — до того, как стало возможным проводить их с помощью компьютеров и соответствующего богатого программного обеспечения. Системы виртуальной реальности, пока еще дорогие и не широко распространенные, в будущем станут такими и создадут новый материал для творчества. Микрокомпьютерная революция изменила характер разработки программного обеспечения. Технологии разработки программного обеспечения 1970-х сами изменились в результате микрокомпьютерной революции и вызвавших ее технических достижений. Устранена значительная часть второстепенных сложностей технологий разработки программного обеспечения. Быстрые персональные компьютеры стали обычным инструментом разработчика, и время оборачиваемости стало почти устаревшим понятием. Сегодняшний персональный компьютер быстрее не только суперкомпьютера 60-го года, но и Unix-станции 1985-го. Это значит, что компиляция быстро осуществляется даже на скромных по мощности машинах, а благодаря большому объему памяти отпали задержки при компоновке с использованием дисков. Большая память позволяет также хранить в памяти таблицы символических имен вместе с объектным кодом, в результате чего становится обычной высокоуровневая отладка без перекомпиляции. За последние 20 лет мы почти покончили с использованием разделения времени как методологией разработки программного обеспечения. В 1975 году разделение времени только-только вытеснило пакетную обработку в качестве наиболее распространенной технологии. Сеть использовалась для того, чтобы дать разработчику программного обеспечения доступ как к общим файлам, так и к большим вычислительным мощностям для компиляции, компоновки и тестирования. Сегодня вычислительную мощность обеспечивает персональная рабочая станция, а сеть используется в основном для обеспечения совместного доступа к файлам бригады, разрабатывающей продукт. Клиент-серверные системы меняют и упрощают технологию общего доступа для загрузки, сборки и выполнения контрольных примеров. Сходный прогресс произошел с пользовательскими интерфейсами. Интерфейс WIMP обеспечивает гораздо большие удобства при редактировании текстов программ и текстов на естественном языке. Экран размером 24 строки на 72 колонки сменился полностраничным или даже двухстраничным экраном, поэтому программисты могут видеть изменения, которые они делают, в значительно более широком контексте. Целая новая программная отрасль — коробочные пакеты Рядом с классической индустрией программных продуктов широко развилась еще одна. Продажи программных продуктов числятся сотнями тысяч и даже миллионами. Целые мощные пакеты можно приобрести по цене меньшей, чем стоимость оплаты одного рабочего дня программиста. Эти две отрасли во многом различны и существуют параллельно. Классическая программная индустрия. В 1975 году программная индустрия имела несколько отдельных и до некоторой степени различных составных частей, существующих по сей день: • Производители компьютеров, поставляющие также операционные системы, компиляторы и утилиты для своих продуктов. • Пользователи приложений, например, в информационно-управляющих системах, банках, страховых компаниях, правительственных учреждениях, создающие пакеты программ для собственного употребления. • Разработчики заказных программ, работающие по контракту с пользователем. Многие из этих подрядчиков специализируются на приложениях для военной сферы, где требования, стандарты и маркетинговые процедуры носят специфический характер. • Разработчики коммерческих пакетов, в то время разрабатывавшие, в основном, большие приложения для специфических рынков, такие как пакеты статистического анализа и автоматического проектирования. Том Демарко отмечает фрагментацию классической индустрии разработки программного обеспечения, особенно в части пользователей приложений: Я не ожидал, что эта область распадется на отдельные ниши. Приемы работы в большей степени определяются нишей, чем использованием общих методов анализа систем, языков программирования и технологий тестирования. Ada был последним из языков общего назначения, и он стал языков ниши. В нише обычных коммерческих приложений значительный вклад сделан языками четвертого поколения (4GL). Бём пишет, что «наиболее удачные из 4GL явились результатом написания какой-либо части области приложений на языке опций и параметров». Наиболее широко распространенными из этих 4GL являются генераторы приложений и комбинированные пакеты баз данных и связи с языками запросов. Миры операционных систем объединились. В 1975 году было изобили операционных систем — у каждого производителя компьютеров была, по крайней мере, одна патентованная операционная система для каждой производственной серии, а часто и две. Насколько изменилось положение сегодня! Лозунгом дня стали открытые системы, и осталось лишь пять главных операционных сред, для которых создаются пакеты приложений (в хронологическом порядке): • IBM MVS и VM • DEC VMS • Unix в том или ином варианте • IBM PC, будь то DOS, OS/2 или Windows • Apple Macintosh. Индустрия коробочных продуктов. Экономические законы для разработчиков в этой отрасли совершенно отличны от тех, которые действуют в классической индустрии: стоимость разработки нужно делить на большое количество экземпляров, расходы на упаковку и маркетинг высоки. В классической индустрии при внутрифирменной разработке график работ и набор функций могли быть изменены, в отличие от стоимости разработки. На открытом рынке жесткой конкуренции сроки и функциональность полностью доминируют над затратами на разработку. Как и следовало ожидать, столь различные экономические требования породили весьма различающиеся культуры программирования. В классической индустрии лидирующее положение заняли крупные фирмы с установившимися стилями управления и культурой работы. В коробочной индустрии, напротив, возникли сотни начинающих фирм, ничем не связанных и сосредоточенных на конечной цели, а не на процессе. В такой атмосфере талант отдельного программиста всегда ценится значительно выше, и существует подспудное ощущение, что выдающиеся проекты создаются выдающимися архитекторами. Во вновь возникшей культуре есть возможность вознаграждать «звезд» соответственно их вкладу. В классической индустрии социальная политика фирм и их принципы оплаты труда всегда это затрудняли. Неудивительно поэтому, что многие звезды нового поколения были втянуты в орбиту пакетной индустрии. Покупай и создавай: коробочные продукты в качестве компонентов Радикально улучшить устойчивость программных продуктов и производительность труда при их создании можно, лишь поднявшись на один уровень и изготавливая программы из модулей или объектов. Особенно многообещающей тенденцией становится использование рыночных пакетов в качестве платформ, на которых создаются более богатые и специализированные продукты. Система управления движением грузовиков создается с помощью коробочной базы данных и коммуникационного пакета, также как и информационная система для студентов. Объявления в журналах предлагают сотни стеков для Hypercard, специализированных шаблонов для Excel, десятки специальных функций на Pascal для MiniCad или функций на AutoLisp для AutoCad. Метапрограммирование. Стеки для Hypercard, специализированные шаблоны для Excel, функции для MiniCad часто называют метапрограммированием, созданием нового слоя, приспосабливающего функции к нуждам определенной группы пользователей пакета. Идея метапрограммирования не нова, она вернулась и получила свое название. В начале 60-х многие производители компьютеров и вычислительные центры больших информационно-управляющих систем образовывали небольшие группы специалистов, создававших целые языки прикладного программирования с помощью макросов, написанных на ассемблере. В вычислительном центре Eastman Kodak был создан язык прикладного программирования на базе макроассемблера для IBM 7080. Аналогично, в телекоммуникационной программе Queued Telecommunications Access Method для IBM OS/360 можно было на многих страницах кода, написанного предположительно на языке макроассемблера, не найти ни одной команды машинного уровня. Сейчас блоки, создаваемые метапрограммистом, значительно больше, чем тогдашние макроопределения. Такое развитие вторичного рынка очень обнадеживает: пока мы ждали возникновения активного рынка классов C++, незаметно возник рынок метапрограмм многократного использования. Это действительно наступление на сущность. Поскольку на среднего программиста информационно-управляющих систем феномен разработки на основе пакетов еще не оказал воздействия, он пока не очень замечаем программной инженерией. Тем не менее, это направление будет быстро развиваться, поскольку затрагивает сущность моделирования концептуальных конструкций. Коробочный пакет предоставляет большой функциональный модуль со сложным, но точным интерфейсом, а его внутреннюю концептуальную структуру вовсе не требуется проектировать. Программные продукты с функциями высокого уровня, такие как Excel и 4th dimension, действительно являются большими модулями, но служат понятными, документированными, отлаженными модулями, с помощью которых можно создавать заказные системы. Разработчики приложений следующего уровня получают богатство функций, сокращение времени разработки, отлаженные компоненты, улучшенную документацию и резко сниженную цену. Сложность, конечно, в том, что коробочные пакеты разработаны как самостоятельные объекты, функции и интерфейсы которых метапрограммисты не могут изменить. Кроме того, более существенно то, что разработчики коробочных пакетов, кажется, не слишком стремятся сделать свои продукты пригодными в качестве модулей более крупных систем. Думаю, что такое понимание неверно, и существует неудовлетворенный рынок для пакетов, способствующих использованию метапрограммирования. Так что же требуется? Можно выделить четыре уровня пользователей коробочных продуктов: • Пользователь как таковой, просто использующий приложение и удовлетворенный функциями и интерфейсом, предоставленными разработчиками. • Метапрограммист, строящий шаблоны и функции поверх отдельного приложения с использованием имеющихся интерфейсов, главным образом, для обеспечения труда конечного пользователя. • Разработчик внешних функций, вводящий в приложение дополнительные функции. Это, по сути, новые примитивы языка прикладного программирования, обращающиеся к отдельным модулям, написанным на языке общего назначения. Необходима возможность интерфейса этих новых функций с приложением через перехватываемые команды, обратные вызовы или перегружаемые функции. • Метапрограммист, использующий одно и, в особенности, несколько приложений в качестве компонентов более крупной системы. Это пользователь, чьи нужды сегодня слабо удовлетворяются. Это тот вид использования, который обещает наибольший рост производительности при создании новых приложений. Для этого последнего типа пользователей коробочный продукт должен иметь дополнительный документированный интерфейс — интерфейс метапрограммирования. Он должен предоставлять несколько возможностей. Прежде всего, метапрограмма должна управлять ансамблем приложений, несмотря на то, что каждое приложение, как правило, считает, что управляет самим собой. Этот ансамбль должен управлять интерфейсом пользователя, хотя обычно само приложение считает, что делает это. Ансамбль должен быть в состоянии вызвать любую функцию приложения, как если бы его командная строка исходила от пользователя. Выходные данных приложения должны передаваться ему, а не на экран, причем в виде логических блоков подходящих типов данных, а не текстовой строки, которую нужно отобразить. В некоторых приложениях, например, FoxPro, есть дырочки, позволяющие передать командную строку, но возвращаются скудные и неразобранные данные. Такая дырочка — заплатка на скорую руку, в то время как требуется общее проработанное решение. Большие возможности дало бы наличие языка сценариев для управления взаимодействием приложений, входящих в ансамбль. Такого рода функции впервые предоставила Unix с помощью каналов и стандарта файлов в формате ASCII-строк. Сегодня неплохим решением является AppleScript. Состояние и будущее программной инженерии Однажды я попросил Джима Феррелла (Jim Ferrell), председателя химико-технологического факультета университета штата Северная Каролина поведать о развитии химических технологий вне связи с химией, на что он экспромтом выдал мне замечательный рассказ, продолжавшийся час, начиная с существовавших с античных времен различных производственных процессов для многих продуктов — от стали до хлеба и парфюмерных изделий. Он рассказал, как профессор Артур Д. Литтл (Arthur D. Little) в 1918 году основал в МТИ факультет прикладной химии для исследования, разработки и обучения общим фундаментальным технологиям всех процессов. Сначала были практические правила, затем эмпирические номограммы, затем рецепты проектирования отдельных компонентов, затем математические модели распространения тепла, масс, количества движения в отдельных емкостях. По ходу рассказа Феррелла я поразился обилию параллелей между разработкой химических технологий и развитием программных технологий, происходившим почти полвека спустя. Парнас утверждает, что я вообще пишу о «программной инженерии». Он противопоставляет программотехнику как науку электротехнику и считает, что называть наше занятие инженерией самонадеянно. Возможно, он прав в том, что эта область никогда не станет инженерной дисциплиной с такой точной и всеохватывающей основой, какая есть у электротехники. В конце концов, программная инженерия, подобно химической технологии, занята нелинейными задачами увеличения масштабов до промышленных процессов и, подобно организации промышленного производства, постоянно ставится в тупик сложностями человеческого поведения. Тем не менее характер и временные рамки развития химической технологии приводят меня к мысли, что программная инженерия в возрасте 27 лет не столько безнадежна, сколько является незрелой, какой химическая промышленность была в 1945 году. Лишь после Второй мировой войны химики-технологи реально обратились к взаимосвязанным поточным системам с замкнутым циклом. Сегодня характерные задачи программной инженерии звучат точно так же, как они изложены в главе 1: • Как проектировать и строить программы, образующие системы. • Как проектировать и строить программы и системы, являющиеся надежным, отлаженным, документированным и сопровождаемым продуктом. • Как осуществлять интеллектуальный контроль в условиях большой сложности. В смоляной яме программной инженерии еще долго придется вязнуть. Можно ожидать, что человечество продолжит опыты с системами как внутри, так и за пределами наших возможностей. Программные системы являются, возможно, наиболее запутанными человеческими творениями. Это сложное ремесло требует непрерывно развивать эту дисциплину, учиться создавать из более крупных блоков, наилучшим образом использовать новые инструменты, старательно осваивать опробованные методы управления инженерией, щедро использовать здравый смысл и смиренно сознавать свою подверженность ошибкам и ограниченность наших возможностей. |
|
||
Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх |
||||
|