ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 04.02.2024
Просмотров: 290
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
Контрольные вопросы
-
Что такое жизненный цикл программного обеспечение? -
Перечислите основные модели процесса разработки программного обеспечения? -
Каковы основные свойства каскадной (итерационной) модели жизненного цикла? -
Из каких этапов состоит модель жизненного цикла UML?
2 Разработка программного обеспечения
2.1 Основные методы и средства эффективной разработки ПО
Существуют два стиля проектирования: эволюционное и предварительное проектирование.
Методология Extreme Programming (XP) бросила вызов многим устоявшимся представлениям о разработке программного обеспечения. Пожалуй, наиболее противоречивой идеей является отказ от предварительного проектирования в пользу более эволюционного Подхода. Противники ХР считают, что это возврат к разработкам типа «code and fix» («пишем и правим»). Для приверженцев же новой методологии это отказ от техник проектирования (например, UML), их принципов. Незачем беспокоиться о проектировании, считают они. Достаточно внимательно «вслушиваться» в свой код, и проектирование образуется само собой.
В большинстве случаев эволюционное проектирование — это нечто ужасное. В конце концов, все равно вместо дизайна системы вы получаете просто набор из специфических решений, каждое из которых затрудняет дальнейшие изменения в программном коде. Часто это вообще нельзя считать дизайном (и, уж конечно, такой дизайн никак нельзя назвать хорошим). Как говорит Кент, дизайн существует для того, чтобы дать возможность оперативно вносить в систему любые изменения. Если дизайн плох, то такая возможность исчезает. В результате вы будете иметь дело с энтропией программного продукта, и со временем и без того плохой дизайн системы станет еще хуже. Теперь вам будет не только сложнее вносить в систему изменения, но и отыскивать и исправлять ошибки, которые начинают множиться с катастрофической быстротой. Все это — кошмар разработок в стиле «code and fix», когда с течением времени исправление ошибок обходится все дороже и дороже.
Предварительное проектирование — полная противоположность эволюционному. При разработке ПО проектировщики заранее продумывают все основные вопросы. При этом они не пишут программный код, поскольку не создают программный продукт, а только разрабатывают его дизайн. В своей работе они могут использовать такие техники, как UML, что позволяет им абстрагироваться от некоторых подробностей разработок, относящихся непосредственно к программированию. Как только проектный план готов, его можно передавать в другой отдел (или даже в другую компанию), где будут вестись работы по непосредственному созданию системы. Поскольку проектировщики работают на некотором уровне абстракции, им удается избежать принятия ряда тактических решений, ведущих к энтропии программного продукта. Программисты же могут руководствоваться проектным планом и (если они ему следуют) создавать качественно выстроенную систему.
Такой подход к разработке ПО не нов — им активно пользуется множество людей начиная с 1970-х годов. По многим показателям он гораздо лучше, чем эволюционное проектирование в стиле «code and fix», однако и у него есть существенные недостатки. Один из главных недостатков заключается в том, что невозможно заранее продумать все вопросы, с которыми придется столкнуться во время кодирования системы. Таким образом, в ходе работ непременно возникнет ситуация, когда у программистов появятся вопросы относительно спроектированного дизайна. А что, если проектировщики, закончив свою часть работы, уже переключились на другой проект? Тогда программисты начинают самостоятельно решать сложившуюся проблему, отступая от уже принятых проектных решений и внося при этом в Программный продукт долю энтропии. И даже если проектировщик еще работает над проектом и может помочь, все равно ему потребуется довольно много времени, чтобы выяснить ситуацию, внести изменения в диаграммы и уже затем менять код. Л при разработке, как правило, вопрос времени всегда стоит остро. Отсюда энтропия (опять-таки).
Кроме того, существует еще и проблема культур. Проектировщиками становится благодаря высокому мастерству и большому опыту в программировании. Однако, став проектировщиком, программист настолько поглощается новой работой что просто не имеет физической возможности заниматься па-писанием программного кода. При этом инструментарий и материалы программных разработок постоянно меняются. А когда вы перестаете сами писать код, вы не только теряете возможность отслеживать новшества в этой области. Вы теряете уважение тех, кто продолжает заниматься написанием программного кода.
Однако такие проблемы все же можно как-то урегулировать. Может быть, можно что-то сделать с напряженностью в отношениях между людьми. Может быть, можно найти таких проектировщиков, которые могли бы разбираться в большинстве вопросов, и такой дисциплинированный процесс разработки, который позволял бы вносить изменения в диаграммы. Однако остается еще одна проблема — изменяющиеся требования. Именно изменяющиеся требования являются проблемой номер один.
Бороться с изменяющимися требованиями можно по-разному. Один из возможных путей — делать дизайн достаточно гибким, чтобы при изменениях в требованиях его можно было легко менять. Однако для этого требуется заранее знать, какого типа изменения следует ожидать. Да, при проектировании системы можно попытаться угадать те области, в которых наиболее вероятны изменения, и учесть их в дизайне. В этом случае вы, действительно, облегчите себе работу с ожидаемыми изменениями в требованиях, но ничуть не облегчите (а возможно, только ухудшите) ситуацию с изменениями неожиданными. Кроме того, чтобы заранее определить тс области, в которых наиболее вероятны изменения, вы должны прекрасно понимать требования, что, по наблюдениям, очень непросто.
Впрочем, не все проблемы с изменениями в требованиях возникают из-за их непонимания. Множество людей напряженно работают над разработкой технических требований к системе в надежде, что это убережет их от дальнейших поправок при проектировании. Но и так вы далеко не всегда сможете решить проблему. Многие изменения в требованиях диктуются изменениями в экономике в том виде бизнеса, для которого предназначается система. Такие изменения предугадать невозможно, сколько бы вы ни сидели над разработкой требований.
Проектирование программного обеспечения при структурном подходе
При проектировании сложного программного обеспечения прежде всего необходимо определить структурные компоненты и связи между ними. Полученная в результате структура ПО должна быть представлена в виде структурной или функциональной схем и спецификаций ее компонентов.
Структурная схема разрабатываемого программного обеспечении
Структурной называют схему, отражающую состав и взаимодействие по управлению частей разрабатываемого программного обеспечения.
Структурная схема определяется архитектурой разрабатываемого ПО.
Разработку структурной схемы программы обычно выполняют методом пошаговой детализации.
Структурные схемы пакетов программ разрабатывают для каждой программы пакета по отдельности, поскольку организация программ в пакеты не предусматривает передачи управления между ними.
Компонентами структурной схемы программной системы или программного комплекса могут служить программы, подсистемы, базы данных, библиотеки ресурсов и т. п.
Пример структурной схемы программного комплекса для решения математических задач изображен на рисунок 2.1.
Как правило, для программных систем разрабатывается функциональная схема, которая лает более полное представление о проектируемом программном обеспечении с точки зрения взаимодействия его компонентов между собой и с внешней средой.
Рисунок 2.1 - Пример структурной схемы программного комплекса
Функциональная схема
Функциональная схема (ГОСТ 19.701—90) — это схема взаимодействия компонентов программного обеспечения с описанием информационных потоков, состава данных в потоках и указанием используемых файлов и устройств. Для изображения функциональных схем используют специальные обозначения, установленные стандартом (таблица 2.1).
Таблица 2.1 - Обозначения элементов функциональных схем
Функциональные схемы более информативны, чем структурные. На рисунке 2.2 приведена функциональная схема программно го комплекса, реализующего различные методы сортировки массивов.
Рисунок 2.2 - пример функциональной схемы программного комплекса
Метод пошаговой детализации при составлении алгоритмов
Метод пошаговой детализации реализует нисходящий подход к программированию и предполагает пошаговую разработку алгоритма. Можно выделить следующие этапы:
-
Создается описание программы в целом. Определяются основные логические шаги, требуемые для решения задачи, даже могут отражать различные физические способы решения или могут быть удобными групповыми именами для тех действий, выполнение который представляется довольно смутно. Последовательности шагов, требуемых для решения задачи, записываются на обычном языке или на псевдокоде. -
В общих терминах детализируется описание шагов, введенных на этапе 1. В детализированное описание может входить обозначение циклических структур, в то время как действия внутри циклов могут по-прежнему оставаться неясными. Таким образом, выполняются только общие эскизы сложных действий. -
На этом и последующих уровнях в виде последовательных итераций производятся те же действия, что описаны на этапе 2.
При каждой новой итерации уточняются детали, оставшиеся неясными после предыдущих итераций, и создаются более определенные описания. По мере выполнения итераций неопределенные детали становятся все проще и проще, так что на каком-то этапе могут быть полностью описаны.
-
Разработка завершена: в модульном виде получено описание требуемой программы. Перевод этого описания в программу на конкретном языке программирования должен быть достаточно простой задачей.
При решении реальной задачи может потребоваться написание на псевдокоде многих уровней, чтобы довести все модули до такого состояния, при котором они окажутся готовыми для программирования.
Структурные карты Константайна
Методика структурных карт используется на этапе проектирования ПО для того, чтобы продемонстрировать
, каким образoм программный продукт выполняет системные требования. При этом наиболее часто применяются две техники: структурные карты Константайна (Constantine), предназначенные для описания отношений между модулями, и структурные карты Джексона (Jackson), предназначенные для описания внутренней структуры модулей.
Структуру программной системы составляют модули, которые в любом языке программирования имеют следующие общие свойства:
-
модуль имеет имя, по которому к нему можно обращаться как к единому фрагменту; -
модуль состоит из множества операторов языка программирования, записанных последовательно; -
модуль может принимать и/или передавать данные как параметры в вызывающей последовательности или связывать данные через фиксированные ячейки или общие области.
Структурные карты Константайна представляют собой модель отношений между модулями программы. Узлы структурных карт соответствуют модулям и областям данных, потоки изображают межмодульные связи. Нa диаграмме специальными узлами изображаются циклические и условные вызовы модулей, а потоки проходят через эти специальные узлы. Потоки, изображающие межмодульные связи по данным и управлению, также изображаются на диаграмме специальными узлами, а стрелками указываются направления потоков. На рисунке 2.3 приведены основные компоненты структурных карт Константайна.
Рисунок 2.3 - Элементы структурных карт:
а — модуль; б— вызов модуля; в— связь по данным; г— связь по управлению
Модуль является базовым элементом структурной карты. Различают следующие типы модулей (рисунок 2.4):
-
модуль (рисунок 2.4, а); -
подсистема — детализированный модуль или программа. Может использоваться повторно любое число раз (рисунок 2.4, б); -
библиотека — совокупность подпрограмм, размещенных в модуле отдельно отданной системы (рисунок 2.4, в); -
область данных — описывает модули, содержащие исключительно области глобальных/распределенных данных (рисунок 2.4, г).
Рисунок 2.4 – Типы модулей
Отдельные части программной системы (программы, подпрограммы) могут вызываться последовательно, параллельно или как сопрограммы (рисунок 2.5),