Опубликован: 17.06.2015 | Доступ: свободный | Студентов: 2343 / 359 | Длительность: 13:09:00
ISBN: 978-5-9556-0174-8
Лекция 3:

Враг: предваряющий анализ

< Лекция 2 || Лекция 3: 123 || Лекция 4 >

3.3 Архитектура и проектирование

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

  • выбор абстракций (в объектно-ориентированной разработке это, в частности, абстракции данных, выражаемые как классы);
  • образцы проектирования (паттерны) – стандартные программные структуры, применимые к специфическим задачам, например, паттерн "Visitor" (Посетитель) поддерживает обход структур данных;
  • спецификации интерфейса (взаимодействия) между модулями;
  • определение структуры наследования, позволяющей организовать множество связанных абстракций в подходящую таксономию.

Существует некоторое различие в понятиях "проектирование" и "архитектура". Для ясности в данном контексте будем использовать термин "проектирование" для обозначения процесса, а "архитектура" – для результата процесса. Такое же соглашение будет действовать для терминов "реализация" и "код".

3.3.1 Отделено ли проектирование от реализации?

Многие традиционные методы программной инженерии представляют проектирование как отдельный независимый этап. Тем не менее, растет понимание того, что не существует четкой границы между проектированием и реализацией. Еще в 1968 году конференция, где программная инженерия зарождалась как научная дисциплина, включала сессию, посвященную разнице между проектированием и производством (как тогда называли реализацию). В своем выступлении Питер Наур [NATO 1968] сказал:

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

Ему вторит Эдсгер Дейкстра:

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

В статье Джека Ривса [Reeves 1992–2005], написанной еще в 1992 году и часто цитируемой сторонниками agile, утверждается об ошибочности говорить о том, что проектирование в программной инженерии представляет независимую деятельность. Аргументы Ривса таковы: в традиционной инженерии под проектированием понимается деятельность по созданию документации, которая затем используется в производственном процессе. В программной инженерии "производственный процесс" соответствует сборке системы (компиляции и связыванию модулей системы) и выполняется главным образом не людьми, а специальным инструментарием (компиляторами, загрузчиками, утилитой "make" и другими подобными средствами). Но затем он пишет:

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

Ривс действительно прав, если считать, что целью является сравнение двух процессов в программной и традиционной инженерии. Их проект – написание документации, наш – написание кода. Их производство – создание продукта на основе документации. Наше производство – сборка системы из написанных модулей. На этом интересном наблюдении обсуждение не должно заканчиваться, так как в программной инженерии термин "проект" использовался в своем собственном смысле, без всякой связи с тем, как этот термин понимается в строительстве или другой инженерной деятельности.

В специфическом программном смысле проектирование означает процесс определения общей структуры кода. Различие с реализацией определяется уровнем абстракции. Пусть я написал код

across subscribers as sub loop
	sub.item.update (arguments)
end

Этот код применяет операцию update с заданными аргументами arguments к полю item каждого элемента sub из списка подписчиков subscribers. Я дал вам код. Если я теперь упомяну, что использовал образец проектирования – паттерн "Observer" (Наблюдатель) [Gamma 1994, Meyer 2009], то я говорю вам об архитектуре, концепции, стоящей за спиной кода. В этом классическом архитектурном решении программный элемент при всяком изменении (например, изменился курс акций) посылает сигнал, приходящий ко всем программным элементам, включенным в список подписчиков, каждый из которых выполняет свои действия по обновлению. Например, элемент интерфейса покажет новый курс, другой элемент обновит данные в базе данных. Каждый из подписчиков выполняет свою операцию обновления – update.

Ясно, что код – это все, что мы имеем в конечном счете. Выполняется код, а не архитектурные элементы (такие, как паттерны проектирования). Но, чтобы построить этот код, понять его, когда он уже существует, критически важными являются знание и понимание элементов проектирования. Как только кто-то скажет: "Давайте используем здесь паттерн Observer", компетентный программист может произвести соответствующий код. Если код уже существует, то знание того, что это не просто произвольный код, а код, представляющий реализацию Observer, критически важно для дальнейшей успешной работы.

Большая разница между программной инженерией и другими видами инженерии состоит в том, что здесь нет четкой границы между проектной документацией и кодом. Языки проектирования выглядят подозрительно похожими на языки программирования, даже UML диаграммы могут отображаться в код. Реализация (перефразируя известную цитату Клаузевица1Война есть продолжение политики другими средствами.) – это проектирование, продолженное другими средствами. Под другими средствами здесь понимается другой уровень абстракции.

Еще одна интересная характеристика программирования в том, что здесь, в отличие от других областей инженерии, может иметь смысл выполнять проектирование – производить документацию – после написания кода или частично до написания, частично после написания. Это хорошо объяснено в классической статье по программной инженерии: Парнас и Клементс "Рациональный процесс проектирования: Как и почему он имитируется" [Parnas 1980]. Заголовок отражает основную идею. Что привело к тому, что проект закончился созданием кода с хорошей архитектурой? Значительно реже мы спрашиваем, как была получена хорошая архитектура и, в особенности, когда – перед реализацией, как принято в жесткой модели "водопада", во время реализации, когда проектирование и реализация пересекаются, или после – для улучшения убогого документа. Возможно, применяется комбинация всех трех подходов. И это то, что, по мнению Парнаса, означает имитацию, подделку процесса проектирования [Parnas 1986]. Нечто подобное встречается в математике. Математическая статья представляет отполированный текст, описывающий последовательный путь вывода, где каждое утверждение следует из предыдущего и влечет справедливость следующего утверждения. Но если спросить математика, как он получил конечный результат, то он опишет (как это сделал Адамар в классической книге [Hadamard 1945]) намного более беспорядочный процесс, где интуиция играет такую же большую роль, как и строгость. Цель оправдывает средства.

Даты публикации цитируемых статей показывают, что проблема взаимодействия проектирования и реализации с давних пор волнует программистов. Эволюция программной инженерии в последние десятилетия, в частности распространение объектно-ориентированной технологии (приводящее к бесшовной разработке), языки высокого уровня, предлагающие высокоуровневые механизмы абстракции, делают эти близкие отношения видимыми.

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

3.3.2 Agile методы и проектирование

Все agile методы сходятся на критике любого процесса, включающего независимый этап проектирования. В то же время нет единого agile подхода к проектированию. Важно представить эти подходы в утвердительной форме (делай так…), хотя следует заметить, что чаще они излагаются в agile презентациях в форме реакции на "неправильные" подходы (вместо того, чтобы делать…). Три ключевые идеи характеризуют agile точку зрения на проектирование:

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

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

Активным защитником идеи проектирования на уровне индивидуальной итерации является Ларман [Larman 2010]. Вот некоторые его высказывания по поводу того, когда следует заниматься проектированием:

"В начале построения каждого нового элемента";

"В тот самый момент, и ни в какой другой, когда команда сочтет полезным моделировать заказ, представленный на стене".

Стена в его описании – безграничное пространство, сплошь покрытое пользовательскими историями и другими материалами.

С замечательной откровенностью agile тексты описывают ограничения agile подхода к проектированию. Большая часть обсуждения проектирования у Кона [Kohn 2010] посвящена описанию того, что может пойти не так "в жизни без предваряющего проектирования":

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

Действительно, эти обстоятельства следует учитывать при рассмотрениях.

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

Подобные заключения заходят слишком далеко. Я совершенно уверен, что Дейкстра (хотя его нет среди нас, и он не может подтвердить мои слова) совсем иное имел в виду, когда говорил о схожести реализации и проектирования. Два типичных примера:

  • Безопасность. Общепризнанным в кругах безопасности считается высказывание: "безопасность нельзя обеспечить, если вы не подумали об этом заранее". В такой категоричной форме оно так же некорректно, как и противоположное мнение: "забудьте о безопасности, пока не закончите проект". Эксперты посоветуют вам позаботиться о безопасности на самых ранних этапах и продолжать эту работу на всем протяжении.
  • Многоязычный пользовательский интерфейс. Есть существенная разница в проектировании системы, поддерживающей многие языки, – диалоги, сообщения об ошибках и прочее. Достаточно просто использовать соответствующее архитектурное решение, если принять его на ранних стадиях проекта. Довольно трудно перестроить систему, построенную как моноязычная.

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

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

3.4 Модели жизненного цикла

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

"Определить" и "стандартизовать". Модели жизненного цикла играют две различные роли, часто перемешанные. Одна из них чисто дескриптивная: попытка описать то, как работает успешная команда. Другая – предписывающая: указывает на то, как должна работать команда. Это различие заложено уже в самом использовании слова "модель" в повседневном языке. Математическая модель предполагает описание, а ролевая задает предписание для человека, выступающего в этой роли.

Модели жизненного цикла, понимаемые в предписывающем смысле, подвергались нападкам, начиная со статьи 1982 года с недвусмысленным заголовком "О вредной концепции жизненного цикла", написанной Мак Кракеном и Джексоном [McCracken 1982]. Школа agile также продолжает обстрел традиционных моделей жизненного цикла, отстаивая более гибкие виды процесса разработки.

Прежде чем присоединиться к партии нападок на "водопад", полезно понять три аргумента в пользу рассмотрения подобных "водопаду" моделей.

  • Исторический аргумент. На заре программной индустрии строгие модели жизненного цикла были здоровой реакцией на полностью неформальные подходы, которые можно характеризовать как "раньше код, думать будем потом" или "хакерство" (понимаемое как погружение в код, а не как угроза безопасности в сегодняшнем понимании). Модели жизненного цикла внесли порядок в процесс разработки. Они отражали необходимость разделения деятельности, предшествующей реализации, и деятельности, осуществляемой после построения кода. Сегодня приемы индустрии намного изощреннее, они уходят от простых моделей жизненного цикла – это наблюдение справедливо и для agile методов независимо от присущих им ограничений. Простые модели сыграли свою роль в достижении современного состояния.
  • Концептуальный аргумент. Даже если мы перестанем говорить об анализе, реализации, верификации и проверке правильности как об упорядоченных во времени этапах, то все равно остается полезным понимание этих различающихся видов деятельности.
  • Педагогический аргумент. При обучении программной инженерии удобно объяснять эти виды деятельности, обсуждать идеализированную линейную последовательность выполнения, объяснять, почему успешная разработка ПО требует гибких схем разработки.

Остающееся современным обсуждение модели "водопада" связано прежде всего с педагогическим аргументом: модель играет роль контраста, на фоне которого можно убеждать в полезности новых подходов. Эта роль важна. Подумайте о политических науках, где рассматриваются монархия, абсолютизм власти. Вряд ли профессору приходит мысль агитировать за возвращение стиля правления Людовика XIV, но анализ того, почему в свое время люди предпочитали такой стиль управления, какие уроки следует из этого извлечь, необходимы. Все это учит нас применять более современные способы управления.

Помимо этой роли, "водопад" сегодня дискредитирован и его agile критика вполне корректна.

Понятие модели, несмотря на 30-летнюю критику Мак Кракена и Джексона, не ушло со сцены как в своей описательной, так и в предписывающей роли. Например, при изучении Scrum полезно знакомство с его моделью жизненного цикла: последовательными одномесячными спринтами, сопровождаемыми специфическим планированием и обзором этапов. Модель жизненного цикла может помочь в структурировании любых инженерных усилий до тех пор, пока она используется как руководство к действию, но не является барьером для креативного подхода.

Обсуждение модели жизненного цикла имеет тенденцию колебания между двумя словами в заголовке книги Зигмунда Фрейда "Тотем и табу". Ни одно из них не подходит. Каждый проект нуждается во временных рамках, предсказании и оценке его прогресса. Это может выполняться более последовательно, приближаясь к идеям "водопада", или более итеративно, в духе Scrum, или некоторой комбинацией этих и других идей. Определение и стандартизация каркаса – только одна из составляющих успеха проекта.

< Лекция 2 || Лекция 3: 123 || Лекция 4 >
Алексей Задойный
Алексей Задойный

В главе "5: Роли agile" http://www.intuit.ru/studies/courses/3505/747/lecture/26297?page=2 есть упоминание:

Скримшир [Scrimshire сайт]

но нет адреса сайта. Укажите пожалуйста адрес в тексте лекции.

Или речь о человеке James Scrimshire?

Павел Плахотник
Павел Плахотник

http://www.intuit.ru/studies/courses/3505/747/lecture/26293

Сделайте пожалуйста вопросы более корректными. Это сложно конечно. Но надо четко понимать что именно имеется в виду.

По предварительному анализу, водопаду, документам требований вообще не понятно что имеется в виду. Возможно надо будет изменить авторский текст, но всё же ясность и конкретность важна. А её нет.