Единое окно доступа к образовательным ресурсам

Технология разработки программного обеспечения: Учебное пособие

Голосов: 6

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

Приведенный ниже текст получен путем автоматического извлечения из оригинального PDF-документа и предназначен для предварительного просмотра.
Изображения (картинки, формулы, графики) отсутствуют.
           Для преодоления проблем, которые возникали при каскадном подходе
была предложена спиральная модель жизненого цикла(ЖЦ) (рисунок 1.4),
делающая упор на начальные этапы ЖЦ: анализ и проектирование. На этих
этапах реализуемость технических решений проверяется путем создания
прототипов. Каждый виток спирали соответствует созданию фрагмента или
версии ПО, на нем уточняются цели и характеристики проекта, определяется
его качество и планируются работы следующего витка спирали. Таким обра-
зом, углубляются и последовательно конкретизируются детали проекта, и в
результате выбирается обоснованный вариант, который доводится до реали-
зации.
       Разработка итерациями отражает объективно существующий спи-
ральный цикл создания системы. Неполное завершение работ на каждом эта-
пе позволяет переходить на следующий этап, не дожидаясь полного заверше-
ния работы на текущем. При итеративном способе разработки недостающую
работу можно будет выполнить на следующей итерации. Главная же задача -
как можно быстрее показать пользователям системы работоспособный про-
дукт, тем самым, активизируя процесс уточнения и дополнения требований.
       Основная проблема спирального цикла - определение момента пере-
хода на следующий этап. Для ее решения необходимо ввести временные ог-
раничения на каждый из этапов жизненного цикла. Переход осуществляется
в соответствии с планом, даже если не вся запланированная работа закончена.
План составляется на основе статистических данных, полученных в преды-
дущих проектах, и личного опыта разработчиков.
       Основным нормативным документом, регламентирующим ЖЦ ПО,
является международный стандарт ISO/IEC 12207 (ISO - International Organi-
zation of Standardization - Международная организация по стандартизации,
IEC - International Electrotechnical Commission - Международная комиссия по
электротехнике). Он определяет структуру ЖЦ, содержащую процессы, дей-
ствия и задачи, которые должны быть выполнены во время создания ПО.




                      Рисунок 1.4 - Спиральная модель ЖЦ



                                                                        11


      Структура ЖЦ ПО по стандарту ISO/IEC 12207 базируется на трех
группах процессов:
   − основные процессы ЖЦ ПО (приобретение, поставка, разработка, экс-
плуатация, сопровождение);
   − вспомогательные процессы, обеспечивающие выполнение основных
процессов (документирование, управление конфигурацией, обеспечение ка-
чества, верификация, аттестация, оценка, аудит, решение проблем);
   − организационные процессы (управление проектами, создание инфра-
структуры проекта, определение, оценка и улучшение самого ЖЦ, обучение).

     1.3 Качество программного обеспечения (ПО)

       Каждое ПС должно выполнять определенные функции, т.е. делать то,
что задумано. Хорошее ПС должно обладать еще целым рядом свойств, по-
зволяющим успешно его использовать в течение длительного периода, т.е.
обладать определенным качеством. Качество (quality) ПС − это совокупность
его черт и характеристик, которые влияют на его способность удовлетворять
заданные потребности пользователей. Это не означает, что разные ПС долж-
ны обладать одной и той же совокупностью таких свойств в их наивысшей
степени. Этому препятствует тот факт, что повышение качества ПС по одно-
му из таких свойств часто может быть достигнуто лишь ценой изменения
стоимости, сроков завершения разработки и снижения качества этого ПС по
другим его свойствам. Качество ПС является удовлетворительным, когда
оно обладает указанными свойствами в такой степени, чтобы гарантировать
успешное его использование.
       Совокупность свойств ПС, которая образует удовлетворительное для
пользователя качество ПС, зависит от условий и характера эксплуатации это-
го ПС, т.е. от позиции, с которой должно рассматриваться качество этого ПС.
Поэтому при описании качества ПС, прежде всего, должны быть фиксирова-
ны критерии отбора требуемых свойств ПС. В настоящее время критериями
качества ПС (criteria of software quality) принято считать:
          − функциональность;
          − надежность;
          − легкость применения;
          − эффективность;
          − сопровождаемость;
          − мобильность.
       Функциональность − это способность ПС выполнять набор функций,
удовлетворяющих заданным или подразумеваемым потребностям пользова-
телей. Набор указанных функций определяется во внешнем описании ПС.
       Надежность (reliability) ПС − это его способность безотказно выпол-
нять определенные функции при заданных условиях в течение заданного пе-

12


риода времени с достаточно большой вероятностью. При этом под отказом в
ПС понимают проявление в нем ошибки. Таким образом, надежное ПС не
исключает наличия в нем ошибок − важно лишь, чтобы эти ошибки при
практическом применении этого ПС в заданных условиях проявлялись доста-
точно редко. Убедиться, что ПС обладает таким свойством можно при его
испытании путем тестирования, а также при практическом применении. Та-
ким образом, фактически мы можем разрабатывать лишь надежные, а не пра-
вильные ПС.
       При оценке степени надежности ПС следует также учитывать послед-
ствия каждого отказа. Некоторые ошибки в ПС могут вызывать лишь некото-
рые неудобства при его применении, тогда как другие ошибки могут иметь
катастрофические последствия, например, угрожать человеческой жизни.
Поэтому для оценки надежности ПС иногда используют дополнительные по-
казатели, учитывающие стоимость (вред) для пользователя каждого отказа.
       Легкость применения − это характеристики ПС, которые позволяют
минимизировать усилия пользователя по подготовке исходных данных, при-
менению ПС и оценке полученных результатов, а также вызывать положи-
тельные эмоции определенного или подразумеваемого пользователя.
       Эффективность − это отношение уровня услуг, предоставляемых ПС
пользователю при заданных условиях, к объему используемых ресурсов.
       Сопровождаемость − это характеристики ПС, которые позволяют
минимизировать усилия по внесению изменений для устранения в нем оши-
бок и по его модификации в соответствии с изменяющимися потребностями
пользователей.
       Мобильность − это способность ПС быть перенесенным из одной сре-
ды (окружения) в другую, в частности, с одной ЭВМ на другую.
       Функциональность и надежность являются обязательными критерия-
ми качества ПС, причем обеспечение надежности будет красной нитью про-
ходить по всем этапам и процессам разработки ПС. Остальные критерии ис-
пользуются в зависимости от потребностей пользователей в соответствии с
требованиями к ПС. Для конкретизации качества ПС по каждому из критери-
ев используется стандартизованный набор достаточно простых свойств ПС,
однозначно интерпретируемых разработчиками. Такие свойства мы будем
называть примитивами качества ПС. Некоторые из примитивов могут ис-
пользоваться по нескольким критериям. Ниже приводится зависимость кри-
териев качества от примитивов качества ПС.
       Функциональность: завершенность.
       Надежность: завершенность, точность, автономность, устойчивость,
защищенность.
       Легкость применения: П-документированность, информативность
(только применительно к документации по применению), коммуникабель-
ность, устойчивость, защищенность.
       Эффективность: временнбя эффективность, эффективность по ресур-
сам (по памяти), эффективность по устройствам.

                                                                     13


       Сопровождаемость. С данным критерием связано много различных
примитивов качества. Однако их можно распределить по двум группам, вы-
делив два подкритерия качества: изучаемость и модифицируемость.
        Изучаемость − это характеристики ПС, которые позволяют миними-
зировать усилия по изучению и пониманию программ и документации ПС.
       Модифицируемость − это характеристики ПС, которые позволяют ав-
томатически настраивать на условия применения ПС или упрощают внесе-
ние в него вручную необходимых изменений и доработок.
       Изучаемость: С-документированность, информативность (здесь при-
менительно к документации по сопровождению), понятность, структуриро-
ванность, удобочитаемость.
       Модифицируемость: расширяемость, модифицируемость (в узком
смысле, как примитив качества), структурированность, модульность.
       Мобильность: независимость от устройств, автономность, структури-
рованность, модульность.
       Ниже даются определения используемых примитивов качества ПС.
       Завершенность (completeness) − свойство, характеризующее степень
обладания ПС всеми необходимыми частями и чертами, требующимися для
выполнения своих явных и неявных функций.
       Точность (accuracy) − мера, характеризующая приемлемость величи-
ны погрешности в выдаваемых программами ПС результатах с точки зрения
предполагаемого их использования.
       Автономность (self-containedness) − свойство, характеризующее спо-
собность ПС выполнять предписанные функции без помощи или поддержки
других компонент программного обеспечения.
       Устойчивость (robustness) − свойство, характеризующее способность
ПС продолжать корректное функционирование, несмотря на неправильные
(ошибочные) входные данные.
       Защищенность (defensiveness) − свойство, характеризующее способ-
ность ПС противостоять преднамеренным или нечаянным деструктивным
(разрушающим) действиям пользователя.
       П-документированность (u. documentation) − свойство, характери-
зующее наличие, полноту, понятность, доступность и наглядность учебной,
инструктивной и справочной документации, необходимой для применения
ПС.
       Информативность (accountability) − свойство, характеризующее на-
личие в составе ПС информации, необходимой и достаточной для понимания
назначения ПС, принятых предположений, существующих ограничений,
входных данных и результатов работы отдельных компонент, а также теку-
щего состояния программ в процессе их функционирования.
       Коммуникабельность (communicativeness) − свойство, характеризую-
щее степень, в которой ПС облегчает задание или описание входных данных,
и способность выдавать полезные сведения в достаточно простой форме и с
простым для понимания содержанием.

14


        Временнбя эффективность (time efficiency) − мера, характеризующая
способность ПС выполнять возложенные на него функции в течение опреде-
ленного отрезка времени.
        Эффективность по ресурсам (resource efficiency) − мера, характери-
зующая способность ПС выполнять возложенные на него функции при опре-
деленных ограничениях на используемые ресурсы (используемую память).
        Эффективность по устройствам (device efficiency) − мера, характе-
ризующая экономичность использования устройств машины для решения по-
ставленной задачи.
        С-документировапнность (documentation) − свойство, характеризую-
щее с точки зрения наличия документации, отражающей требования к ПС и
результаты различных этапов разработки данной ПС, включающие возмож-
ности, ограничения и другие черты ПС, а также их обоснование.
        Понятность (understandability) − свойство, характеризующее степень,
в которой ПС позволяет изучающему его лицу понять его назначение, сде-
ланные допущения и ограничения, входные данные и результаты работы его
программ, тексты этих программ и состояние их реализации.
        Структурированность (structuredness) − свойство, характеризующее
программы ПС с точки зрения организации взаимосвязанных их частей в
единое целое определенным образом (например, в соответствии с принципа-
ми структурного программирования).
        Удобочитаемость (readability) − свойство, характеризующее легкость
восприятия текста программ ПС (отступы, фрагментация, форматирован-
ность).
        Расширяемость (augmentability) − свойство, характеризующее спо-
собность ПС к использованию большего объема памяти для хранения данных
или расширению функциональных возможностей отдельных компонент.
        Модифицируемость (modifiability) − мера, характеризующая ПС с
точки зрения простоты внесения необходимых изменений и доработок на
всех этапах и стадиях жизненного цикла ПС.
        Модульность (modularity) − свойство, характеризующее ПС с точки
зрения организации его программ из таких дискретных компонент, что изме-
нение одной из них оказывает минимальное воздействие на другие компо-
ненты.
        Независимость от устройств (device independence) − свойство, ха-
рактеризующее способность ПС работать на разнообразном аппаратном
обеспечении (различных типах, марках, моделях ЭВМ).

     1.4 Стиль программирования

      Стиль программирования связан с удобочитаемостью программы.
      Правила хорошего стиля программирования – это результат соглаше-
ния между опытными программистами.


                                                                         15


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

     1.5 Модульное программирование

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



16


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

                                                                      17


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

     1.6 Методы проектирования программных средств

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


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


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




20



    
Яндекс цитирования Яндекс.Метрика