ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 20.11.2019
Просмотров: 9465
Скачиваний: 184

Информационно
связанными
считают
функции
,
обрабатывающие
одни
и
те
желанные
(
рис
.
2.1,
в
).
При
использовании
структурных
языков
программирования
раздельное
выполнение
функций
можно
осуществить
только
,
если
каждая
функция
реализуется
своей
подпрограммой
функция
».
Из
тех
же
соображений
следует
избегать
неструктурированного
распределения
функции
Хотя
раньше
в
подобных
случаях
обычно
использовали
разные
точки
входа
в
модуль
,
оформлен
-
ный
как
одна
подпрограмма
.
Несмотря
на
объединение
нескольких
функций
,
информационно
связанный
модуль
имеет
неплохие
показатели
технологичности
.
Это
объясняется
тем
,
что
все
функции
,
работающие
с
некоторыми
данными
,
собраны
в
одно
место
,
что
позволяет
при
изменении
формата
данных
корректировать
только
один
модуль
.
Информационно
связанными
также
считают
данные
,
которые
обрабатываются
одной
функцией
.
Процедурно
связаны
функции
или
данные
,
которые
являются
частями
одного
процесса
(
рис
.
2.1,
г
).
Обычно
модули
с
процедурной
связностью
функций
получают
,
если
в
модуле
объединены
функции
альтернативных
частей
программы
.
При
процедурной
связности
отдельные
элементы
модуля
связаны
крайне
слабо
,
так
как
реализуемые
ими
действия
связаны
лишь
общим
процессом
,
следовательно
,
технологичность
данного
вида
связи
ниже
,
чем
предыдущего
.
Временная
связность
функций
подразумевает
,
что
эти
функции
выполняются
параллельно
или
в
течение
некоторого
периода
времени
(
рис
. 2.1,
д
).
Временная
связность
данных
означает
,
что
они
используются
в
некотором
временном
интервале
.
Например
,
временную
связность
имеют
функции
,
выполняемые
при
инициализации
некоторого
процесса
.
Отличительной
особенностью
временной
связности
является
то
,
что
действия
,
реализуемые
такими
функциями
,
обычно
могут
выполняться
в
любом
порядке
.
Содержание
модуля
с
временной
связностью
функций
имеет
тенденцию
меняться
:
в
него
могут
включаться
новые
действия
и
/
или
исключаться
старые
.
Большая
вероятность
модификации
функции
еще
больше
уменьшает
показатели
технологичности
модулей
данного
вида
по
сравнению
с
предыдущим
.
Логическая
связь
базируется
на
объединении
данных
или
функций
в
одну
логическую
группу

(
рис
. 2.1,
е
).
В
качестве
примера
можно
привести
функции
обработки
текстовой
информации
или
данные
одного
и
того
же
типа
.
Модуль
с
логической
связностью
функций
часто
реализует
альтернативные
варианты
одной
операции
,
например
,
сложение
целых
чисел
и
сложение
вещественных
чисел
.
Из
такого
модуля
всегда
будет
вызываться
одна
какая
-
либо
его
часть
,
при
этом
вызывающий
и
вызываемый
модули
будут
связаны
по
управлению
.
Понять
логику
работы
модулей
,
содержащих
логически
связанные
компоненты
,
как
правило
,
сложнее
,
чем
модулей
,
использующих
временную
связность
,
следовательно
,
их
показатели
технологичности
еще
ниже
.
В
том
случае
,
если
связь
между
элементами
мала
или
отсутствует
,
считают
,
что
они
имеют
случайную
связность
.
Модуль
,
элементы
которого
связаны
случайно
,
имеет
самые
низкие
показатели
технологичности
,
так
как
элементы
,
объединенные
в
нем
,
вообще
не
связаны
.
Обратите
внимание
,
что
в
трех
предпоследних
случаях
связь
между
несколькими
подпрограммами
в
модуле
обусловлена
внешними
причинами
.
А
в
последнем
-
вообще
отсутствует
.
Это
соответствующим
образом
проецируется
на
технологические
характеристики
модулей
.
В
табл
. 2.2
представлены
характеристики
различных
видов
связности
по
экспертным
оценкам
[21, 30].
Анализ
табл
. 2.2
показывает
,
что
на
практике
целесообразно
использовать
функциональную
,
последовательную
и
информационную
связности
.
Таблица
2.2
Вид
связности
Сцепление
,
балл
Наглядность
(
понятность
)
Возможность
изменения
Сопровождаемость
Функциональная
10
Хорошая
Хорошая
Хорошая
Последовательная
9
Хорошая
Хорошая
Хорошая
Информационная
8
Средняя
Средняя
Средняя
Процедурная
5
Средняя
Средняя
Плохая
Временная
3
Средняя
Средняя
Плохая
Логическая
1
Плохая
Плохая
Плохая
Случайная
0
Плохая
Плохая
Плохая
Как
правило
,
при
хорошо
продуманной
декомпозиции
модули
верхних
уровней
иерархии
имеют
функциональную
или
последовательную
связность
функций
и
данных
.
Для
модулей
обслуживания
данных
характерна
информационная
связность
функций
.
Данные
таких
модулей
могут
быть
связаны
по
-
разному
.
Так
,
модули
,
содержащие
описание
классов
при
объектно
-
ориентированном
подходе
,
характеризуются
информационной
связностью
методов
и
функциональной
связностью
данных
.
Получение
в
процессе
декомпозиции
модулей
с
другими
видами
связности
,
скорее
всего
,
означает
недостаточно
продуманное
проектирование
.
Исключением
являются
лишь
библиотеки
ресурсов
.
Библиотеки
ресурсов
.
Различают
библиотеки
ресурсов
двух
типов
:
библиотеки
подпрограмм
и
библиотеки
классов
.
Библиотеки
подпрограмм
реализуют
функции
,
близкие
по
назначению
,
например
,
библиотека
графического
вывода
информации
.
Связность
подпрограмм
между
собой
в
такой
библиотеке
-
логическая
,
а
связность
самих
подпрограмм
-
функциональная
,
так
как
каждая
из
них
обычно
реализует
одну
функцию
.
Библиотеки
классов
реализуют
близкие
по
назначению
классы
.
Связность
элементов
класса
-
информационная
,
связность
классов
между
собой
может
быть
функциональной
-
для
родственных
или
ассоциированных
классов
и
логической
-
для
остальных
.
В
качестве
средства
улучшения
технологических
характеристик
библиотек
ресурсов
в
настоящее
время
широко
используют
разделение
тела
модуля
на
интерфейсную
часть
и
область

реализации
(
секции
Interface
и
Implementation -
в
Pascal, h
и
срр
-
файлы
в
C++
и
в
Java).
Интерфейсная
часть
в
данном
случае
содержит
совокупность
объявлений
ресурсов
(
заголовков
подпрограмм
,
имен
переменных
,
типов
,
классов
и
т
.
п
.),
которые
данная
библиотека
предоставляет
другим
модулям
.
Ресурсы
,
объявление
которых
в
интерфейсной
части
отсутствует
,
извне
не
доступны
.
Область
реализации
содержит
тела
подпрограмм
и
,
возможно
,
внутренние
ресурсы
(
подпрограммы
,
переменные
,
типы
),
используемые
этими
подпрограммами
.
При
такой
организации
любые
изменения
реализации
библиотеки
,
не
затрагивающие
ее
интерфейс
,
не
требуют
пересмотра
модулей
,
связанных
с
библиотекой
,
что
улучшает
технологические
характеристики
модулей
-
библиотек
.
Кроме
того
,
подобные
библиотеки
,
как
правило
,
хорошо
отлажены
и
продуманы
,
так
как
часто
используются
разными
программами
.
2.3.
Нисходящая
и
восходящая
разработка
программного
обеспечения
При
проектировании
,
реализации
и
тестировании
компонентов
структурной
иерархии
,
полученной
при
декомпозиции
,
применяют
два
подхода
:
•
восходящий
;
•
нисходящий
.
В
литературе
встречается
еще
один
подход
,
получивший
название
«
расширение
ядра
».
Он
предполагает
,
что
в
первую
очередь
проектируют
и
разрабатывают
некоторую
основу
-
ядро
программного
обеспечения
,
например
,
структуры
данных
и
процедуры
,
связанные
с
ними
.
В
дальнейшем
ядро
наращивают
,
комбинируя
восходящий
и
нисходящий
методы
.
На
практике
дан
-
ный
подход
в
зависимости
от
уровня
ядра
практически
сводится
либо
к
нисходящему
,
либо
к
восходящему
подходам
.
Восходящий
подход
.
При
использовании
восходящего
подхода
сначала
проектируют
и
реализуют
компоненты
нижнего
уровня
,
затем
предыдущего
и
т
.
д
.
По
мере
завершения
тестирования
и
отладки
компонентов
осуществляют
их
сборку
,
причем
компоненты
нижнего
уровня
при
таком
подходе
часто
помещают
в
библиотеки
компонентов
.
Для
тестирования
и
отладки
компонентов
проектируют
и
реализуют
специальные
тестирующие
программы
.
Подход
имеет
следующие
недостатки
:
•
увеличение
вероятности
несогласованности
компонентов
вследствие
неполноты
спецификаций
;
•
наличие
издержек
на
проектирование
и
реализацию
тестирующих
программ
,
которые
нельзя
преобразовать
в
компоненты
;
•
позднее
проектирование
интерфейса
,
а
соответственно
невозможность
продемонстрировать
его
заказчику
для
уточнения
спецификаций
и
т
.
д
.
Исторически
восходящий
подход
появился
раньше
,
что
связано
с
особенностью
мышления
программистов
,
которые
в
процессе
обучения
привыкают
при
написании
небольших
программ
сначала
детализировать
компоненты
нижних
уровней
(
подпрограммы
,
классы
).
Это
позволяет
им
лучше
осознавать
процессы
верхних
уровней
.
При
промышленном
изготовлении
программного
обеспечения
восходящий
подход
в
настоящее
время
практически
не
используют
.
Нисходящий
подход
.
Нисходящий
подход
предполагает
,
что
проектирование
и
последующая
реализация
компонентов
выполняется
«
сверху
-
вниз
»,
т
.
е
.
вначале
проектируют
компоненты
верхних
уровней
иерархии
,
затем
следующих
и
так
далее
до
самых
нижних
уровней
.
В
той
же
последовательности
выполняют
и
реализацию
компонентов
.
При
этом
в
процессе
программи
-
рования
компоненты
нижних
,
еще
не
реализованных
уровней
заменяют
специально
разработанными
отладочными
модулями
- «
заглушками
»,
что
позволяет
тестировать
и
отлаживать
уже
реализованную
часть
.
При
использовании
нисходящего
подхода
применяют
иерархический
,
операционный
и
комбинированный
методы
определения
последовательности
проектирования
и
реализации
компонентов
.
Иерархический
метод
предполагает
выполнение
разработки
строго
по
уровням
.
Исключения

допускаются
при
наличии
зависимости
по
данным
,
т
.
е
.
если
обнаруживается
,
что
некоторый
модуль
использует
результаты
другого
,
то
его
рекомендуется
программировать
после
этого
модуля
.
Основной
проблемой
данного
метода
является
большое
количество
достаточно
сложных
заглушек
.
Кроме
того
,
при
использовании
данного
метода
основная
масса
модулей
разрабатывается
и
реализуется
в
конце
работы
над
проектом
,
что
затрудняет
распределение
человеческих
ресурсов
.
Операционный
метод
связывает
последовательность
выполнения
при
запуске
программы
.
Применение
метода
усложняется
тем
,
что
порядок
выполнения
модулей
может
зависеть
от
дан
-
ных
.
Кроме
того
,
модули
вывода
результатов
,
несмотря
на
то
,
что
они
вызываются
последними
,
должны
разрабатываться
одними
из
первых
,
чтобы
не
проектировать
сложную
заглушку
,
обеспечивающую
вывод
результатов
при
тестировании
.
С
точки
зрения
распределения
человеческих
ресурсов
сложным
является
начало
работ
,
пока
не
закончены
все
модули
,
находящиеся
на
так
называемом
критическом
пути
.
Комбинированный
метод
учитывает
следующие
факторы
,
влияющие
на
последовательность
разработки
:
•
достижимость
модуля
-
наличие
всех
модулей
в
цепочке
вызова
данного
модуля
;
•
зависимость
по
данным
-
модули
,
формирующие
некоторые
данные
,
должны
создаваться
раньше
обрабатывающих
;
•
обеспечение
возможности
выдачи
результатов
-
модули
вывода
результатов
должны
создаваться
раньше
обрабатывающих
;
•
готовность
вспомогательных
модулей
-
вспомогательные
модули
,
например
,
модули
закрытия
файлов
,
завершения
программы
,
должны
создаваться
раньше
обрабатывающих
;
•
наличие
необходимых
ресурсов
.
Кроме
того
,
при
прочих
равных
условиях
сложные
модули
должны
разрабатываться
прежде
простых
,
так
как
при
их
проектировании
могут
выявиться
неточности
в
спецификациях
,
а
чем
раньше
это
произойдет
,
тем
лучше
.
Нисходящий
подход
допускает
нарушение
нисходящей
последовательности
разработки
компонентов
в
специально
оговоренных
случаях
.
Так
,
если
некоторый
компонент
нижнего
уровня
используется
многими
компонентами
более
высоких
уровней
,
то
его
рекомендуют
проектировать
и
разрабатывать
раньше
,
чем
вызывающие
его
компоненты
.
И
,
наконец
,
в
первую
очередь
проектируют
и
реализуют
компоненты
,
обеспечивающие
обработку
правильных
данных
,
оставляя
компоненты
обработки
неправильных
данных
напоследок
.
Пример
определения
последовательности
реализации
модулей
будет
рассмотрен
в
§ 5.2.
Нисходящий
подход
обычно
используют
и
при
объектно
-
ориентированном
программировании
.
В
соответствии
с
рекомендациями
подхода
вначале
проектируют
и
реализуют
пользовательский
интерфейс
программного
обеспечения
,
затем
разрабатывают
классы
некоторых
базовых
объектов
предметной
области
,
а
уже
потом
,
используя
эти
объекты
,
проектируют
и
реализуют
остальные
компоненты
.
Нисходящий
подход
обеспечивает
:
•
максимально
полное
определение
спецификаций
проектируемого
компонента
и
согласованность
компонентов
между
собой
;
•
раннее
определение
интерфейса
пользователя
,
демонстрация
которого
заказчику
позволяет
уточнить
требования
к
создаваемому
программному
обеспечению
:
•
возможность
нисходящего
тестирования
и
комплексной
отладки
(
см
.
гл
. 9).
2.4.
Структурное
и
«
неструктурное
»
программирование
.
Средства
описания
структурных
алгоритмов
Одним
из
способов
обеспечения
высокого
уровня
технологичности
разрабатываемого
программного
обеспечения
является
структурное
программирование
.
Различают
три
вида
вычислительного
процесса
,
реализуемого
программами
:
линейный
,

разветвленный
и
циклический
.
Линейная
структура
процесса
вычислений
предполагает
,
что
для
получения
результата
необходимо
выполнить
некоторые
операции
в
определенной
последовательности
.
Разветвленная
структура
процесса
вычислений
предполагает
,
что
конкретная
последовательность
операций
зависит
от
значений
одной
или
нескольких
переменных
.
Циклическая
структура
процесса
вычислений
предполагает
,
что
для
получения
результата
некоторые
действия
необходимо
выполнить
несколько
раз
.
Для
реализации
указанных
вычислительных
процессов
в
программах
используют
соответствующие
управляющие
операторы
.
Первые
процедурные
языки
программирования
высокого
уровня
,
такие
,
как
FORTRAN,
понятием
«
тип
вычислительного
процесса
»
не
оперировали
.
Для
изменения
линейной
последовательности
операторов
в
них
,
как
в
языках
низкого
уровня
,
использовались
команды
условной
(
при
выполнении
некоторого
условия
)
и
безусловной
передач
управления
.
Потому
и
программы
,
написанные
на
этих
языках
,
имели
запутанную
структуру
,
присущую
в
настоящее
время
только
низкоуровневым
(
машинным
)
языкам
.
Именно
для
изображения
схем
алгоритмов
таких
программ
в
свое
время
был
разработан
ГОСТ
19.701-90,
согласно
которому
каждой
группе
действий
ставится
в
соответствие
специальный
блок
(
табл
. 2.3).
Хотя
этот
стандарт
предусматривает
блоки
для
обозначения
циклов
,
он
не
запрещает
и
произвольной
передачи
управления
,
т
.
е
.
допускает
использование
команд
условной
и
безусловной
передачи
управления
при
реализации
алгоритма
.