Проектирование программного обеспечения
Проектирование программного обеспечения (англ. software design) — это процесс концептуализации того, как будет работать программная система, до её реализации или модификации[1]. Под проектированием программного обеспечения также понимается непосредственный результат такого процесса — концепции того, как будет работать программа. Эти концепции могут быть формально документированы или же поддерживаться неофициально, в том числе посредством устной передачи.
Процесс проектирования позволяет моделировать различные аспекты программной системы до её создания с целью повышения эффективности последующей разработки кода. Ключевыми факторами успешного проектирования являются креативность, прошлый опыт, понимание критериев «качественного» программного обеспечения и нацеленность на качество.
Проект программного обеспечения можно сравнить с архитектурным планом дома. Общие планы отображают всю конструкцию (например, трёхмерное изображение дома), а детальные планы описывают отдельные элементы (например, схему водопровода). Аналогично, модель проектирования программного обеспечения предоставляет различные представления предлагаемых решений.
Место в процессе разработки
В терминах каскадной модели разработки, проектирование программного обеспечения является стадией, следующей за анализом требований и предшествующей программированию[2]. Анализ требований определяет, что должна делать система, не затрагивая вопрос как это реализовать, поэтому возможно множество вариантов проектов, удовлетворяющих исходным требованиям. Проектирование может выполняться прямо в процессе программирования, без плана или анализа требований[3], однако для сложных проектов это менее осуществимо. Завершённое до программирования проектирование позволяет взаимодействовать специалистам из разных областей с программистами для создания функционального и технически обоснованного программного обеспечения.
Иногда для поиска оптимального решения создаются модели или прототипы системы.
Код как форма проектирования
Одно из затруднений, связанных с термином «проектирование» в программировании, заключается в том, что этот процесс применяется на разных уровнях абстракции — от архитектуры программного обеспечения до отдельных компонентов, функций и алгоритмов. На высоких уровнях абстракции процесс проектирования может быть достаточно формальным, тогда как на низких уровнях результатом проектирования становится непосредственно программный код. В таком случае проектирование программного обеспечения становится проектированием самого процесса проектирования. Эдсгер Дейкстра называл такой уровневый подход к организации смысловых уровней «радикальной новизной программирования»[4], а Дональд Кнут, используя свой опыт написания TeX, отмечал бесполезность попытки полностью спроектировать программу до её реализации:
TeX был бы полным провалом, если бы я только задал его спецификации и не участвовал бы в его непосредственной реализации. Процесс реализации постоянно приводил меня к неожиданным вопросам и новым пониманиям, как можно улучшить исходные спецификации[5].
Артефакты проектирования
Процесс проектирования может сопровождаться созданием артефактов проектной документации, таких как блок-схема, вариант использования, псевдокод, модель в унифицированном языке моделирования (UML) и других концептуальных моделях. Для ориентированных на пользователя систем проектирование включает проектирование пользовательского опыта, что может приводить к построению раскадровок для уточнения спецификаций. Документация может пересматриваться с целью корректировки ограничений, спецификаций и даже требований до этапа кодирования.
Итеративное проектирование
Программные системы по природе своей связаны с неопределённостью, а размер компонентов способен существенно влиять на работу системы как положительно, так и отрицательно. Нил Форд и Марк Ричардс предлагают итеративный подход к выделению и оптимизации компонентов[6]. Такой подход акцентирует внимание на постепенном уточнении структуры системы и требований по мере накопления знаний.
Типичный цикл включает несколько стадий:[6]
- Формируется стратегия высокоуровневого разделения (например, техническое или доменное деление), определяется минимальная осмысленная развёртываемая единица — «кванта». Эти решения могут пересматриваться в процессе.
- На основании стратегии формируются начальные компоненты.
- К компонентам прикрепляются требования.
- Анализируются роли и ответственности каждого компонента для прояснения и минимизации пересечений.
- Оцениваются архитектурные характеристики (масштабируемость, устойчивость, сопровождаемость).
- При необходимости производится реорганизация компонентов на основе обратной связи от команд разработки.
Этот цикл может адаптироваться под специфику разных проектов и предметных областей.
Принципы проектирования
Принципы проектирования помогают инженеру ориентироваться в процессе разработки. Дэвис[7] предложил ряд принципов, уточнённых в последующих работах:
- Процесс проектирования не должен быть односторонним («туннельным зрением»)
- Хороший разработчик рассматривает альтернативы, оценивает их с учётом требований задачи и ресурсов.
- Проект должен быть прослеживаемым до модели анализа
- Поскольку один элемент проектной модели часто связан с несколькими требованиями, необходимы средства отслеживания соответствия проектных решений требованиям.
- Не стоит «изобретать велосипед»
- Для построения систем нужно использовать уже существующие шаблоны проектирования как альтернативу созданию новых решений с нуля.
- Проект должен минимизировать разрыв между программным продуктом и реальной задачей
- Структура программного решения должна по возможности отражать структуру предметной области.
- Проект должен быть единообразным и интегрированным
- Для этого определяются общие правила стиля до начала работы и особое внимание уделяется интерфейсам между компонентами.
- Проект должен быть гибким к изменениям
- Следующие разделы дополняют этот принцип концепциями, обеспечивающими масштабируемость и эволюционность проектных решений.
- Проект должен компенсировать нештатные ситуации
- Хорошо спроектированное ПО должно корректно реагировать на аномальные данные или сбои, в том числе завершать работу «мягко».
- Проектирование не тождественно кодированию
- Даже при создании детализированных проектных решений уровень абстракции проектной модели выше, чем исходный код.
- Качество проекта должно оцениваться на всех этапах
- Применяются различные концепции и метрики качества для поддержки процесса разработки.
- Проект должен проходить рецензирование с целью минимизации смысловых ошибок
- Важно обеспечить полноту, однозначность и непротиворечивость ещё до обсуждения технических деталей.
Концепции проектирования
Концепции проектирования образуют основу, на которой строятся более сложные методы. К этим концепциям относятся:
- Абстракция
- Сокращение объёма информации до главного — представление только релевантных признаков явления для поставленной задачи.
- Архитектура
- Общая структура программного комплекса, обеспечивающая его концептуальную целостность. Грамотно построенная архитектура способствует достижению параметров эффективности, качества, надёжности и экономичности.
- Иерархия управления
- Структура программы, отражающая порядок взаимодействия компонентов и передачу управления.
- Структура данных
- Способы логического представления и хранения данных.
- Шаблон проектирования
- Перенос накопленного опытного решения типовой задачи проектирования, что способствует ускорению разработки[8].
- Сокрытие информации
- Каждый модуль должен быть организован так, чтобы его внутренние данные были недоступны другим модулям без необходимости.
- Модульность
- Деление решения на части (модули).
- Уточнение
- Процесс пошаговой детализации — декомпозиция функций от общих формулировок к программным инструкциям.
- Программная процедура
- Фокусировка на обработке каждого модуля по отдельности.
- Структурное разбиение
- Горизонтальное и вертикальное деление программы на независимые части.
Грэди Буч выделяет абстракцию, инкапсуляцию, модульность и иерархию как основные принципы проектирования[9]. Комплекс этих принципов обозначается как PHAME (principles of hierarchy, abstraction, modularization, encapsulation)[10].
Аспекты проектирования
При проектировании программного обеспечения необходимо учитывать множество факторов, значимость которых определяется целями и требованиями конкретного проекта. Важнейшие аспекты:
- Совместимость
- Способность программы взаимодействовать с другими продуктами, например, обратная совместимость с более ранними версиями.
- Расширяемость (Extensibility)
- Возможность добавления новых функций без существенной перестройки архитектуры.
- Отказоустойчивость
- Способность ПО сопротивляться сбоям и восстанавливаться после них.
- Сопровождаемость
- Лёгкость внесения изменений и исправлений. Часто обеспечивается за счёт модульности и расширяемости.
- Модульность
- Строгое разделение ПО на независимые компоненты, что упрощает тестирование и дальнейшее развитие.
- Издержки
- Ресурсы, расходуемые на поддержание программных и аппаратных требований.
- Производительность
- Выполнение задач за приемлемое время и ограниченное потребление памяти.
- Портируемость
- Применимость программного продукта в разных условиях и на различных платформах.
- Надёжность
- Способность выполнять требуемые функции в заявленных условиях и сроках.
- Повторное использование
- Возможность применения частей существующего ПО в новых проектах с минимальными изменениями.
- Устойчивость
- Работа в условиях стресса или некорректных данных, например, при нехватке памяти.
- Масштабируемость
- Адаптация к увеличению нагрузки, числу пользователей или функций. Как отмечает Марк Брукер, «система масштабируема в диапазоне, где предельная стоимость обработки дополнительной нагрузки почти постоянна». Бесcерверные технологии удовлетворяют этому критерию, однако важно учитывать суммарную стоимость владения[11].
- Безопасность
- Устойчивость к внешним воздействиям и атакам.
- Удобство работы
- Интерфейс должен быть интуитивным для пользователя. Значения параметров по умолчанию должны быть хорошо подобраны для большинства пользователей[12].
Языки моделирования
Язык моделирования позволяет формализованно описывать информацию, знания или системы по единому набору правил — графически или текстово. Основные языки моделирования для проектирования программного обеспечения:
- Язык описания архитектуры (ADL)
- Формализует архитектуру программной системы.
- Business Process Modeling Notation (BPMN)
- Язык моделирования бизнес-процессов.
- EXPRESS и EXPRESS-G (ISO 10303-11)
- Международный стандарт языков моделирования данных общего назначения.
- Extended Enterprise Modeling Language (EEML)
- Применяется для моделирования бизнес-процессов на разных уровнях.
- Блок-схема
- Схематичное изображение алгоритмов и процессов.
- Fundamental Modeling Concepts (FMC)
- Язык моделирования для комплексных программных систем.
- IDEF
- Семейство языков моделирования, включающее IDEF0 для функционального моделирования, IDEF1X для моделирования информации и IDEF5 для онтологий.
- Jackson Structured Programming (JSP)
- Метод структурного программирования, отражающий соответствие между структурой данных и логикой программы.
- LePUS3
- Объектно-ориентированный визуальный язык описания архитектуры и формальных спецификаций, в частности для больших проектов на Java, C++ и C# и моделирования шаблонов проектирования.
- Унифицированный язык моделирования (UML)
- Универсальный язык для описания программных систем структурно и поведением; поддерживает графическую нотацию и расширение профилями.
- Alloy
- Язык для формализации сложных структурных ограничений и поведения в ПО, основанный на реляционной логике первого порядка.
- Systems Modeling Language (SysML)
- Общий язык моделирования для инженерии систем.
- Фреймворк сервис-ориентированного моделирования (SOMF)[13]
Примечания
Литература
- Pressman R. S. Software engineering: a practitioner’s approach. McGraw-Hill, 2001. ISBN 0-07-365578-3.
- Davis, A. 201 Principles of Software Development. McGraw Hill, 1995.


