Архивы: по дате | по разделам | по авторам

Как проектировать ПО?

Архив
автор : Джек Ривз   05.05.2005

Техники объектно-ориентированного программирования (ООП) и, в частности, C++, похоже, взяли мир разработки ПО штурмом.

Статья впервые была напечатана в «C++ Journal» осенью 1992 года и любезно предоставлена Джеком Ривзом для публикации в «Компьютерре». Перепечатка или распространение статьи возможны только с письменного разрешения автора.
«What is software design», ©1992 by Jack W. Reeves.

Техники объектно-ориентированного программирования (ООП) и, в частности, C++, похоже, взяли мир разработки ПО штурмом. Появилось множество статей и книг, рассказывающих, как применять новые техники программирования. На смену сомнениям, не являются ли техники ООП очередным модным поветрием, пришел вопрос, как получить результат с минимумом издержек. ООП появилось не вчера, но его взрывная популярность выглядит не совсем обычной. Откуда столь внезапный интерес?

Тому есть несколько объяснений, но, возможно, единой причины просто не существует. Может быть, некая комбинация факторов достигла, наконец, критической массы — и понеслось. Тем не менее, похоже, что именно сам язык C++ сыграл в происходящем не последнюю роль. Это, разумеется, вызвано своими причинами, но я хотел бы посмотреть на происходящее под другим углом и предложить свой ответ: C++ обрел популярность, потому что в одно и то же время легко позволяет проектировать ПО и программировать.

Если моя реплика кажется вам необычной, то сделано это специально. В этой статье я хочу рассмотреть взаимоотношения между программированием и проектированием ПО. Вот уже почти десять лет меня не оставляет ощущение, что софтверная индустрия не замечает трудноуловимую разницу между разработкой проекта ПО и самим проектом. Я считаю, что растущая популярность C++ может научить нас, как стать хорошими разработчиками — если только мы увидим скрытый урок. А урок заключается в том, что программирование вовсе не создание программного обеспечения. Программирование — это проектирование ПО.

Много лет назад на одном из семинаров поднимался вопрос, является ли разработка ПО инженерной дисциплиной. Не помню, к чему мы тогда пришли, но та дискуссия послужила катализатором для моих собственных размышлений о том, что индустрия программирования придумала ложные параллели с разработкой аппаратуры, но упустила из виду существующее сходство. В итоге, я пришел к выводу, что мы, разработчики, не являемся инженерами, потому что не понимаем, что такое проектирование ПО. Сегодня я в этом убежден еще больше.

Конечная цель любой инженерной деятельности — это некая документация. Когда разработка проекта завершена, проектная документация поступает на производство. Производством занимаются совершенно другие люди с иными навыками. Если проектная документация написана грамотно, производственники могут приступать к созданию продукта и при необходимости штамповать его бесконечно без всякого участия проектировщиков. Изучив жизненный цикл разработки ПО, я пришел к выводу, что единственным видом софтверной документации, который может быть сравним с инженерным проектом, являются листинги исходного кода.

Наверняка аргументов в пользу и против этого допущения хватит на кучу журнальных публикаций. Я исхожу из того, что именно конечный исходный код является проектом программного продукта, и исследую некоторые следствия из этого допущения. Возможно, мне не удастся доказать, что эта точка зрения верна, но я надеюсь показать, что в действительности она объясняет некоторые замеченные мною факты, касающиеся индустрии программирования, в том числе и популярность С++.

Одно из следствий перевешивает все остальные. Оно так важно и так очевидно, что остается белым пятном для большинства софтверных компаний: создание программного обеспечения — дешевый процесс. Его даже нельзя назвать недорогим, так он дешев. Да что там — практически бесплатен. Если считать проектом ПО исходный код, то создание («постройка») программного продукта осуществляется компиляторами и компоновщиками. Есть даже подходящий термин для этого — сделать билд. Инвестиции в оборудование для создания программных конструкций невысоки — все, что действительно нужно, это компьютер, редактор текста, компилятор и компоновщик. И на собственно производство программы нужно совсем немного времени. Может показаться, что, допустим, компиляция программы, написанной на C++ и состоящей из 50 тысяч строк, занимает вечность, но подумайте, сколько времени у вас уйдет на создание аппаратуры того же уровня сложности.
Еще одним следствием из нашего предположения, что исходный код и есть проект программы, является тот факт, что проектирование программ с механической точки зрения — процесс несложный. На написание (то есть проектирование) типичного программного модуля длиной в 50–100 строк кода обычно уходит пара дней (отладка такого модуля — это совсем другая история, но об этом позже). Хочется спросить: существует ли любая иная инженерная специализация, в которой на подготовку проектов такой сложности уходило бы столь же мало времени, но сперва мы должны определить, как определять и сравнивать сложность. Тем не менее, очевидно, что программные проекты довольно быстро «набирают объем».

Если принять, что программные продукты относительно легко проектировать и что они практически бесплатны в производстве, то тенденция усложнения и увеличения объема программных проектов становится легко объяснимой. Это может показаться даже очевидным, однако важность проблемы часто игнорируется. Школьные проекты нередко затухают после нескольких тысяч строк кода. Есть программные продукты, заброшенные своими авторами после десяти тысяч строк. Нам уже давно неинтересны простые программы. Типичный коммерческий продукт состоит из сотен тысяч строк кода, многие дотягивают до миллиона. Вдобавок программы постоянно эволюционируют. И даже если в сегодняшнем проекте у нас всего несколько тысяч строк, то за все время его жизни будет написано во много раз больше.

Хотя хватает примеров, когда «аппаратные» проекты не уступают по сложности программным, давайте отметим два факта о современном «железе». Во-первых, в сложных устройствах тоже есть баги (как бы ни пытались уверить нас в обратном критики качества ПО). Микропроцессоры поставляются на рынок с ошибками в логике, мосты рушатся, дамбы прорывает, самолеты падают, тысячи автомобилей и прочих потребительских продуктов отзываются с рынка производителем — все это не раз происходило на нашей памяти, и все это результат ошибок проектировщиков.

Во-вторых, сложные устройства требуют соответственно сложных и дорогих производственных линий. В результате позволить себе строить такие системы может лишь ограниченное количество компаний. С программным обеспечением все иначе. На рынке сотни фирм и тысячи очень сложных программных продуктов (и оба этих показателя растут с каждым днем). Это означает, что для решения проблем софтверной индустрии рецепты, найденные разработчиками аппаратуры, не подходят. Пожалуй, наоборот, — с развитием CAD- и CAM-систем проектирование аппаратных средств приблизилось к разработке ПО.

Проектирование программы — это упражнение на управление сложностью. Сложность заложена в самих проектах, в компаниях, которые ими занимаются, и в индустрии в целом. Проектирование программ очень напоминает проектирование систем. Оно охватывает множество технологий и зачастую включает в себя ряд дополнительных дисциплин. Спецификации ПО подвижны, они могут меняться «на лету», меняться часто и сильно в ходе процесса проектирования. Группы разработчиков тоже неустойчивы и меняются в ходе процесса. Во многих отношениях программное обеспечение больше напоминает сложные социальные или органические системы, нежели механические устройства. Все это усложняет проектирование ПО и повышает вероятность ошибок. Я не открыл здесь Америки, но спустя тридцать лет после начала софтверной революции разработка ПО до сих пор напоминает искусство в сравнении с прочими инженерными специализациями.

Общепринято, что настоящие инженеры, закончив проект любой сложности, уверены в реальности его воплощения. Также они не сомневаются, что их разработка может быть создана с применением существующих технологий. Для этого инженеры тратят кучу времени, утверждая и подчищая свой проект. Возьмем, например, проект моста. Перед постройкой моста инженеры проводят структурный анализ; они строят компьютерные модели и запускают симуляции; они делают уменьшенные модели и проверяют их в аэродинамических трубах или как-то иначе. Короче говоря, проектировщики делают все, чтобы избавиться от сомнений в качестве своего проекта перед его воплощением. Еще сложнее проектировать самолеты — приходится строить полноразмерные прототипы и проводить испытания, чтобы подтвердить предположения конструкторов.

Большинство людей полагает, что проекты программного обеспечения не проходят столь безжалостных проверок. Однако если мы примем, что проектом программного продукта является его исходный код, то увидим, что разработчики, на самом деле, уделяют достойное внимание подтверждению и уточнению своих проектов. Мы называем эти процессы тестированием и отладкой. Большинство (уж в софтверном бизнесе точно) не считает тестирование и отладку настоящей «инженерной» деятельностью. Одна из главных причин этого не в какой-то межотраслевой разнице, а в том, что софтверная индустрия не принимает, что код — это и есть проект. Модели, прототипы и макеты являются общепринятой составляющей прочих инженерных дисциплин. Разработчики программного обеспечения не имеют и не используют других формальных методов проверки достоверности своих проектов из-за простоты экономики цикла создания программных продуктов.

Откровение номер два: просто сделать проект и протестировать его — легче и дешевле. Нас не волнует количество билдов — они все равно ничего не стоят, если говорить о времени, а ресурсы, если билд окажется неудачным, можно потом использовать снова. Заметим, что тестирование не просто проверяет правильность проекта, а является частью процесса внесения улучшений. Настоящие инженеры-конструкторы часто строят модели (или, по меньшей мере, их трехмерные компьютерные репрезентации). Это позволяет «почувствовать» проект, что невозможно сделать, ограничившись проектной документацией. Создавать такие модели в рамках программного проекта и невозможно, и не нужно. Мы сразу производим продукт. Даже если бы мы могли проверять правильность программы (так же автоматически, как сейчас компилируем ее), это все равно не избавило бы нас от циклов билд/тестирование. Ergo, формальные доказательства правильности ПО никогда не были предметом особого интереса в софтверной индустрии.

Такова реальность нынешнего процесса разработки ПО. Все больше людей и компаний создают все более сложные программные проекты. Они пишутся на каком-то языке программирования, а потом сверяются и улучшаются с помощью циклов билд/тестирование. Этот процесс подвержен ошибкам и неточен. И то, что многие разработчики не хотят понимать, что все работает именно так, только обостряет проблему.

Они пытаются разложить процесс проектирования по полочкам. Проектирование архитектуры приложения (проектирование верхнего уровня) должно быть завершено и заморожено до того, как будет написан код. Тестирование и отладка необходимы только для исключения ошибок. А между этими процессами болтаются программисты, рабочие-строители софтверной индустрии. Многие полагают, что если заставить программистов воплощать проекты в том виде, в котором они им спущены сверху (внося при этом некоторое количество ошибок), то разработка ПО может превратиться в настоящую инженерную дисциплину. Но это вряд ли произойдет, поскольку описанная схема игнорирует экономические и рабочие реалии.

К примеру, ни в одной другой современной отрасли промышленности не будут терпеть полную переделку работы. Строитель, который не может построить что-то с первого раза, очень скоро вылетит с работы. В софтверном же мире любая часть кода может быть пересмотрена или даже переписана с нуля по результатам тестирования и отладки. Такого рода переделки имеют право на существование в творческих процессах, например в проектировании, но не на производстве. Никто не ожидает, что инженер-проектировщик создаст совершенный проект с первой попытки. Но даже если и создаст — проект все равно должен пройти все стадии доработки, чтобы доказать свое совершенство.

Если уж заимствовать что-то у японских управленцев, то первое, чему мы должны научиться: обвинять работников в ошибках непродуктивно. И вместо того, чтобы продолжать втискивать разработку ПО в прокрустово ложе неверно выбранной модели процессов, нам нужно пересмотреть выбранную модель, чтобы она помогала, а не мешала создавать лучшее ПО. Это лакмусовая бумажка для «инженерности» разработки ПО. Инженерный подход заключается в том, как вы осуществляете процессы, а не в том, используете вы CAD-системы или нет.

Главная сложность в разработке ПО заключается в том, что в процесс проектирования входит всё. Кодирование — это проектирование; тестирование и отладка — это тоже проектирование; создание архитектуры ПО — это тоже старое доброе проектирование. Может быть, делать программы и дешево, зато проектировать их чертовски дорого. Программы столь сложны, что при их проектировании применяется множество подходов (и, как следствие, множество разных точек зрения). Проблема же в том, что все эти аспекты взаимосвязаны (как и в разработке аппаратуры). Было бы отлично, если б создатели архитектуры могли игрнорировать детали разработки отдельного модуля. Точно так же было бы замечательно, если бы программисты могли не тревожиться об общей архитектуре, кодируя внутренние алгоритмы в своем модуле. К несчастью, аспекты одного уровня проектирования связаны с другими. Выбор алгоритмов для конкретного модуля может быть столь же важен для проекта в целом, как любой из аспектов проектирования архитектуры приложения. Нельзя сказать, что какой-то подход важнее другого. Неправильное проектирование модуля может оказаться столь же фатальным для проекта в целом, как дефект архитектуры. Проект должен быть закончен и верен во всем. В противном случае все его билды будут содержать ошибки.

Чтобы как-то справиться со сложностью, проектирование ПО разделено на уровни. Когда программист занимается детальным проектированием конкретного модуля, возможно, существуют сотни других модулей и тысячи деталей, о которых он может пока не волноваться. К примеру, есть множество аспектов проекта, которые невозможно четко причислить к структурам данных или алгоритмам. В идеале программист, занятый написанием кода, беспокоиться о таких вещах не должен.

Но это не работает. И в этом есть определенный смысл. Программу нельзя считать законченной, пока она не написана и не протестирована. Тестирование — важнейшая часть проверки проекта и его последующего улучшения. Проектирование ПО не сводится к созданию архитектуры приложения, это просто каркас для более детального проектирования. У нас очень ограниченные возможности по проверке правильности архитектуры. Детализированный проект в итоге повлияет (или должен повлиять) на архитектуру — не меньше, чем прочие факторы. Улучшение всех сторон проекта — это процесс, который должен вестись в течение всего цикла проектирования. Если же какая-то часть проекта заморожена (и не может быть улучшена), то не стоит удивляться, если конечный результат окажется неудовлетворительным или вовсе неработоспособным.

Как было бы славно, если б однажды спроектированная архитектура была более устойчивой, однако настоящий мир программных систем не таков. Программы слишком сложны и несамодостаточны. Может быть, какие-то «железки» будут работать не так, как ожидалось, или в какой-нибудь библиотеке найдется недокументированное ограничение. С подобными трудностями рано или поздно сталкивается любой программный проект. Такие проблемы выявляются во время тестирования (если мы добросовестно тестируем код) по той простой причине, что нет никакой возможности выявить их раньше. Когда они обнаружены, они начинают влиять на проект. Если мы везунчики, то их влияние локально. Но частенько случается иначе — согласно закону Мерфи требующиеся изменения затрагивают значительную часть проекта. И когда какая-то его часть не может быть изменена по некоторой причине, то согласовать между собой другие части проекта — сложнее. В итоге мы приходим к тому, что менеджеры называют «хакерством», но это, на самом деле, сегодняшняя реальность разработки ПО.

К примеру, я сейчас работал над проектом, в котором между внутренностями модуля А и модулем Б была обнаружена временная зависимость. К несчастью, абстракция модуля А не предусматривала возможности корректного включения вызова модуля Б. Естественно, когда мы это обнаружили, менять абстракцию модуля А было уже поздно. Как вы понимаете, чтобы решить эту проблему, нам пришлось внести массу поправок во внутренности модуля А. Мы еще не установили версию 1.0, но уже были уверены, что проект «посыпался». Каждая новая поправка мешала одной из предыдущих. Это нормальная практика. В конце концов, я и мои коллеги потребовали внесения изменений в проект, но чтобы убедить в этом руководство, пришлось попотеть в нерабочее время. Разумеется, бескорыстно.

То есть среднестатистическому программному проекту тернии гарантированы, и с этим надо смириться заранее, ибо «главного глазами не увидишь», и как ни старайся, какие-то ляпы вылезут непременно. В этом и есть разница между мастерством и инженерией. Опыт может вывести нас на нужную дорогу практически по прямой — это мастерство. Но если мы работаем на неизвестной территории, шаг за шагом улучшая наш продукт, — это уже инженерный подход.

Маленькое дополнение: все программисты знают, что документировать разработку ПО целесообразнее после написания кода, а не наоборот, — точность документации от этого только выигрывает. И это неудивительно. В коде отражается окончательный вариант проекта, и именно он обрабатывается в процессе создания билдов и тестирования. Вероятность того, что исходный вариант проекта останется неизменным на протяжении всего цикла, обратно пропорциональна числу модулей и числу задействованных программистов. То есть практически стремится к нулю.

Нам отчаянно необходимо хорошее проектирование на всех уровнях. В частности, на уровне архитектуры. Чем лучше будет спроектирована архитектура, тем проще детализировать проект. Проектировщики должны использовать все, что им нужно: структурные схемы, диаграммы Буча, таблицы состояний, PDL и т. д. Если это работает, пользуйтесь! Однако надо иметь в виду, что весь этот инструментарий еще не проект. Настоящий программный проект пишется на одном из языков программирования. Поэтому мы должны кодировать наши проекты с самого начала. Позднее мы просто отладим этот код при необходимости.

Универсальных нотаций, подходящих для проектирования верхнего и нижнего уровней, не существует. В конечном счете, проект будет закодирован на одном из языков программирования. Это означает, что архитектура проекта должна быть транслирована на требуемый язык программирования до того, как начнется детализация проекта. На это требуется время, и трансляция сама по себе является источником ошибок. И прежде чем транслировать с нотации, которая, возможно, не ложится четко на выбранный язык программирования, программисты зачастую возвращаются к требованиям и переделывают архитектуру. Это тоже часть реальности разработки ПО.

Так может, лучше позволить настоящим проектировщикам сразу описывать проект в настоящем коде, а не заниматься позднейшей трансляцией языконезависимого проекта? Что нам нужно — так это унифицированная проектная нотация, подходящая для проектирования всех уровней. Другими словами, нам нужен язык программирования, на котором можно заниматься и проектированием концепций верхнего уровня. И такой язык есть. C++ — язык программирования, подходящий для реальных приложений —является также ясным языком для описания проекта. C++ позволяет нам напрямую выражать высокоуровневую информацию о составляющих проекта, что облегчает производство и дальнейшую доводку до ума. Строгая проверка типов позволяет легко обнаружить ошибки. В результате мы получаем более ясный — а по существу, более технический, более инженерный — проект.

В конечном счете, программный проект должен быть представлен на каком-то языке программирования, а затем проверен и доведен до ума с помощью циклов билд/тестирование. Остальное — от лукавого. Давайте посмотрим, какие средства или технологии разработки ПО получили популярность. Структурные языки были настоящим прорывом в свое время. Для их популяризации был создан Pascal, который и сам стал популярным. ООП — это новый виток развития, в центре которого лежит С++. А теперь давайте подумаем о том, что не сработало? CASE-средства? Популярны? Да. Универсальны? Нет! Структурные схемы? То же самое. Как и диаграммы Уорнера-Орра, диаграммы Буча, объектные диаграммы и т. д. У всех вышеперечисленных технологий есть свои сильные стороны и один общий недостаток — они не имеют прямого отношения к разработке. На самом деле, единственная действительно популярная нотация — это PDL и его аналоги.

Это говорит нам о том, что коллективное подсознательное софтверной индустрии инстинктивно знает, что улучшения в технологии программирования и работающих языках программирования на порядки важнее всего остального, а равно и о том, что программисты хотят проектировать. Как только появляется более выразительный язык, программисты сразу же осваивают его.

Отметьте также, как меняется процесс разработки. Раньше разработка была подобна водопаду(Имеется в виду водопадная модель программирования — линейная модель жизненного цикла проекта разработки программ, состоящая из четко определенных этапов: сбор требований, проектирование, кодирование, тестирование и эксплуатация. Каждый их них должен быть завершен до начала следующего. Возвраты к предыдущему этапу допускаются). Сегодня мы говорим, что она идет по спирали, о быстром создании прототипов. И хотя такие техники частенько сопровождаются терминами типа «снижение риска» и «сокращенные сроки поставки продукта», на самом деле речь идет о кодировании с самого начала жизненного цикла проекта. И это хорошо. Это позволяет запустить цикл билд/тестирование раньше, а также повышает вероятность того, что детализацию проекта будут делать те же программисты, которые разрабатывали его архитектуру.

Как отмечено выше — инженерный подход больше касается того, как вы создаете продукт, нежели того, как этот конечный продукт выглядит. Мы, софтверщики, близки к тому, чтобы стать инженерами, но нам нужно несколько изменить собственное восприятие. Программирование и цикл билд/тестирование — это центральные точки процесса разработки ПО. И мы должны относиться к ним соответствующе. Экономика циклов билд/тестирование плюс тот факт, что софтверная система может быть репрезентацией чего угодно, делает невозможным нахождение общих методов проверки работоспособности программного проекта. Мы можем усовершенствовать процесс доводки, но не можем его избежать.

И последнее: цель любого проектирования — получение на выходе некоторой документации. Очевидно, что наиболее важны актуальные проектные документы, но их недостаточно. Кто-то ведь, в конце концов, планирует использовать это ПО. Не исключено, что позднее система будет модифицироваться и расширяться, а значит, вспомогательная документация так же важна для программного проекта, как и для «железного». Если пока оставить в стороне руководства пользователей, инструкции по установке и прочую писанину, напрямую не связанную с проектом по разработке ПО, — имеется как минимум две причины, подтверждающие необходимость вспомогательных документов.

Во-первых, вспомогательная документация нужна для того, чтобы извлекать из пространства задачи важную информацию, не отраженную в проекте. В процессе проектирования создается компьютерная модель для решения поставленных задач. Этот процесс требует понимания самой задачи, а такое понимание зачастую подразумевает информацию, которая напрямую в компьютерной модели не отражена, но неявно используется разработчиком при моделировании. Эта информация должна быть сохранена на тот случай, если вдруг модель потребует доработок.

Во-вторых, вспомогательная документация нужна для документирования неочевидных аспектов проекта (как верхнего, так и нижнего уровня). Многие из таких аспектов лучше описываются графически, поэтому отразить их непосредственно в комментариях к коду трудно. Это не значит, что графическая проектная нотация лучше, чем язык программирования. Относитесь к графическим комментариям, как к подписям на чертежах. Не забывайте, что настоящим проектом является только исходный код, а не вспомогательная документация. В идеале нам бы подошли такие средства разработки, которые могли бы автоматически генерировать вспомогательную документацию на основе исходного кода, но это, пожалуй, из области фантастики. В лучшем случае мы можем ожидать появления утилит, которые позволят программистам (или техническим писателям) извлечь определенную информацию из исходников с целью ее дальнейшего документирования. Без сомнения, поддержание такой документации в актуальном состоянии — задача трудная. Вот еще один аргумент в пользу более выразительных языков программирования (а также в пользу уменьшения объемов вспомогательной документации и как можно более позднего — в рамках проекта — ее оформления). И, конечно, мы должны использовать самые совершенные средства, чтобы не оказаться, в конце концов, у грифельной доски с кусочком мела или с ручкой перед чистым листом бумаги.

Итак, к чему мы пришли:

  • Настоящее ПО запускается на компьютерах. Оно представляет собой последовательность из единиц и нулей, сохраненных на каком-то магнитном носителе. Это не листинг программы на С++ или любом другом языке программирования.
  • Листинг программы — это проектный документ. Сами программы создаются компиляторами и компоновщиками.
  • Производить настоящее ПО очень дешево (а по мере развития компьютерных мощностей будет еще дешевле).
  • Проектировать настоящее ПО безумно дорого. Это так, потому что программы невероятно сложны и практически все этапы развития программного продукта можно отнести к проектированию.
  • Программирование есть вид проектирования. Хорошие проектировщики поняли это и кодируют всегда, когда нужно.
  • Кодировать нужно чаще, чем многим кажется. Зачастую процесс воспроизведения проекта в коде выявляет недостатки проекта и приводит к дополнительной доработке. Чем раньше это случится, тем лучше окажется проект.
  • Раз уж производить ПО так дешево, то формальные инженерные методы проверки работоспособности проектов не слишком востребованы. Гораздо легче и дешевле построить проект, а потом уже тестировать его, чем пытаться доказать его корректность.
  • Тестирование и отладка — это тоже проектирование (точнее, софтверный эквивалент утверждения проекта и его доводки в других инженерных дисциплинах). При правильно поставленном процессе разработки важность этих этапов не принижается.
  • Есть и другие виды проектирования ПО (проектирование архитектуры, проектирование модулей, структурное проектирование и т. д.). Эти методы тоже могут быть полезны.
  • Все виды проектирования взаимосвязаны. Правильная постановка процесса разработки предусматривает — порой радикальные — изменения проекта, если на каком-то этапе проектирования выясняется, что это необходимо.
  • В процессе разработки вы можете использовать разнообразные нотации (как для вспомогательной документации, так и в средствах для облегчения проектирования). Однако эти нотации не являются частью разработки.
  • Разработка ПО в большей мере искусство, нежели инженерная дисциплина. В основном это происходит из-за недостатка жесткости в критических процессах утверждения и улучшения проекта.
  • В конечном счете, успехи разработок программного обеспечения зависят от успешного развития техник программирования, что, в свою очередь, означает усовершенствование языков программирования. Подобным усовершенствованным языком можно считать C++, который завоевал популярность, потому что был мэйнстримовским языком программирования, напрямую поддерживающим лучшее проектирование.
  • С++ — шаг в правильном направлении, но этого мало.
Конвейер. Линия 1

Разумеется, Джек Ривз далеко не единственный человек, который задумывался над тем, насколько Настоящие Программисты похожи на Настоящих Инженеров. В 2002 году Уоттс С. Хамфри (Watts S. Humphrey), известный ученый, почти тридцать лет проработавший в IBM, посвятил этой проблеме несколько выпусков своей колонки «Watts New». Правда, Уоттса заинтересовала более общая постановка задачи: насколько вообще отлаженные инженерные методики разработки проектов пригодны для создания программного обеспечения? По мнению Уоттса, ничто и никто не мешает программистам использовать опыт инженеров из других областей. Никто, кроме них самих.

Как и Ривз, Уоттс отмечает, что между софтверной индустрией и промышленностью есть значительные различия. Однако они не столь велики, чтобы программисты могли с чистой совестью отказаться от создания жестких планов разработки и четкого следования им. Конечно, затраты на производство программ, пишет Уоттс, отличаются от затрат на производство экземпляра продукта, но если приплюсовать к стоимости компиляции (здесь я использую терминологию Ривза. — В.Г.) затраты на постпродажное обслуживание, то окажется, что программы вовсе не так дешевы, как можно было бы подумать.
Собственно говоря, конфликт между свободолюбивыми программистами и настырными менеджерами проектов не является уникальной чертой софтверной индустрии. Просто в промышленности все эти страсти уже давно улеглись, однако еще сто лет назад всерьез обсуждалось, кто эффективнее: талантливые Кулибины, иногда выдающие гениальные продукты, или заполненные серыми костюмами конструкторские бюро, которые выдают не бог весть что, зато регулярно. К сожалению, бизнесу в целом гораздо важнее предсказуемость, и, наверное, любой читатель понимает, что продукты, его окружающие, созданы коллективами, а не гениями-одиночками.

У софтверной индустрии романтический период становления все никак не завершится (сверхуспешные программные продукты, созданные одиночками, появляются и сегодня), поэтому попытка внедрить «цивилизованный» подход к разработке упирается в неумение, непонимание и откровенное нежелание программистов следовать предложенным гайдлайнам.

Конвейер. Линия 2

Но не меньше виноваты и менеджеры проектов, которые зачастую составляют план работ, исходя из собственных соображений и прикидок на требуемое время исполнения. Между тем программирование такая штука, где вы зачастую действительно можете получить продукт «вчера», но и качества он будет соответствующего.

В колонке «Поучимся у железячников: планирование» Уоттс задает себе два вопроса и сам же на них отвечает. На вопрос «Подходят ли стандартные инженерные методики к разработке программного обеспечения?» он дает утвердительный ответ. А вот на вопрос «Должны ли эти методики быть жесткими и принудительными?» четко ответить затрудняется и долго объясняет, что любые методики, мол, нужно применять с умом. Тем не менее, разумное применение общепринятых методов разработки в контексте разработки программного обеспечения позволит, по его мнению, значительно повысить вероятность того, что проект будет сдан в срок, не вылезет за рамки отведенного бюджета и будет достаточно качественным.
Очевидно, что только такими методами радикально проблему качества ПО не решить, поэтому в следующей колонке Уоттс снова возвращается к теме «инженеров» и «программистов», чтобы предложить в качестве панацеи — лучшее документирование. Это, утверждает Уоттс,

  • дисциплинирует разработчиков,
     
  • помогает оценить проект,
     
  • помогает управлять изменениями,
     
  • дает возможность ознакомиться с проектом тем, кто не участвует в разработке,
     
  • гарантирует качественное и экономически эффективное исполнение проекта.
  • Некоторые, считает Уоттс, могут держать сложные проекты в своей голове. Но как бы ни был одарен разработчик, у каждого есть свой предел, и если этот предел наступает, то проекту тоже наступает кое-что. Таким образом, правильно составленная документация — гарантия жизнеспособности проекта. С другой стороны, документация улучшает качество кодирования, а значит, и общую производительность команды (вероятность переделок проекта в этом случае тоже меньше, хотя нулевой она, конечно, никогда не будет). Кроме того, пишет Уоттс, по мере развития проекта главные разработчики уходят делать другие продукты, но они должны оставить своим последователям возможность вносить любые изменения в проект. То есть — правильно составленную документацию.

    Конвейер. Линия 3


    В принципе, Уоттс выступает за жесткое разделение обязанностей в команде разработчиков. Есть проектировщики, есть кодеры, есть тестеры. Каждый из членов команды может быть полностью в курсе происходящего, поскольку вся работа над проектом тщательно документируется. Время, потраченное на составление документации, окупается стократ за счет того, что проект получается более устойчивым и предсказуемым.

    Не вступая в прямую конфронтацию с Ривзом (мы даже не знаем, читал ли он его статью), Уоттс в своих колонках описывает маленький программистский ад, в котором программисту отводится роль махонького винтика в большой фабрике по производству ПО. И как будто этого недостаточно, винтик еще должен тратить массу времени на всякого рода бумажную волокиту.

    Единственное исключение Уоттс делает для новых разработок. Если в проекте возможны частые и значительные по сути изменения, то логичнее (другими словами, дешевле) использовать сплоченную группу разработчиков, которая будет заниматься проектированием и кодированием одновременно. Однако, по мнению Уоттса, таких разработок ничтожно мало. Как правило, софтверные компании занимаются либо поддержкой и улучшением собственных продуктов, либо производством новых программ на основе «домашних заготовок», которые — совершенно верно — должны быть правильно задокументированы и уложены на верные полочки.

    Производственное качество, резюмирует Уоттс, базируется на двух принципах: качество продукта определяется качеством процесса, и уровнем качества можно управлять. И хотя методы управления качеством в софтверной индустрии отличаются от промышленных практик, принципы везде одни и те же.

    Бизнес-подходы тоже от индустрии к индустрии меняются мало, так что ничего хорошего программистов в ближайшее время не ждет. Один из последних оплотов вольнодумцев — относительно творческая игровая индустрия — стремительно превращается в большую фабрику грез с ударением на слове «фабрика».

    Одно из свидетельств тому — выступление Грега Костикяна (www.costik.com) на конференции разработчиков компьютерных игр GDC 2005. Местами Грег перегибает палку, но зато объясняет, почему старые игрушки мы помним до сих пор, а о новых забываем, вынув диск из лотка.

    Конвейер. Линия 4

    Игры создаются новаторами. Это они создают новые игровые жанры. Благодаря им растут игровые сообщества. Это новаторы расширили палитру возможного. История последних двадцати лет вовсе не является историей (как вам пытаются впарить) повышения тактовой частоты процессора или улучшения компьютерной графики. Это был изумительный взрыв творческого подхода и новаторства. Вот что создало нашу индустрию. И вот почему мы любим игры.

    Но теперь этого нет.

    Не далее как в 1992 году средний бюджет ПК-игры составлял 200 тысяч долларов. Сегодня типичный бюджет игры класса А — 5 млн. долларов. На следующем витке бюджеты будут порядка 20 млн. долларов. С увеличением вложений издатели становятся невероятно консервативными, и шансов у нетривиальных проектов все меньше и меньше. Вот мы и получим Driver 69. Бесконечный Grand Theft Auto. Дребедень за дребеденью. Сегодня вы не можете издать новационную игру. Если, конечно, вас зовут не Райт[Уилл Райт (Will Wright) — основатель компании Maxis (Sim City, The Sims)] или Миямото[Сигеру Миямото (Shigeru Miyamoto) — главный игровой дизайнер Nintendo, автор Donkey Kong].

    Многие из вас были на выступлении Microsoft?

    Не знаю, как вам, а мне было страшно. Эра высокого разрешения. Больше. Громче. Более реалистичное 3D. Сотни разработчиков в команде. И большие бабки.

    Нам с вами, конечно, большие бабки не светят. Мы, разработчики, останемся в рамках положенного бюджета. Бабки — издателям.

    Новые бюджеты, новые команды означают смерть новаторского подхода.

    <…>

    Друзья мои, нас поимели. Основательно. Со знанием дела. Планка поднимается все выше и выше — до тех пор, пока никто не сможет позволить себе рисковать, выпуская игры. Общее количество работников на проекте растет экспоненциально, но разработчикам не светит ничего, кроме привычных дедлайнов и восьмидесятичасовой рабочей недели (пока этот фронт не саутсорсят в Азию, по крайней мере).

    С такими ставками — не рискуют. Но без риска не будет новаторства, а именно новаторство — сердце игровой индустрии.

    Грег Костикян

    © ООО "Компьютерра-Онлайн", 1997-2024
    При цитировании и использовании любых материалов ссылка на "Компьютерру" обязательна.