Kitabı oxu: «Программная инженерия. Теория и практика»

Şrift:

Введение

Иан Соммервилл в своей книге «Инженерия программного обеспечения» определяет программную инженерию как интегрирование принципов математики, информатики и компьютерных наук с инженерными подходами, разработанными для производства осязаемых материальных артефактов. Дисциплина программной инженерии включается в круг вопросов компьютинга (англ. computing) и может рассматриваться как инженерная область, имеющая более тесные связи со своей базовой дисциплиной – компьютерными науками, чем другие инженерные области [1]. Среди других инженерных дисциплин она качественно выделяется нематериальностью программного обеспечения и дискретной природой его функционирования. Основываясь на математике и компьютинге, программная инженерия занимается разработкой систематических моделей и надежных методов производства высококачественного программного обеспечения, и данный подход распространяется на все уровни – от теории и принципов до реальной практики создания программного обеспечения, которая лучше всего заметна сторонним наблюдателям.

Термин «инженерия программного обеспечения» появился впервые в 1968 г. на конференции НАТО «Инженерия программного обеспечения» и должен был спровоцировать размышления относительно текущего в то время «кризиса программного обеспечения». С тех пор он стал использоваться для определения как профессии, так и области исследований, посвященных созданию программного обеспечения, которое имеет более высокое качество, более доступно, поддерживаемо и быстрее строится.

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

Все же несмотря на юность профессии, будущее области радужно. Так, Money Magazine и Salary.com оценили профессию разработчика программного обеспечения как лучшую работу в Америке в 2006 г.

В настоящее время существует как минимум три основополагающих документа в области программной инженерии. Это SWEBOK (Software Engineering Body of Knowledge) – документ, подготавливаемый комитетом Software Engineering Coordinating Committee, в который вовлечено сообщество IEEE Computer Society (IEEE-CS). Назначение SWEBOK – в объединении знаний по инженерии программного обеспечения (разработке программного обеспечения), Второй документ – Software Engineering Code of Ethics and Professional Practice, посвящен этическим и профессиональным стандартам для инженерии ПО, выпущен в 1998 г. Третий документ (SE2004), выпущенный в 2004 г., посвящен составлению учебного плана по программной инженерии.

Эти документы созданы совместными усилиями IEEE-CS и Association for Computing Machinery (ACM) и призваны определить следующее:

• необходимый набор знаний и рекомендуемые практики;

• этические и профессиональные стандарты;

• учебную программу для студентов, аспирантов и продолжающих обучение.

В рамках изучения дисциплины «Программная инженерия» сложно охватить весь объем накопленных в этой области знаний. Этот учебник представляет собой попытку собрать основные компоненты необходимых наборов знаний, умений и рекомендуемых практик в рассматриваемой дисциплине. В первую очередь он предназначен для студентов, обучающихся по направлению подготовки «Прикладная информатика». Также он будет небезынтересен людям, непосредственно занимающимся разработкой и проектированием различных информационных систем, в аспекте систематизации и актуализации знаний по программной инженерии.

Учебник состоит из теоретического курса и практикума. Для успешного освоения теории необходимо использовать так называемые карты памяти. Обратите внимание, что первые карты памяти нужно рисовать «вручную». Впоследствии, особенно при «массовом» процессе использования карт памяти, целесообразно пользоваться инструментами. Мы рекомендуем продукт Comapping (www.comapping.com).

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

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

Часто задания с помощью карт памяти оказываются не совсем картами памяти. Исчезает центральный объект, вместо него появляется произвольный «плоский» граф. Также полезно оказывается рисовать имена связям. Мы все равно называем такие графы картами памяти, чтобы терминологически не усложнять ситуацию.

Теоретический курс

1. Методы и средства программной инженерии

Понятие программной инженерии. Основные определения: информатика, системотехника, бизнес-реинжиниринг. Программное обеспечение: определение, свойства.

1.1. Введение в программную инженерию

Чем программирование отличается от программной инженерии [2]? Тем, что первое является некоторой абстрактной деятельностью и может происходить во многих контекстах. Можно программировать для удовольствия, для того, чтобы научиться (например, на уроках, на семинарах в университете), можно программировать в рамках научных разработок, а можно заниматься промышленным программированием. Как правило, это происходит в команде. При этом необходимо точно понимать, что нужно заказчику, выполнить работу в определенные сроки и результат должен быть нужного качества – того, которое удовлетворит заказчика и за которое он заплатит. Чтобы удовлетворить этим требованиям, программирование «обрастает» различными дополнительными видами деятельности: разработкой требований, планированием, тестированием, конфигурационным управлением, проектным менеджментом, созданием различной документации (проектной, пользовательской и пр.).

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

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

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

Все эти и другие дополнительные виды деятельности, выполняемые в процессе промышленного программирования и необходимые для успешного выполнения заказов, и будем называть программной инженерией (software engineering). Хотя еще в 70-х гг. прошлого столетия академиком А.П. Ершовым термин software engineering переводился на русский язык как «технология программирования», программная инженерия – более современный, но менее традиционный перевод этого же термина, предложенный в конце 90-х И.В. Поттосиным. Получается, что так мы обозначаем, во-первых, некоторую практическую деятельность, а во-вторых, специальную область знания, или, другими словами, научную дисциплину. Ведь для облегчения выполнения каждого отдельного проекта, для возможности использовать разнообразный положительный опыт, достигнутый другими командами и разработчиками, этот самый опыт подвергается осмыслению, обобщению и надлежащему оформлению. Так появляются различные методы и практики (best practices) – тестирования, проектирования, работы над требованиями, архитектурных шаблонов, а также стандарты и методологии, касающиеся всего процесса в целом (например, MSF, RUP, CMMI, Scrum). Вот эти-то обобщения и входят в программную инженерию как в область знания.

Необходимость в программной инженерии как в специальной области знаний была осознана мировым сообществом в конце 60-х гг. прошлого века, более чем на 20 лет позже рождения самого программирования, если считать таковым знаменитый отчет фон Неймана «First Draft of a Report on the EDVAC», обнародованный им в 1945 г. Рождением программной инженерии является 1968 г. – конференция НАТО «Software Engineering», г. Гармиш (ФРГ), которая целиком была посвящена рассмотрению этих вопросов. В сферу программной инженерии попадают все вопросы и темы, связанные с организацией и улучшением процесса разработки ПО, управлением коллективом разработчиков, созданием и внедрением программных средств поддержки жизненного цикла ПО. Программная инженерия использует достижения информатики, тесно связана с системотехникой, часто предваряется бизнес-реинжинирингом (рис. 1). Немного подробнее об этом контексте программной инженерии.

Информатика (computer science) – это свод теоретических наук, основанных на математике и посвященных формальным основам вычислимости. Сюда относят математическую логику, теорию грамматик, методы построения компиляторов, математические формальные методы, используемые в верификации и модельном тестировании и т.д. Трудно строго отделить программную инженерию от информатики, но в целом направленность этих дисциплин различна. Программная инженерия нацелена на решение проблем производства, информатика – на разработку формальных, математизированных подходов к программированию.

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

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

Рис. 1. Связь программной инженерии с другими областями


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

Это определение, данное Харальдом Милсом, известным специалистом в области программной инженерии из компании IBM, заключает в себе следующее.

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

Современное ПО предназначено, как правило, для одновременной работы со многими пользователями, которые могут быть значительно удалены друг от друга в физическом пространстве. Таким образом, вычислительная среда (персональные компьютеры, серверы и т.д.), в которой ПО функционирует, оказывается распределенной.

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

ПО развивается во времени – исправляются ошибки, добавляются новые функции, выпускаются новые версии, меняется его аппаратная база.

Таким образом, ПО является сложной динамической системой, включающей в себя технические, психологические и социальные аспекты. ПО заметно отличается от других видов систем, создаваемых (созданных) человеком – механических, социальных, научных и пр., и имеет следующие особенности, выделенные Фредериком Бруксом в его знаменитой статье «Серебряной пули нет»:

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

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

3. Изменяемость – ПО легко изменить и, как следствие, требования к нему постоянно меняются в процессе разработки. Это создает много дополнительных трудностей при его разработке и эволюции.

4. Нематериальность, или, как было в оригинале, незримость – ПО невозможно увидеть, оно виртуально. Поэтому, например, трудно воспользоваться технологиями, основанными на предварительном создании чертежей, успешно используемыми в других промышленных областях (например, в строительстве, машиностроении). Там на чертежах в схематичном виде воспроизводятся геометрические формы создаваемых объектов. Когда объект создан, эти формы можно увидеть, а ПО увидеть невозможно.

1.2. Технология программирования и ее основные этапы

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

Технологией программирования называют совокупность методов и средств, используемых в процессе разработки программного обеспечения. Как любая другая технология, технология программирования представляет собой набор технологических инструкций. Они включают:

• указание последовательности выполнения технологических операций;

• перечисление условий, при которых выполняется та или иная операция;

• описания самих операций, в которых для каждой операции определены исходные данные, результаты, а также инструкции, нормативы, стандарты, критерии и методы оценки и т.п.

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

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

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

Первый этап – «стихийное» программирование. Этот этап охватывает период от момента появления первых вычислительных машин до середины 60-х гг. XX в. В этот период практически отсутствовали сформулированные технологии и программирование фактически было искусством. Первые программы имели простейшую структуру. Они состояли из собственно программы на машинном языке и обрабатываемых ею данных. Сложность программ в машинных кодах ограничивалась способностью программиста одновременно мысленно отслеживать последовательность выполняемых операций и местонахождение данных при программировании.

Появление ассемблеров позволило вместо двоичных или 16-ричных кодов использовать символические имена данных и мнемоники кодов операций. В результате программы стали более «читаемыми».

Создание языков программирования высокого уровня, таких, как FORTRAN и ALGOL, существенно упростило программирование вычислений, снизив уровень детализации операций. Это, в свою очередь, позволило увеличить сложность программ.

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

Типичная программа того времени состояла из основной программы, области глобальных данных и набора подпрограмм (в основном библиотечных), выполняющих обработку всех данных или их части.

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

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

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

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

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

Второй этап – структурный подход к программированию (60–70-е гг. XX в.). Структурный подход к программированию представляет собой совокупность рекомендуемых технологических приемов, охватывающих выполнение всех этапов разработки программного обеспечения. В основе структурного подхода лежит декомпозиция (разбиение на части) сложных систем с целью последующей реализации в виде отдельных небольших (до 40–50 операторов) подпрограмм. С появлением других принципов декомпозиции (объектного, логического и т.д.) данный способ получил название процедурной декомпозиции.

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

Поддержка принципов структурного программирования была заложена в основу так называемых процедурных языков программирования. Как правило, они включали основные «структурные» операторы передачи управления, поддерживали вложение подпрограмм, локализацию и ограничение области «видимости» данных. Среди наиболее известных языков этой группы стоит назвать PL/1, ALGOL-68, Pascal, С.

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

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

Модульное программирование предполагает выделение групп подпрограмм, использующих одни и те же глобальные данные в отдельно компилируемые модули (библиотеки подпрограмм), например, модуль графических ресурсов, модуль подпрограмм вывода на принтер. Связи между модулями при использовании данной технологии осуществляются через специальный интерфейс, в то время как доступ к реализации модуля (телам подпрограмм и некоторым «внутренним» переменным) запрещен. Эту технологию поддерживают современные версии языков Pascal и С (C++), языки Ада и Modula.

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

Практика показала, что структурный подход в сочетании с модульным программированием позволяет получать достаточно надежные программы, размер которых не превышает 100 000 операторов. Узким местом модульного программирования является то, что ошибка в интерфейсе при вызове подпрограммы выявляется только при выполнении программы (из-за раздельной компиляции модулей обнаружить эти ошибки раньше невозможно). При увеличении размера программы обычно возрастает сложность межмодульных интерфейсов, и с некоторого момента предусмотреть взаимовлияние отдельных частей программы становится практически невозможно. Для разработки программного обеспечения большого объема было предложено использовать объектный подход.

Третий этап – объектный подход к программированию (с середины 80-х до конца 90-х гг. XX в.). Объектно-ориентированное программирование – технология создания сложного программного обеспечения, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного типа (класса), а классы образуют иерархию с наследованием свойств. Взаимодействие программных объектов в такой системе осуществляется путем передачи сообщений.

Объектная структура программы впервые была использована в языке имитационного моделирования сложных систем Simula, появившемся еще в 60-х гг. XX в. Естественный для языков моделирования способ представления программы получил развитие в другом специализированном языке моделирования – языке Smalltalk (70-е гг. XX в.), а затем был использован в новых версиях универсальных языков программирования, таких, как Pascal, C++, Modula, Java.

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

Бурное развитие технологий программирования, основанных на объектном подходе, позволило решить многие проблемы. Так были созданы среды, поддерживающие визуальное программирование, например, Delphi, C++ Builder, Visual C++ и т.д. При использовании визуальной среды у программиста появляется возможность проектировать некоторую часть, например, интерфейсы будущего продукта, с применением визуальных средств добавления и настройки специальных библиотечных компонентов. Результатом визуального проектирования является заготовка будущей программы, в которую уже внесены соответствующие коды.

Использование объектного подхода дает много преимуществ, однако его конкретная реализация в объектно-ориентированных языках программирования, таких, как Pascal и C++, имеет существенные недостатки:

• фактически отсутствуют стандарты компоновки двоичных результатов компиляции объектов в единое целое даже в пределах одного языка программирования: компоновка объектов, полученных разными компиляторами C++, в лучшем случае проблематична, что приводит к необходимости разработки программного обеспечения с использованием средств и возможностей одного языка программирования высокого уровня и одного компилятора, а значит, требует одного языка программирования высокого уровня и одного компилятора, а также наличия исходных кодов используемых библиотек классов;

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

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

Четвертый этап – компонентный подход и CASE-технологии (с середины 90-х гг. XX в. до нашего времени). Компонентный подход предполагает построение программного обеспечения из компонентов – физически отдельно существующих частей программного обеспечения, которые взаимодействуют между собой через стандартизованные двоичные интерфейсы. В отличие от обычных объектов, объекты-компоненты можно собрать в динамически вызываемые библиотеки или исполняемые файлы, распространять в двоичном виде (без исходных текстов) и использовать в любом языке программирования, поддерживающем соответствующую технологию. В настоящее время рынок объектов стал реальностью: в Интернете существуют узлы, предоставляющие большое количество компонентов, рекламой компонентов забиты журналы. Это позволяет программистам создавать продукты, хотя бы частично состоящие из повторно использованного кода, т.е. использовать технологию, хорошо зарекомендовавшую себя в области проектирования аппаратуры.

Компонентный подход лежит в основе технологий, разработанных на базе COM (Component Object Model – компонентная модель объектов), и технологии создания распределенных приложений CORBA (Common Object Request Broker Architecture – общая архитектура с посредником обработки запросов объектов). Эти технологии используют сходные принципы и различаются лишь особенностями их реализации.

Технология СОМ фирмы Microsoft является развитием технологии OLE I (Object Linking and Embedding – связывание и внедрение объектов), которая использовалась в ранних версиях Windows для создания составных документов. Технология СОМ определяет общую парадигму взаимодействия программ любых типов: библиотек, приложений, операционной системы, т.е. позволяет одной части программного обеспечения использовать функции (службы), предоставляемые другой, независимо от того, функционируют ли эти части в пределах одного процесса, в разных процессах на одном компьютере или на разных компьютерах. Модификация СОМ, обеспечивающая передачу вызовов между компьютерами, называется DCOM (Distributed COM – распределенная СОМ).

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

Каждый интерфейс имеет имя, начинающееся с символа «I» и глобальный уникальный идентификатор IID (Interface IDentifier). Любой объект СОМ обязательно реализует интерфейс ILJnknown (на схемах этот интерфейс всегда располагают сверху). Использование этого интерфейса позволяет получить доступ к остальным интерфейсам объекта.

Объект всегда функционирует в составе сервера – динамической библиотеки или исполняемого файла, которые обеспечивают функционирование объекта. Различают три типа серверов:

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

• локальный – создается отдельным процессом (модулем, ехе), который работает на одном компьютере с клиентом;

• удаленный – создается процессом, который работает на другом компьютере.

Например, Microsoft Word является локальным сервером. Он включает множество объектов, которые могут использоваться другими приложениями.

Для обращения к службам клиент должен получить указатель на соответствующий интерфейс. Перед первым обращением к объекту клиент посылает запрос к библиотеке СОМ, хранящей информацию обо всех зарегистрированных в системе классах СОМ-объектов, и передает ей имя класса, идентификатор интерфейса и тип сервера. Библиотека запускает необходимый сервер, создает требуемые объекты и возвращает указатели на объекты и интерфейсы. Получив указатели, клиент может вызывать необходимые функции объекта.

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

На базе технологии СОМ и ее распределенной версии DCOM были разработаны компонентные технологии, решающие различные задачи разработки программного обеспечения.

OLE-automation, или просто Automation (автоматизация) – технология создания программируемых приложений, обеспечивающая программируемый доступ к внутренним службам этих приложений. Вводит понятие диспинтерфейса (dispinterface) – специального интерфейса, облегчающего вызов функций объекта. Эту технологию поддерживает, например, Microsoft Excel, предоставляя другим приложениям свои службы.

ActiveX – технология, построенная на базе OLE-automation, которая предназначена для создания программного обеспечения как сосредоточенного на одном компьютере, так и распределенного в сети. Предполагает использование визуального программирования для создания компонентов – элементов управления ActiveX. Полученные таким образом элементы управления можно устанавливать на компьютер дистанционно с удаленного сервера, причем устанавливаемый код зависит от используемой операционной системы. Это позволяет применять элементы управления ActiveX в клиентских частях приложений Интернет.

Основными преимуществами технологии ActiveX, обеспечивающими ей широкое распространение, являются:

• быстрое написание программного кода, поскольку все действия, связанные с организацией взаимодействия сервера и клиента, берет на себя программное обеспечение СОМ, программирование сетевых приложений становится похожим на программирование для отдельного компьютера;

• открытость и мобильность (спецификации технологии недавно были переданы в Open Group как основа открытого стандарта);

• возможность написания приложений с использованием знакомых средств разработки (например, Visual Basic, Visual C++, Borland Delphi, Borland C++ и любых средств разработки на Java);

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

• стандартность – технология основана на широко используемых стандартах Internet (TCP/IP, HTML, Java), с одной стороны, и стандартах, введенных в свое время Microsoft и необходимых для сохранения совместимости (COM, OLE), – с другой.

MTS (Microsoft Transaction Server – сервер управления транзакциями) – технология, обеспечивающая безопасность и стабильную работу распределенных приложений при больших объемах передаваемых данных.

MIDAS (Multitier Distributed Application Server – сервер многозвенных распределенных приложений) – технология, организующая доступ к данным разных компьютеров с учетом балансировки нагрузки сети.

Все указанные технологии реализуют компонентный подход, заложенный в СОМ. Так, с точки зрения СОМ элемент управления ActiveX – внутренний сервер, поддерживающий технологию OLE-automation. Для программиста же элемент ActiveX – «черный ящик», обладающий свойствами, методами и событиями, который можно использовать как строительный блок при создании приложений.

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

Отличительной особенностью современного этапа развития технологии программирования, кроме изменения подхода, является создание и внедрение автоматизированных технологий разработки и сопровождения программного обеспечения, которые были названы CASE-технологиями (Computer-Aided Software/System Engineering – разработка программного обеспечения/программных систем с использованием компьютерной поддержки). Без средств автоматизации разработка достаточно сложного программного обеспечения на настоящий момент становится трудно осуществимой: память человека уже не в состоянии фиксировать все детали, которые необходимо учитывать при разработке программного обеспечения. На сегодня существуют CASE-технологии, поддерживающие как структурный, так и объектный (в том числе и компонентный) подходы к программированию.

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

1.3. Разработка сложных программных систем

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

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

Дополнительными факторами, увеличивающими сложность разработки программных систем, являются:

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

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

• коллективная разработка;

• необходимость увеличения степени повторяемости кодов.

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

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

Коллективная разработка. Из-за больших объемов проектов разработка программного обеспечения ведется коллективом специалистов. Работая в коллективе, отдельные специалисты должны взаимодействовать друг с другом, обеспечивая целостность проекта, что при отсутствии удовлетворительных средств описания поведения сложных систем, упоминавшемся выше, достаточно трудно. Чем больше коллектив разработчиков, тем сложнее организовать процесс работы.

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

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

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

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

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

В природе существует еще один вид иерархии – иерархия «простое – сложное», или иерархия развития (усложнения) систем в процессе эволюции. В этой иерархии любая функционирующая система является результатом развития более простой системы. Именно данный вид иерархии реализуется механизмом наследования объектно-ориентированного программирования.

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

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

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

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

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

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

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

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

• непротиворечивость – контроль согласованности элементов между собой;

• полнота – контроль на присутствие лишних элементов;

• формализация – строгость методического подхода;

• повторяемость – необходимость выделения одинаковых блоков для удешевления и ускорения разработки;

• локальная оптимизация – оптимизация в пределах уровня иерархии.

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

Каждый объект в процессе проектирования, как правило, приходится рассматривать с нескольких сторон. Различные взгляды на объект проектирования принято называть аспектами проектирования.

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

Необходимо отметить, что использование блочно-иерархического подхода применительно к программным системам стало возможным только после конкретизации общих положений подхода и внесения некоторых изменений в процесс проектирования. При этом структурный подход учитывает только свойства иерархии «целое – часть», а объектный – использует еще и свойства иерархии «простое – сложное».

Использование CASE-технологий. CASE-технологии представляют собой совокупность методологий анализа, проектирования, разработки и сопровождения сложных программных систем, основанных как на структурном, так и на объектном подходах, которые поддерживаются комплексом взаимосвязанных средств автоматизации. В основе любой CASE-технологии лежит парадигма методология/метод/нотация/средство.

Методология строится на базе некоторого подхода и определяет шаги работы, их последовательность, а также правила распределения и назначения методов. Метод определяет способ достижения той или иной цели – выполнение шага работы.

Нотацией называют систему обозначений, используемых для описания некоторого класса моделей. Нотации бывают графические (предоставление моделей в виде графов, диаграмм, таблиц, схем и т.п.) и текстовые (описания моделей на формальных и естественных языках). В CASE-технологиях нотации используют для описания структуры проектируемой системы, элементов данных, этапов обработки и т.п.

Средства – инструментарий для поддержки методов: средства создания и редактирования графического проекта, организации проекта в виде иерархии уровней абстракции, а также проверки соответствия компонентов разных уровней. Различают:

• CASE-средства анализа требований, проектирования спецификаций и структуры, редактирования интерфейсов (первое поколение CASE-I);

• CASE-средства генерации исходных текстов и реализации интегрированного окружения поддержки полного жизненного цикла разработки программного обеспечения (второе поколение CASE-II).

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

Автоматизируя трудоемкие операции, современные CASE-средства существенно повышают производительность труда программистов и улучшают качество создаваемого программного обеспечения, а именно:

• обеспечивают автоматизированный контроль совместимости спецификаций проекта;

• уменьшают время создания прототипа системы;

• ускоряют процесс проектирования и разработки ПО;

• автоматизируют формирование проектной документации для всех этапов жизненного цикла в соответствии с современными стандартами;

• частично генерируют коды программ для различных платформ разработки;

• поддерживают технологии повторного использования компонентов системы;

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

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

В табл. 1 показано, как изменяется процесс разработки ПО при переходе к использованию CASE-средств.

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

Таблица 1

Особенности процесса разработки ПО


Таблица 2

Трудозатраты на разработку сложного ПО, %


Ускорение разработки программного обеспечения. Разработка спиральной модели жизненного цикла программного обеспечения и CASE-технологий позволили сформулировать условия, выполнение которых сокращает сроки создания программного обеспечения.

Современная технология проектирования, разработки и сопровождения программного обеспечения должна отвечать следующим требованиям:

• поддержка полного жизненного цикла программного обеспечения;

• гарантированное достижение целей разработки с заданным качеством и в установленное время;

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

• минимальное время получения работоспособной системы;

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

• независимость выполняемых проектных решений от средств реализации (систем управления базами данных – СУБД, операционных систем – ОС, языков и систем программирования);

• поддержка комплекса согласованных CASE-средств, обеспечивающих автоматизацию процессов, выполняемых на всех стадиях жизненного цикла.

Этим требованиям отвечает технология RAD (Rapid Application Development – быстрая разработка приложений). Эта технология ориентирована, как следует из названия, на максимально быстрое получение первых версий разрабатываемого программного обеспечения. Она предусматривает выполнение следующих условий:

• ведение разработки небольшими группами разработчиков (3–7 человек), каждая из которых проектирует и реализует отдельные подсистемы проекта, позволяет улучшить управляемость проекта;

• использование итерационного подхода способствует уменьшению времени получения работоспособного прототипа;

• наличие четко проработанного графика цикла, рассчитанного не более чем на три месяца, существенно увеличивает эффективность работы.

Процесс разработки при этом делится на следующие этапы: анализ и планирование требований пользователей, проектирование, реализация, внедрение.

На этапе анализа и планирования требований формулируют наиболее приоритетные требования, что ограничивает масштаб проекта.

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

Под функциональной точкой в технологии RAD понимают любой из следующих функциональных элементов разрабатываемой системы:

• входной элемент приложения (входной документ или экранная форма);

• выходной элемент приложения (отчет, документ или экранная форма);

• запрос (пара «вопрос/ответ»);

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

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

Нормы, рассчитанные исходя из экспертных оценок, для систем со значительной повторяемостью кодов определяются следующим образом: менее 1 тыс. функциональных точек – 1 человек; от 1 до 4 тыс. функциональных точек – одна команда разработчиков; более 4 тыс. функциональных точек – одна команда на каждые 4 тыс. точек.

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

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

На этапе реализации выполняют итеративное построение реальной системы, при этом для контроля над выполнением требований к создаваемой системе привлекаются будущие пользователи.

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

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

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

1.4. Оценка качества процессов создания программного обеспечения

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

• международные стандарты серии ISO 9000 (ISO 9000–ISO 9004);

• СММ (Capability Maturity Model) – модель зрелости (совершенствования) процессов создания программного обеспечения, предложенная SEI (Software Engineering Institute – Институт программирования при Университете Карнеги-Меллон);

• рабочая версия международного стандарта ISO/IEC 15504: Information Technology – Software Process Assessment; эта версия более известна под названием SPICE (Software Process Improvement and Capability dEtermination – определение возможностей и улучшение процесса создания программного обеспечения).

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

СММ. Данный стандарт представляет собой совокупность критериев оценки зрелости организации-разработчика и рецептов улучшения существующих процессов.

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

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

1. Начальный уровень (initial level) описан в стандарте в качестве основы для сравнения со следующими уровнями. На предприятии такого уровня организации не существует стабильных условий для создания качественного программного обеспечения. Результат любого проекта целиком и полностью зависит от личных качеств менеджера и опыта программистов, причем успех в одном проекте может быть повторен только в случае назначения тех же менеджеров и программистов на следующий проект. Более того, если эти менеджеры или программисты уходят с предприятия, то резко снижается качество производимых программных продуктов. В стрессовых ситуациях процесс разработки сводится к написанию кода и его минимальному тестированию.

2. Повторяемый уровень (repeatable level) – на предприятии внедрены технологии управления проектами. При этом планирование и управление проектами основывается на накопленном опыте, существуют стандарты на разрабатываемое программное обеспечение (причем обеспечивается следование этим стандартам) и специальная группа обеспечения качества. В случае необходимости организация может взаимодействовать с субподрядчиками. В критических условиях процесс имеет тенденцию скатываться на начальный уровень.

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

4. Управляемый уровень (managed level) – в организации устанавливаются количественные показатели качества как на программные продукты, так и на процесс в целом. Таким образом, более совершенное управление проектами достигается за счет уменьшения отклонений различных показателей проекта. При этом осмысленные вариации в производительности процесса можно отличить от случайных вариаций (шума), особенно в хорошо освоенных областях.

5. Оптимизирующий уровень (optimizing level) характеризуется тем, что мероприятия по улучшению применяются не только к существующим процессам, но и для оценки эффективности ввода новых технологий. Основной задачей всей организации на этом уровне является постоянное улучшение существующих процессов. При этом улучшение процессов в идеале должно помогать предупреждать возможные ошибки или дефекты. Кроме того, должны вестись работы по уменьшению стоимости разработки программного обеспечения, например с помощью создания и повторного использования компонентов. Сертификационная оценка соответствия всех ключевых областей проводится по 10-балльной шкале. Для успешной квалификации данной ключевой области необходимо набрать не менее 6 баллов. Оценка ключевой области осуществляется по следующим показателям:

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

• насколько широко данная область применяется в организации, например, оценке в 4 балла соответствует фрагментарное применение;

• успешность использования данной области на практике, например, оценке в 0 баллов соответствует полное отсутствие какого-либо эффекта, а оценка в 8 баллов выставляется при наличии систематического и измеримого положительного результата практически во всей организации.

В принципе можно сертифицировать только один процесс или подразделение организации, например, подразделение разработки программного обеспечения компании IBM сертифицировано на пятый уровень. Кстати, в мире существует совсем немного компаний, которые могут похвастаться наличием у них пятого уровня СММ хотя бы в одном из подразделений (таких всего около пятидесяти). С другой стороны, насчитывается несколько тысяч компаний, сертифицированных по третьему или четвертому уровням, т.е. существует колоссальный разрыв между оптимизированным уровнем зрелости и предыдущими уровнями. Однако еще больший разрыв наблюдается между количеством организаций начального уровня и числом их более продвинутых собратьев. По некоторым оценкам, свыше 70 % всех компаний-разработчиков находится на первом уровне СММ [3].

SPICE. Стандарт SPICE унаследовал многие черты более ранних стандартов, в том числе и уже упоминавшихся ISO 9001 и СММ. Больше всего SPICE напоминает СММ. Точно так же, как и в СММ, основной задачей организации является постоянное улучшение процесса разработки программного обеспечения. Кроме того, в SPICE тоже используется схема с различными уровнями возможностей (в SPICE определено 6 различных уровней), но эти уровни применяются не только к организации в целом, но и к отдельно взятым процессам.

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

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

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

Использование формальных моделей и методов позволяет создавать понятные, непротиворечивые спецификации на разрабатываемое программное обеспечение. Конечно, внедрение таких методов имеет смысл, хотя оно весьма дорого и трудоемко, а возможности их применения весьма ограничены. Основная же проблема – проблема сложности разрабатываемого программного обеспечения с совершенствованием процессов разработки – пока не решена. Создание программного обеспечения по-прежнему предъявляет повышенные требования к квалификации тех, кто этим занимается: проектировщикам программного обеспечения и непосредственно программистам.

Контрольные вопросы

1. Дайте понятие программной инженерии.

2. Назовите дату зарождения программной инженерии как отдельной науки.

3. В чем отличие программной инженерии от информатики?

4. В чем отличие программной инженерии от системотехники?

5. Приведите примеры дисциплин информатики и программной инженерии (дисциплины не путать с учебными предметами).

6. Раскройте понятие «программное обеспечение».

7. Перечислите характеристики ПО по Бруксу и кратко охарактеризуйте каждую.

8. C какими иными видами человеческой деятельности соотносится создание ПО в данной главе?

9. Что понимают под термином «технология программирования»?

10. Что называют подходом и чем он отличается от метода?

11. Назовите основные периоды истории развития технологии программирования. Чем характеризуются эти периоды? Как изменялись основные подходы и используемые средства?

12. Дайте определение понятия «сложная иерархическая система». Какой подход используют при разработке таких систем? На каких характеристиках этих систем он основан? В чем особенность данного подхода при разработке программного обеспечения?

13. Что понимают под термином «жизненный цикл программного обеспечения»? Какие основные процессы включают в это понятие?

14. Назовите основные этапы разработки программного обеспечения. Какие основные задачи решаются на этих этапах?

15. Назовите основные модели жизненного цикла программного обеспечения. С чем связано появление новых моделей?

16. Какие технологии называют CASE-технологиями? Почему?

17. Назовите основные составляющие любой CASE-технологии.

18. Перечислите основные положения технологии RAD. Какие программные системы нельзя разрабатывать с использованием этой технологии?

19. Что понимают под моделями качества процессов разработки программного обеспечения? Для чего они разработаны? Что гарантирует сертификация качества процессов? Почему?

20. Почему мы говорим, что современный этап развития технологии программирования характеризуется переходом от ремесленного к промышленному производству программного обеспечения?

Задания

1. С помощью карт памяти максимально полно ответьте на вопрос: что такое программная инженерия (учитывая все измерения этого термина, мелкие и крупные детали)?

2. С помощью карт памяти нарисуйте взаимосвязи характеристик ПО по Бруксу, пользуясь надписями на дугах.

2. Процесс разработки программного обеспечения

Понятие процесса разработки ПО. Универсальный процесс. Текущий процесс. Конкретный процесс. Стандартный процесс. Совершенствование процесса. Pull/Push-стратегии. Фазы и виды деятельности. Классические модели процесса: водопадная модель, спиральная модель. Рабочий продукт. Дисциплина обязательств. Понятие проекта. Управление проектами.

2.1. Понятие процесса разработки программного обеспечения

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

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

Пока не существует универсального процесса разработки ПО – набора методик, правил и предписаний, подходящих для ПО любого вида, для любых компаний, для команд любой национальности. Каждый текущий процесс разработки, осуществляемый некоторой командой в рамках определенного проекта, имеет большое количество особенностей и индивидуальностей. Перед началом проекта целесообразно спланировать процесс работы, определив роли и обязанности в команде, рабочие продукты (промежуточные и финальные), порядок участия в их разработке членов команды и т.д. Будем называть это предварительное описание конкретным процессом, отличая его от плана работ, проектных спецификаций и пр. Например, в системе Microsoft Visual Team System есть шаблон процесса, создаваемый или адаптируемый (в случае использования стандартного) перед началом разработки. В VSTS существуют заготовки для конкретных процессов на базе CMMI, Scrum и др.

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

• информацию, правила использования, документацию и инсталляционные пакеты средств разработки, используемых в проектах компании (систем версионного контроля, средств контроля ошибок, средств программирования – различных IDE, СУБД и т.д.);

• описание практик разработки – проектного менеджмента, правил работы с заказчиком и т.д.;

• шаблоны проектных документов – технических заданий, проектных спецификаций, планов тестирования и пр.

Также возможна стандартизация процедуры разработки конкретного процесса как «вырезки» из стандартного. Основная идея стандартного процесса – курсирование внутри компании передового опыта, а также унификация средств разработки. Очень часто в компаниях различные департаменты и проекты сильно отличаются по зрелости процесса разработки, а также затруднено повторное использование передового опыта. Кроме того, случается, что компания использует несколько средств параллельных инструментов разработки, например, СУБД средства версионного контроля. Иногда это бывает оправданно (например, таковы требования заказчика), часто это необходимо, например, Java, .NET (большая компетентность офшорной компании позволяет ей брать более широкий спектр заказов). Но очень часто это произвольный выбор самих разработчиков. В любом случае такая множественность существенно затрудняет миграцию специалистов из проекта в проект, использование результатов одного проекта в другом и т.д. Однако при организации стандартного процесса необходимо следить, чтобы стандартный процесс не оказался всего лишь формальным, бюрократическим аппаратом. Понятие стандартного процесса введено и подробно описано в подходе CMMI.

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

Совершенствование процесса (software process improvement). Это деятельность по изменению существующего процесса (как текущего, в рамках одного проекта, так и стандартного, для всей компании) с целью улучшения качества создаваемых продуктов и/или снижения цены и времени их разработки. Причины актуальности этой деятельности для компаний-производителей ПО заключаются в следующем: происходит быстрая смена технологий разработки ПО, требуются изучение и внедрение новых средcтв разработки; наблюдаются быстрый рост компаний и их выход на новые рынки, что требует новой организации работ; имеет место высокая конкуренция, которая требует поиска более эффективных, более экономичных способов разработки.

Перечислим, что и каким образом можно улучшать:

1. Переход на новые средства разработки, языки программирования и т.д.

2. Улучшение отдельных управленческих и инженерных практик – тестирования, управления требованиями и пр.

3. Полная, комплексная перестройка всех процессов в проекте, департаменте, компании (в соответствии, например, с CMMI).

4. Сертификация компании (CMM/CMMI, ISO 9000 и пр.).

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

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

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

Pull/Push-стратегии. В контексте внедрения инноваций в производственные процессы бизнес-компаний (не обязательно компаний по созданию ПО) существуют две парадигмы:

• organization pull – внедрение инноваций, нацеленных на решение конкретных проблем компании;

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

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

Пример использования стратегии technology push – переход компании со средств структурной разработки на объектно-ориентированные. Еще один пример использования той же стратегии – внедрение стандартов качества ISO 9000 или CMMI. В обоих случая компания не решает какую-то одну проблему или ряд проблем, она хочет радикально изменить ситуацию, выйти на новые рубежи и т.д.

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

Использование стратегии organization pull менее рискованно, вносимые ею изменения в процесс менее глобальны, более локальны, но и выгод такие инновации приносят меньше, по сравнению с удачными внедрениями в соответствии со стратегией technology push.

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

Еще одно различие обеих стратегий заключается в том, что при использовании organization pull, как правило, возврат инвестиций от внедрения происходит быстрее, чем при technology push.

Pulsuz fraqment bitdi.

Yaş həddi:
0+
Litresdə buraxılış tarixi:
02 aprel 2019
Yazılma tarixi:
2012
Həcm:
315 səh. 160 illustrasiyalar
ISBN:
978-5-7638-2511-4
Yükləmə formatı:

Oxşar kitablar