Страница:
Разработка программ трассировки находится в согласии с той идеей, что проект никогда не кончается: всегда будет потребность в изменениях и добавлении функций. Это – инкрементальный подход.
Обычная альтернатива является своего рода тяжеловесным техническим подходом: программа разделяется на модули, которые программируются в вакууме. Модули объединены в подсистемы, которые затем подлежат дальнейшему объединению, пока в один прекрасный день вы не получаете завершенное приложение. И только тогда приложение в целом может быть представлено пользователю и протестировано. Технология программы трассировки имеет много преимуществ:
• Пользователи могут увидеть нечто, работающее еще до выпуска окончательной версии.Если вам удалось передать суть делаемого вами (см. "Большие надежды"), то ваши пользователи будут осознавать, что видят перед собой еще нечто незрелое. Они не будут разочарованы отсутствием функциональных возможностей; будут гореть желанием увидеть некий видимый прогрессе создании их системы. По мере того как проект будет продвигаться, они начнут делать вложения. Эти пользователи и станут теми людьми, которые скажут вам о том, насколько близко к цели находится та или иная итерация.
• Разработчики выстраивают некую структуру, в которой они работают.Наибольший страх вызывает лист бумаги, на котором ничего не написано. Если вы разработали все механизмы взаимодействия между модулями вашего приложения и воплотили их в тексте программы, то вашей команде не придется многое высасывать из пальца. Это делает труд каждого члена команды более производительным и способствует последовательности в их работе.
• У вас есть платформа для интеграции.Как только все компоненты системы связаны друг с другом, появляется некая среда, в которую можно добавлять новые фрагменты программ, прошедшие модульное тестирование. Вы будете заниматься интеграцией каждый день (иногда несколько раз вдень), не пытаясь интегрировать все сразу по методу "большого скачка". Воздействие каждого вновь вносимого изменения становится более очевидным, взаимодействия более ограниченными, поэтому отладка и тестирование будут более быстрыми и точными.
• У вас есть что продемонстрировать.Спонсоры проекта и руководство стремятся увидеть демонстрационные версии в самое неподходящее время. При наличии программы трассировки у вас всегда будет то, что можно им продемонстрировать.
• Вы лучше ощущаете прогресс.При разработке программы трассировки программисты работают над сценариями использования системы по очереди. Они заканчивают один сценарий и переходят к следующему. При этом гораздо проще определить производительность и продемонстрировать пользователю продвижение проекта. Поскольку каждая индивидуальная разработка меньше по объему, вы избежите создания монолитных программных блоков, о которых каждую неделю сообщается, что они готовы на 95 %.
При стрельбе трассирующими вы не всегда попадаете в цель
Программа трассировки и создание прототипов
11
Для чего создаются прототипы
Как использовать прототипы
Создание прототипов архитектуры
Как не надо использовать прототипы
12
Языки программирования влияют на то, как вы думаете о проблеме, и на то, как вы думаете об общении. В каждом языке имеются свои особенности – ученые словечки типа "статический и динамический контроль типов", "раннее и позднее связывание", "модели наследования" (простое, множественное или отсутствие) – все они могут предложить определенные решения или затруднить их. Решение, создаваемое в стиле Lisp, отличается от решения, основанного на мышлении приверженца языка С, и наоборот. Верно и обратное (и по нашему мнению, более важное) – язык, отражающий специфику данной области, может, со своей стороны, предложить решение в области программирования.
Мы всегда пытаемся написать программу, используя словарь, характерный для прикладной области (см. "Ловушка требований", где предлагается использовать проектный глоссарий). В ряде случаев можно перейти на следующий уровень и действительно программировать, пользуясь словарем, синтаксисом и семантикой предметной области.
Пользователи предложенной системы должны быть в состоянии точно изложить, как она должна работать:
From X25LINE1 (Format=ABC123) {
Put TELSTAR1 (Format=XYZ43B);
Store DB;
}
Этот язык не должен быть исполняемым. В своем исходном виде он мог бы просто фиксировать требования пользователя – спецификации. Однако вы наверняка посчитали возможным пойти дальше и фактически реализовать язык. Ваша спецификация превратилась в исполняемую программу.
После того как вы написали приложение, пользователи предъявляют вам новое требование: сообщения с отрицательным балансом не должны сохраняться и должны отсылаться обратно по каналам связи Х.25 в первоначальном формате:
From X25LINE1 (Format=ABC123) {
if (ABC123.balance «0) {
Put X25L1NE1 (Format=ABC123);
}
else {
Put TELSTAR1 (format=XYZ43B);
Store DB;
}
}
Несложно? При наличии надлежащей поддержки вы можете программировать значительно ближе к прикладной области. Мы не предлагаем, чтобы ваши конечные пользователи программировали на этих языках. Вместо этого вы даете самому себе инструмент, который позволяет вам работать ближе к их области.
Мы полагаем, что вам следует рассмотреть способы перемещения вашего объекта ближе к предметной области проблемы – будь то простейший язык для конфигурирования и управления прикладной программой или же более сложный язык для обозначения правил или процедур. При составлении программы на более высоком уровне абстракции вам легко сосредоточиться на решении проблем предметной области и вы можете проигнорировать мелкие детали, связанные с реализацией.
Помните, что с приложением работают многие пользователи. Существует конечный пользователь, который понимает правила предметной области и то, что должно быть на выходе программы. Есть также вторичные пользователи: обслуживающий персонал, менеджеры, занимающиеся конфигурированием и тестированием, программисты служб поддержки и сопровождения и будущие поколения разработчиков. У каждого из этих пользователей есть собственная предметная область, и для всех них вы можете генерировать мини-среды и языки.
From X25LINE1 (Format=AB123)
Если подобное происходит в универсальном языке программирования, то выдается стандартное сообщение об ошибке:
Syntax error: undeclared identifier
Используя мини-язык, вместо этого можно создать сообщение об ошибке, используя словарь предметной области:
"АВ123" is not a format. Known formats are ABC123, XYZ43B, PDQB, and 42.
Вы можете реализовать и более сложный язык с более формальным синтаксисом. Хитрость состоит в том, чтобы вначале определить синтаксис, используя систему обозначений, подобную нормальной форме Бэкуса-Наура [12]. Как только вы определили грамматику, ее обычно легко преобразовать во входной синтаксис для генератора. Программисты, работающие с языками С и С++, давно используют уасс (или его бесплатную версию bison [URL 27]). Подробное описание этих программ приводится в книге "Lex and Yacc" [LMB92]. Программисты, работающие с языком Java, могут поработать с программой javaCC, которая находится на сайте [URL 26]. В ответе к упражнению 7 (Приложение В) дана программа грамматического разбора, написанная с помощью bison. Пример показывает, что как только вы изучите синтаксис, написание мини-языков не представит сложности.
Существует другой способ реализации мини-языка: расширить существующий. Например, можно интегрировать функциональные возможности на уровне приложения при помощи Python [URL 9] и написать нечто вроде [13]:
record = X25UNE1.get(format=ABC123)
if (record.balanc<0):
X25UNE1.put(record, format=ABC123)
else:
TELSTR1.put(record, format=XYZ43B)
DB.store(record)
Языки управления даннымисоздают некую форму структуры данных, используемой приложением. Эти языки часто используются для представления конфигурации.
Например, программа sendmail применяется во всем мире для маршрутизации электронной почты в сети Интернет. Она обладает многими достоинствами и преимуществами, которые управляются огромным файлом конфигурации, написанном на собственном языке конфигурирования программы sendmail:
Уже давно фирма Microsoft использует язык данных, который может описывать меню, реквизиты окон, диалоговые окна и другие ресурсы Windows. На рис. 2.2 показан фрагмент типичного файла ресурсов. Он читается намного легче, чем пример с программой sendmail, но используется точно так же – компилируется для генерации структуры данных.
Рис. 2.2. Файл .rc для Windows
Процедурные языкиидут дальше. В этом случае язык является исполняемым и поэтому может содержать инструкции, конструкции управления и т. п. (подобные сценарию на с. 50).
Вы также можете использовать собственные процедурные языки, чтобы облегчить сопровождение программы. Например, вас просят интегрировать информацию из унаследованного приложения в новую разработку графического интерфейса. Обычно это осуществляется при помощи "экранного кармана"; ваше приложение связывается с основным (mainframe) приложением так, как если бы это обычный пользователь-человек, генерируя нажатия клавиш и «считывая» принимаемые отклики. Вы можете создать сценарий взаимодействия при помощи мини-языка
Обычная альтернатива является своего рода тяжеловесным техническим подходом: программа разделяется на модули, которые программируются в вакууме. Модули объединены в подсистемы, которые затем подлежат дальнейшему объединению, пока в один прекрасный день вы не получаете завершенное приложение. И только тогда приложение в целом может быть представлено пользователю и протестировано. Технология программы трассировки имеет много преимуществ:
• Пользователи могут увидеть нечто, работающее еще до выпуска окончательной версии.Если вам удалось передать суть делаемого вами (см. "Большие надежды"), то ваши пользователи будут осознавать, что видят перед собой еще нечто незрелое. Они не будут разочарованы отсутствием функциональных возможностей; будут гореть желанием увидеть некий видимый прогрессе создании их системы. По мере того как проект будет продвигаться, они начнут делать вложения. Эти пользователи и станут теми людьми, которые скажут вам о том, насколько близко к цели находится та или иная итерация.
• Разработчики выстраивают некую структуру, в которой они работают.Наибольший страх вызывает лист бумаги, на котором ничего не написано. Если вы разработали все механизмы взаимодействия между модулями вашего приложения и воплотили их в тексте программы, то вашей команде не придется многое высасывать из пальца. Это делает труд каждого члена команды более производительным и способствует последовательности в их работе.
• У вас есть платформа для интеграции.Как только все компоненты системы связаны друг с другом, появляется некая среда, в которую можно добавлять новые фрагменты программ, прошедшие модульное тестирование. Вы будете заниматься интеграцией каждый день (иногда несколько раз вдень), не пытаясь интегрировать все сразу по методу "большого скачка". Воздействие каждого вновь вносимого изменения становится более очевидным, взаимодействия более ограниченными, поэтому отладка и тестирование будут более быстрыми и точными.
• У вас есть что продемонстрировать.Спонсоры проекта и руководство стремятся увидеть демонстрационные версии в самое неподходящее время. При наличии программы трассировки у вас всегда будет то, что можно им продемонстрировать.
• Вы лучше ощущаете прогресс.При разработке программы трассировки программисты работают над сценариями использования системы по очереди. Они заканчивают один сценарий и переходят к следующему. При этом гораздо проще определить производительность и продемонстрировать пользователю продвижение проекта. Поскольку каждая индивидуальная разработка меньше по объему, вы избежите создания монолитных программных блоков, о которых каждую неделю сообщается, что они готовы на 95 %.
При стрельбе трассирующими вы не всегда попадаете в цель
Трассирующие пули показывают, что вы куда-то попали. Это не обязательно должна быть ваша цель. Затем вы корректируете прицел, пока пули не попадают в цель. В этом-то все и дело.
То же самое относится и к программе трассировки. Вы используете методику в ситуациях, когда не уверены на 100 %, куда же вам двигаться. Не стоит удивляться, если две первых попытки сорвались: пользователь говорит: "Это совсем не то, что я имел в виду", нужные данные становятся недоступными в самый неподходящий мо-мент, и явно возникают проблемы с производительностью. Выработайте подход для изменения того, что мешает приблизиться к цели, и будьте благодарны судьбе, что вы используете скудную методологию разработки. Небольшой фрагмент программы отличается малой инерцией – его легко и быстро изменить. Вы сможете собрать отклики на ваше приложение и сгенерировать новую, более точную версию быстрее и дешевле. И поскольку каждый основной компонент приложения представлен в программе трассировки, ваши пользователи могут быть уверены – то, что они видят, основано на реальности, а не на бумажных спецификациях.
То же самое относится и к программе трассировки. Вы используете методику в ситуациях, когда не уверены на 100 %, куда же вам двигаться. Не стоит удивляться, если две первых попытки сорвались: пользователь говорит: "Это совсем не то, что я имел в виду", нужные данные становятся недоступными в самый неподходящий мо-мент, и явно возникают проблемы с производительностью. Выработайте подход для изменения того, что мешает приблизиться к цели, и будьте благодарны судьбе, что вы используете скудную методологию разработки. Небольшой фрагмент программы отличается малой инерцией – его легко и быстро изменить. Вы сможете собрать отклики на ваше приложение и сгенерировать новую, более точную версию быстрее и дешевле. И поскольку каждый основной компонент приложения представлен в программе трассировки, ваши пользователи могут быть уверены – то, что они видят, основано на реальности, а не на бумажных спецификациях.
Программа трассировки и создание прототипов
Вы могли бы подумать, что принцип программы трассировки – это то же самое, что и чем создание прототипов, только с более агрессивным названием. Отличие есть. Цель работы с прототипом – исследование определенных характеристик (аспектов) конечной версии системы. Создавая истинный прототип, вы отбросите все то, что критиковали при опробовании принципа, и перепишете его надлежащим образом, используя полученные уроки.
Например, вы создаете приложение, которое помогает транспортным компаниям определять, как упаковывать ящики нестандартного размера в контейнеры. Помимо всего прочего, интерфейс пользователя должен быть интуитивно понятным, а алгоритмы, используемые для определения оптимальной упаковки, очень сложны.
Вы могли бы создать интерфейс для конечных пользователей при помощи соответствующих инструментальных средств. Вашей программы достаточно для того, чтобы сделать интерфейс восприимчивым к действиям пользователя. Как только пользователи согласятся с компоновкой интерфейса, вы можете отбросить его и переписать на этот раз на основе бизнес-логики, используя целевой язык. Аналогично, вы можете захотеть создать прототип ряда алгоритмов, которые осуществляют реальную упаковку. Вы можете запрограммировать функциональные тесты на высокоуровневом, «всепрощающем» языке типа Perl и затем запрограммировать низкоуровневые тесты производительности на языке, который более близок к машинному. В любом случае, как только вы приняли решение, необходимо начать сначала и запрограммировать алгоритмы в окончательной версии среды, которая взаимодействует с внешним миром. Это и есть создание прототипов, и это очень полезно.
Подход типа "стрельба трассирующими" обращается к иной проблеме. Вам необходимо знать, как работает приложение в целом. Вы хотите показать вашим пользователям, как на практике осуществляется взаимодействие, и дать им «скелет» архитектуры, на который наращивается тело программы. В этом случае вы можете сконструировать программу трассировки, состоящую из тривиальной реализации алгоритма упаковки контейнера (возможно, нечто вроде FIFO), и простой, но работающий интерфейс пользователя. Как только вы соедините все компоненты приложения, у вас уже есть каркас, который можно представить вашим пользователям и разработчикам. Спустя некоторое время вы добавляете к этому каркасу новую функциональную возможность, заменяя заглушки программами. Но сам остов остается нетронутым, и вы знаете, что система будет вести себя так же, как и в тот момент, когда завершалась первая программа трассировки.
Различие достаточно важно, чтобы гарантировать повторяемость. Прототипы генерируют одноразовую программу. Программа трассировки является скудной, но завершенной; она образует часть «скелета» конечной версии системы. Рассматривайте создание прототипов как рекогносцировку и сбор данных разведки до начала стрельбы трассирующими.
• Прототипы и памятные записки
• Западня спецификации
• Большие надежды
Например, вы создаете приложение, которое помогает транспортным компаниям определять, как упаковывать ящики нестандартного размера в контейнеры. Помимо всего прочего, интерфейс пользователя должен быть интуитивно понятным, а алгоритмы, используемые для определения оптимальной упаковки, очень сложны.
Вы могли бы создать интерфейс для конечных пользователей при помощи соответствующих инструментальных средств. Вашей программы достаточно для того, чтобы сделать интерфейс восприимчивым к действиям пользователя. Как только пользователи согласятся с компоновкой интерфейса, вы можете отбросить его и переписать на этот раз на основе бизнес-логики, используя целевой язык. Аналогично, вы можете захотеть создать прототип ряда алгоритмов, которые осуществляют реальную упаковку. Вы можете запрограммировать функциональные тесты на высокоуровневом, «всепрощающем» языке типа Perl и затем запрограммировать низкоуровневые тесты производительности на языке, который более близок к машинному. В любом случае, как только вы приняли решение, необходимо начать сначала и запрограммировать алгоритмы в окончательной версии среды, которая взаимодействует с внешним миром. Это и есть создание прототипов, и это очень полезно.
Подход типа "стрельба трассирующими" обращается к иной проблеме. Вам необходимо знать, как работает приложение в целом. Вы хотите показать вашим пользователям, как на практике осуществляется взаимодействие, и дать им «скелет» архитектуры, на который наращивается тело программы. В этом случае вы можете сконструировать программу трассировки, состоящую из тривиальной реализации алгоритма упаковки контейнера (возможно, нечто вроде FIFO), и простой, но работающий интерфейс пользователя. Как только вы соедините все компоненты приложения, у вас уже есть каркас, который можно представить вашим пользователям и разработчикам. Спустя некоторое время вы добавляете к этому каркасу новую функциональную возможность, заменяя заглушки программами. Но сам остов остается нетронутым, и вы знаете, что система будет вести себя так же, как и в тот момент, когда завершалась первая программа трассировки.
Различие достаточно важно, чтобы гарантировать повторяемость. Прототипы генерируют одноразовую программу. Программа трассировки является скудной, но завершенной; она образует часть «скелета» конечной версии системы. Рассматривайте создание прототипов как рекогносцировку и сбор данных разведки до начала стрельбы трассирующими.
Другие разделы, относящиеся к данной теме:
• Приемлемые программы• Прототипы и памятные записки
• Западня спецификации
• Большие надежды
11
Прототипы и памятные записки
Для опробования определенных идей во многих отраслях промышленности используются прототипы; это дешевле, чем организовывать полномасштабное производство. Например, в автомобильной промышленности для новой модели автомобиля может быть построено несколько различных прототипов. Каждый из них конструируется для проверки определенных свойств автомобиля – аэродинамики, дизайна, свойств конструкции и т. д. Для испытания в аэродинамической трубе изготовляется модель из глины, для отдела дизайна создается модель из бальзовой древесины и клейкой ленты и т. д. Некоторые автомобильные фирмы идут дальше и осуществляют значительную часть работы по моделированию при помощи компьютеров, что приводит к еще большему сокращению расходов. В этом случае нет необходимости в реальном изготовлении рискованных элементов конструкции для их опробования.
Мы создаем прототипы программ тем же образом и по тем же причинам – для анализа и выявления риска, предлагая возможности для коррекции при существенно меньших затратах. Подобно тому, как это делается в автомобильной промышленности, мы можем использовать прототип для опробования одного или нескольких характеристик проекта.
Мы склонны полагать, что основой прототипов являются программы, но не это не всегда так. Подобно тому, как это делается в автомобильной промышленности, мы можем строить прототипы из различных материалов. Памятные записки великолепно подходят для создания прототипов таких динамических объектов, как логика документооборота и прикладная логика. Прототип интерфейса может моделироваться на лекционной доске, как модель без функциональных возможностей, изображенная с помощью графической программы или программы-построителя интерфейса.
Прототипы разрабатываются для того, чтобы ответить лишь на несколько вопросов, поэтому их разработка намного дешевле и быстрее, чем приложения, которые идут в производство. Программа может игнорировать незначительные подробности – незначительные в данный момент, но позже могущие оказаться для пользователя очень важными. Если, к примеру, вы создаете прототип графического интерфейса пользователя, то можете смириться с неправильными результатами или данными. С другой стороны, если вы просто исследуете характеристики вычислений или производительности, можете обойтись скудным графическим интерфейсом пользователя или вообще без него.
Но если вы работаете в среде, где нельзя отказаться от подробностей, тогда необходимо спросить себя, а нужно ли вообще создавать прототип. Возможно, в этом случае лучше всего подходит стиль разработки типа "стрельба трассирующими" (см. "Стрельба трассирующими").
Мы создаем прототипы программ тем же образом и по тем же причинам – для анализа и выявления риска, предлагая возможности для коррекции при существенно меньших затратах. Подобно тому, как это делается в автомобильной промышленности, мы можем использовать прототип для опробования одного или нескольких характеристик проекта.
Мы склонны полагать, что основой прототипов являются программы, но не это не всегда так. Подобно тому, как это делается в автомобильной промышленности, мы можем строить прототипы из различных материалов. Памятные записки великолепно подходят для создания прототипов таких динамических объектов, как логика документооборота и прикладная логика. Прототип интерфейса может моделироваться на лекционной доске, как модель без функциональных возможностей, изображенная с помощью графической программы или программы-построителя интерфейса.
Прототипы разрабатываются для того, чтобы ответить лишь на несколько вопросов, поэтому их разработка намного дешевле и быстрее, чем приложения, которые идут в производство. Программа может игнорировать незначительные подробности – незначительные в данный момент, но позже могущие оказаться для пользователя очень важными. Если, к примеру, вы создаете прототип графического интерфейса пользователя, то можете смириться с неправильными результатами или данными. С другой стороны, если вы просто исследуете характеристики вычислений или производительности, можете обойтись скудным графическим интерфейсом пользователя или вообще без него.
Но если вы работаете в среде, где нельзя отказаться от подробностей, тогда необходимо спросить себя, а нужно ли вообще создавать прототип. Возможно, в этом случае лучше всего подходит стиль разработки типа "стрельба трассирующими" (см. "Стрельба трассирующими").
Для чего создаются прототипы
Какие объекты можно изучать при помощи прототипов? Все, что характеризуются наличием риска. Все, что не подвергались тестированию ранее или являются абсолютно критичными для конечного варианта системы. Вес, что является недоказанным, экспериментальным или сомнительным. Вес то, с чем вы еще не освоились. Вы можете создавать прототипы:
• Архитектуры
• Новой функциональной возможности уже существующей системы
• Структуры или содержания внешних данных
• Инструментальных средств или компонентов, выпущенных фирмами-субподрядчиками
• Рабочих характеристик
• Дизайна интерфейса пользователя
Создание прототипов способствует приобретению опыта. Значение этого опыта заключается не в созданной программе, а в полученных уроках. В этом и состоит смысл создания прототипов.
• Архитектуры
• Новой функциональной возможности уже существующей системы
• Структуры или содержания внешних данных
• Инструментальных средств или компонентов, выпущенных фирмами-субподрядчиками
• Рабочих характеристик
• Дизайна интерфейса пользователя
Создание прототипов способствует приобретению опыта. Значение этого опыта заключается не в созданной программе, а в полученных уроках. В этом и состоит смысл создания прототипов.
Подсказка 16: Создавайте прототипы, чтобы учиться на них
Как использовать прототипы
Какими деталями можно пренебречь при построении прототипа?
• Корректность.Там, где это приемлемо, вы сможете использовать фиктивные данные.
• Завершенность.Прототип может функционировать лишь в ограниченном смысле, возможно, лишь с одним наперед заданным фрагментом входных данных и одним пунктом меню.
• Надежность.Процедура проверки ошибок, вероятно, будет неполной или будет отсутствовать полностью. Если вы отклоняетесь от определенного пути, то прототип может выйти из строя и сгореть, как ракета. Это нормально.
• Стиль.Неприятно признавать это, но прототип программы не имеет большого значения для комментариев или документации. При работе с прототипом можно написать горы документации, но сравнительно малая ее часть будет посвящена собственно прототипу системы.
Поскольку в прототипе детали отодвигаются на второй план, а в центре рассмотрения оказываются определенные аспекты системы, вам может показаться реальным создание прототипов с использованием языка очень высокого уровня – выше уровня языка остальной части проекта (язык типа Perl, Python или Tel). Язык сценариев высокого уровня позволяет опускать многие детали (включая указание типов данных) и при этом создавать функциональный (хотя и неполный и медленный) фрагмент программы [11]. Если вам необходимо создать прототип интерфейсов пользователей, изучите инструментальные средства типа Tcl/Tk, Visual Basic, Powerbuilder или Delphi.
Языки сценариев хороши для использования в качестве «клея» при соединении низкоуровневых фрагментов в новые сочетания. При работе в системе Windows язык Visual Basic может «скреплять» средства управления СОМ. В более общем смысле вы можете использовать языки типа Perl и Python для связывания воедино низкоуровневых библиотек языка С – вручную или автоматически при помощи инструментов наподобие бесплатного SWIG [URL 28]. Используя этот подход, вы можете быстро собрать существующие компоненты в новые конфигурации, чтобы посмотреть, как они работают.
• Корректность.Там, где это приемлемо, вы сможете использовать фиктивные данные.
• Завершенность.Прототип может функционировать лишь в ограниченном смысле, возможно, лишь с одним наперед заданным фрагментом входных данных и одним пунктом меню.
• Надежность.Процедура проверки ошибок, вероятно, будет неполной или будет отсутствовать полностью. Если вы отклоняетесь от определенного пути, то прототип может выйти из строя и сгореть, как ракета. Это нормально.
• Стиль.Неприятно признавать это, но прототип программы не имеет большого значения для комментариев или документации. При работе с прототипом можно написать горы документации, но сравнительно малая ее часть будет посвящена собственно прототипу системы.
Поскольку в прототипе детали отодвигаются на второй план, а в центре рассмотрения оказываются определенные аспекты системы, вам может показаться реальным создание прототипов с использованием языка очень высокого уровня – выше уровня языка остальной части проекта (язык типа Perl, Python или Tel). Язык сценариев высокого уровня позволяет опускать многие детали (включая указание типов данных) и при этом создавать функциональный (хотя и неполный и медленный) фрагмент программы [11]. Если вам необходимо создать прототип интерфейсов пользователей, изучите инструментальные средства типа Tcl/Tk, Visual Basic, Powerbuilder или Delphi.
Языки сценариев хороши для использования в качестве «клея» при соединении низкоуровневых фрагментов в новые сочетания. При работе в системе Windows язык Visual Basic может «скреплять» средства управления СОМ. В более общем смысле вы можете использовать языки типа Perl и Python для связывания воедино низкоуровневых библиотек языка С – вручную или автоматически при помощи инструментов наподобие бесплатного SWIG [URL 28]. Используя этот подход, вы можете быстро собрать существующие компоненты в новые конфигурации, чтобы посмотреть, как они работают.
Создание прототипов архитектуры
Многие прототипы создаются, чтобы смоделировать рассматриваемую систему в целом. В отличие от подхода типа "стрельба трассирующими", ни один из отдельных модулей в прототипе системы не должен быть особенно функциональным. На самом деле вам даже не нужно писать программу для создания прототипов – вы можете создать прототип на лекционной доске, при помощи памятных записок или каталожных карточек. Вы пытаетесь понять то, как система выглядит в собранном виде, опуская детали. Вот некоторые из конкретных областей, которые вы можете обнаружить в архитектурном прототипе:
• Четко ли определены обязанности основных компонентов, и являются ли они приемлемыми?
• Четко ли определена совместная работа основных компонентов?
• Сведено ли к минимуму связывание?
• Можно ли идентифицировать потенциальные источники дублирования?
• Можно ли применить определения интерфейсов и ограничения?
• Обладает ли каждый из модулей путем доступа к данным, требуемым ему в ходе выполнения? Может ли он получить такой доступ в случае необходимости?
Последний пункт приносит большинство сюрпризов и наиболее ценных результатов, основанных на опыте создания прототипов.
• Четко ли определены обязанности основных компонентов, и являются ли они приемлемыми?
• Четко ли определена совместная работа основных компонентов?
• Сведено ли к минимуму связывание?
• Можно ли идентифицировать потенциальные источники дублирования?
• Можно ли применить определения интерфейсов и ограничения?
• Обладает ли каждый из модулей путем доступа к данным, требуемым ему в ходе выполнения? Может ли он получить такой доступ в случае необходимости?
Последний пункт приносит большинство сюрпризов и наиболее ценных результатов, основанных на опыте создания прототипов.
Как не надо использовать прототипы
Перед тем как вы займетесь созданием любого прототипа, основанного на программе, убедитесь, что все понимают – вы пишете одноразовую программу. Прототипы могут быть обманчиво привлекательными для людей, которые не знают, что это всего лишь прототипы. Вы должны очень четко уяснить – эта программа одноразовая, незавершенная и не может быть завершена.
Легко впасть в заблуждение из-за очевидной завершенности демонстрационного прототипа, и спонсоры проекта или менеджмент могут настаивать на развертывании прототипа (или его потомства), если вы заранее не определите, что можно ожидать от прототипа. Напомните им, что вы, конечно, можете создать великолепный прототип новой модели автомобиля из бальзовой древесины и клейкой ленты, но вы же не поедете на нем в час пик!
Если вы полагаете, что в вашей среде или культуре существует большая вероятность того, что назначение прототипа программы может быть истолковано неправильно, вам лучше воспользоваться подходом "стрельба трассирующими". Вы получите некий жесткий каркас, на котором можно основывать будущие разработки.
При надлежащем использовании прототип может сэкономить вам огромное количество времени, денег, головной боли и мучений за счет идентификации и исправления потенциальных проблем в самом начале цикла разработки – затраты на устранение ошибок будут недорогими и не вызовут затруднений.
• Общайтесь!
• Стрельба трассирующими
• Большие надежды
Легко впасть в заблуждение из-за очевидной завершенности демонстрационного прототипа, и спонсоры проекта или менеджмент могут настаивать на развертывании прототипа (или его потомства), если вы заранее не определите, что можно ожидать от прототипа. Напомните им, что вы, конечно, можете создать великолепный прототип новой модели автомобиля из бальзовой древесины и клейкой ленты, но вы же не поедете на нем в час пик!
Если вы полагаете, что в вашей среде или культуре существует большая вероятность того, что назначение прототипа программы может быть истолковано неправильно, вам лучше воспользоваться подходом "стрельба трассирующими". Вы получите некий жесткий каркас, на котором можно основывать будущие разработки.
При надлежащем использовании прототип может сэкономить вам огромное количество времени, денег, головной боли и мучений за счет идентификации и исправления потенциальных проблем в самом начале цикла разработки – затраты на устранение ошибок будут недорогими и не вызовут затруднений.
Другие разделы, относящиеся к данной теме:
• Мой исходный текст съел кот Мурзик• Общайтесь!
• Стрельба трассирующими
• Большие надежды
Упражнения
4. Специалисты по маркетингу хотели бы сесть и вместе с вами провести мозговой штурм по дизайну нескольких интернет-страниц. Они думают об активных картах ссылок – для перехода к другим страницам. Но они не могут определиться с моделью ссылки: это могут быть изображения автомобиля, телефона или дома. У вас имеется перечень целевых страниц и содержания; они хотели бы увидеть несколько прототипов. Да, кстати, в вашем распоряжении 15 мин. Какими инструментами вы могли бы воспользоваться? (Ответ см. в Приложении В.)
12
Языки, отражающие специфику предметной области
Границы моего языка есть границы моего мира.
Людвиг фон Витгенштейн
Языки программирования влияют на то, как вы думаете о проблеме, и на то, как вы думаете об общении. В каждом языке имеются свои особенности – ученые словечки типа "статический и динамический контроль типов", "раннее и позднее связывание", "модели наследования" (простое, множественное или отсутствие) – все они могут предложить определенные решения или затруднить их. Решение, создаваемое в стиле Lisp, отличается от решения, основанного на мышлении приверженца языка С, и наоборот. Верно и обратное (и по нашему мнению, более важное) – язык, отражающий специфику данной области, может, со своей стороны, предложить решение в области программирования.
Мы всегда пытаемся написать программу, используя словарь, характерный для прикладной области (см. "Ловушка требований", где предлагается использовать проектный глоссарий). В ряде случаев можно перейти на следующий уровень и действительно программировать, пользуясь словарем, синтаксисом и семантикой предметной области.
Пользователи предложенной системы должны быть в состоянии точно изложить, как она должна работать:
Ожидать прихода сообщений, определенных нормативом 12.3 фирмы ABC, по каналам связи Х.25, преобразовать их в формат 43В фирмы XYZ, ретранслировать на спутниковый канал связи и сохранить для анализа в будущем.Если ваши пользователи располагают набором подобных четких инструкций, то вы можете изобрести мини-язык, скорректированный в соответствии с прикладной областью и выражающий именно то, что им нужно:
From X25LINE1 (Format=ABC123) {
Put TELSTAR1 (Format=XYZ43B);
Store DB;
}
Этот язык не должен быть исполняемым. В своем исходном виде он мог бы просто фиксировать требования пользователя – спецификации. Однако вы наверняка посчитали возможным пойти дальше и фактически реализовать язык. Ваша спецификация превратилась в исполняемую программу.
После того как вы написали приложение, пользователи предъявляют вам новое требование: сообщения с отрицательным балансом не должны сохраняться и должны отсылаться обратно по каналам связи Х.25 в первоначальном формате:
From X25LINE1 (Format=ABC123) {
if (ABC123.balance «0) {
Put X25L1NE1 (Format=ABC123);
}
else {
Put TELSTAR1 (format=XYZ43B);
Store DB;
}
}
Несложно? При наличии надлежащей поддержки вы можете программировать значительно ближе к прикладной области. Мы не предлагаем, чтобы ваши конечные пользователи программировали на этих языках. Вместо этого вы даете самому себе инструмент, который позволяет вам работать ближе к их области.
Подсказка 17: Программируйте ближе к предметной области вашей задачи
Мы полагаем, что вам следует рассмотреть способы перемещения вашего объекта ближе к предметной области проблемы – будь то простейший язык для конфигурирования и управления прикладной программой или же более сложный язык для обозначения правил или процедур. При составлении программы на более высоком уровне абстракции вам легко сосредоточиться на решении проблем предметной области и вы можете проигнорировать мелкие детали, связанные с реализацией.
Помните, что с приложением работают многие пользователи. Существует конечный пользователь, который понимает правила предметной области и то, что должно быть на выходе программы. Есть также вторичные пользователи: обслуживающий персонал, менеджеры, занимающиеся конфигурированием и тестированием, программисты служб поддержки и сопровождения и будущие поколения разработчиков. У каждого из этих пользователей есть собственная предметная область, и для всех них вы можете генерировать мини-среды и языки.
Ошибки, отражающие специфику предметной области
Если вы работаете в определенной предметной области, то можете осуществить и проверку правильности данных, характерных для нее, сообщая о проблемах языком, понятным вашим пользователям. Рассмотрим программу коммутации каналов, приведенную выше. Предположим, что пользователь неправильно обозначил наименование формата:From X25LINE1 (Format=AB123)
Если подобное происходит в универсальном языке программирования, то выдается стандартное сообщение об ошибке:
Syntax error: undeclared identifier
Используя мини-язык, вместо этого можно создать сообщение об ошибке, используя словарь предметной области:
"АВ123" is not a format. Known formats are ABC123, XYZ43B, PDQB, and 42.
Реализация мини-языка
В самом простейшем варианте мини-язык может реализовываться в строчно-ориентированном, легко анализируемом формате. Практически мы используем эту форму больше, чем любую другую. Ее просто проанализировать при помощи инструкций switch или используя регулярные выражения в языках сценариев типа Perl. Ответ к упражнению 5 (Приложение В) показывает простую реализацию мини-языка на языке С.Вы можете реализовать и более сложный язык с более формальным синтаксисом. Хитрость состоит в том, чтобы вначале определить синтаксис, используя систему обозначений, подобную нормальной форме Бэкуса-Наура [12]. Как только вы определили грамматику, ее обычно легко преобразовать во входной синтаксис для генератора. Программисты, работающие с языками С и С++, давно используют уасс (или его бесплатную версию bison [URL 27]). Подробное описание этих программ приводится в книге "Lex and Yacc" [LMB92]. Программисты, работающие с языком Java, могут поработать с программой javaCC, которая находится на сайте [URL 26]. В ответе к упражнению 7 (Приложение В) дана программа грамматического разбора, написанная с помощью bison. Пример показывает, что как только вы изучите синтаксис, написание мини-языков не представит сложности.
Существует другой способ реализации мини-языка: расширить существующий. Например, можно интегрировать функциональные возможности на уровне приложения при помощи Python [URL 9] и написать нечто вроде [13]:
record = X25UNE1.get(format=ABC123)
if (record.balanc<0):
X25UNE1.put(record, format=ABC123)
else:
TELSTR1.put(record, format=XYZ43B)
DB.store(record)
Языки управления данными и процедурные языки
Реализуемые вами языки могут использоваться двумя различными способами.Языки управления даннымисоздают некую форму структуры данных, используемой приложением. Эти языки часто используются для представления конфигурации.
Например, программа sendmail применяется во всем мире для маршрутизации электронной почты в сети Интернет. Она обладает многими достоинствами и преимуществами, которые управляются огромным файлом конфигурации, написанном на собственном языке конфигурирования программы sendmail:
Mlocal, P=/usr/bin/procmail,Очевидно, удобочитаемость не является сильной стороной sendmail.
F=lsDFMAw5:/|@qSPfhn9,
S=10/30, R=20/40,
T=DNS/RFC822/X-Unix,
A=procmail -Y -a $h -d $u
Уже давно фирма Microsoft использует язык данных, который может описывать меню, реквизиты окон, диалоговые окна и другие ресурсы Windows. На рис. 2.2 показан фрагмент типичного файла ресурсов. Он читается намного легче, чем пример с программой sendmail, но используется точно так же – компилируется для генерации структуры данных.
Рис. 2.2. Файл .rc для Windows
MAIN_MENU MENU
{
POPUP " &File"
{
MENUITEM "&New", CM_FILENEW
MENUITEM "&Open…", CM_FILEOPEN
MENUITEM "&Save", CM_FILESAVE
}
}
MY_DIALOG_BOX DIALOG 6,15,292,287
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "My Dialog Box"
FONT 8, "MS Sans Serif"
{
DEFPUSHBUTTON «OK», ID_OK, 232,16, 50,14
PUSHBUTTON «Help», ID.HELP, 232, 52, 50,14
CONTROL "Edit Text Control", ID EDIT1, "EDIT", WS_BODER | WS_TABSTOP, 16,16, 80, 56
CHECKBOX «Checkbox», ID CHECKBOX 1,153, 65,42,38, BS_AUTOCHECKBOX | WS_ABSTOP
}
Процедурные языкиидут дальше. В этом случае язык является исполняемым и поэтому может содержать инструкции, конструкции управления и т. п. (подобные сценарию на с. 50).
Вы также можете использовать собственные процедурные языки, чтобы облегчить сопровождение программы. Например, вас просят интегрировать информацию из унаследованного приложения в новую разработку графического интерфейса. Обычно это осуществляется при помощи "экранного кармана"; ваше приложение связывается с основным (mainframe) приложением так, как если бы это обычный пользователь-человек, генерируя нажатия клавиш и «считывая» принимаемые отклики. Вы можете создать сценарий взаимодействия при помощи мини-языка