Опубликован: 17.10.2005 | Доступ: свободный | Студентов: 8825 / 590 | Оценка: 4.38 / 4.10 | Длительность: 41:16:00
ISBN: 978-5-7502-0255-3
Специальности: Программист
Лекция 5:

К объектной технологии

Функциональная декомпозиция

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

Непрерывность

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

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

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

Традиционным ответом на этот вопрос была функциональная декомпозиция "сверху вниз", кратко определенная в одной из предыдущих лекций. Насколько хорошо разработка сверху вниз отвечает требованиям модульности?

Проектирование сверху вниз

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

Джонатан Свифт, "Путешествия Гулливера"

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

[C0]
"Оттранслировать СИ-программу в машинный код"

или

[P0]
"Обработать команду пользователя"

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

[C1]
"Прочесть программу и породить последовательность лексем"
"Разобрать последовательность лексем и построить абстрактное синтаксическое дерево"
"Снабдить дерево семантической информацией"
"Сгенерировать по полученному дереву код"

или, используя другую структуру (и сделав упрощающее предположение, что СИ-программа - это последовательность определений функций):

[C'1]
from
   "Инициализировать структуры данных"
until
   "Определения всех функций обработаны"
loop
   "Прочесть определение следующей функции"
   "Сгенерировать частичный код"
end
"Заполнить перекрестные ссылки"

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

Процесс уточнения сверху вниз можно представить как построение дерева. Вершины представляют элементы декомпозиции, ветви показывают отношение "B есть уточнение A".

Разработка сверху вниз: структура дерева

Рис. 5.2. Разработка сверху вниз: структура дерева

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

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

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

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

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

Структура простой системы расчета зарплаты

Рис. 5.3. Структура простой системы расчета зарплаты

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

Предположим, однако, что разработка нашей платежной системы благополучно завершена и программа выполняет всю необходимую работу. Скорее всего, на этом разработка не прекратится. Хорошие системы имеют противную привычку возбуждать в своих пользователях множество идей о других вещах, которые они могут делать. Как разработчику системы вам было сказано вначале, что все, что вы должны сделать - это сгенерировать чеки и пару вспомогательных выходных данных. Но затем просьбы о расширениях начинают попадать на ваш стол одна за другой: "Может ли программа собирать некоторую дополнительную статистику?" "Я говорил вам, что в следующем квартале мы собираемся начать платить некоторым служащим ежемесячно, а некоторым - дважды в месяц, не так ли?" "И, между прочим, мне нужен ежемесячный суммарный отчет для администрации и еще один ежеквартальный для акционеров". "Бухгалтерам требуется отдельный отчет для начисления налогов". "Кстати, правильно ли вы храните информацию о зарплате? Очень хотелось бы предоставить персоналу интерактивный доступ к ней. Не понимаю, почему трудно добавить такую функцию?"

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

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

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

Александр Шалухо
Александр Шалухо
Анатолий Садков
Анатолий Садков

При заказе pdf документа с сертификатом будет отправлен только сертификат или что-то ещё?