[x]. Причина, по которой мы используем это слово, а не "действие" - чисто грамматическое удобство от использования соответствующего прилагательного, например во фразе "функциональная декомпозиция". Слово "действие" не имеет соответствующего производного прилагательного. Другим термином, чье значение в нашем обсуждении эквивалентно значению слова "действие", является слово "операция".
Всякое обсуждение, связанное с программированием, должно учитывать оба аспекта: объект и функцию, это относится и к проектированию программной системы. Но есть один вопрос, при ответе на который между ними нужно выбирать - это вопрос данной лекции: что является критерием выделения модулей системы? Здесь нужно решить, будут ли модули строиться как единицы функциональной декомпозиции или они будут создаваться вокруг главных типов объектов.
Ответ на этот вопрос демонстрирует различие между ОО-подходом и другими методами. При традиционных подходах каждый модуль строится вокруг некоторой единицы функциональной декомпозиции - некоторой части действия. В отличие от них, ОО-метод строит каждый модуль вокруг некоторого типа объектов.
Нетрудно догадаться, что в этой книге развивается именно этот подход. Но нам не следует принимать ОО-декомпозицию на веру лишь потому, что она подразумевается названием этой книги, или потому, что она является "вещью-в-себе", которую просто необходимо делать.
В последующих разделах мы проанализируем аргументы, обосновывающие использование типов объектов в качестве основы модуляризации, а начнем с исследования достоинств и ограничений традиционных не ОО-методов. Затем мы попытаемся получить ясное представление о том, что на самом деле означает слово "объект" для проектирования ПО, хотя полный ответ, требующий некоторых дополнительных теоретических рассуждений, появится только в следующей лекции.
Мы должны также отложить до следующей лекции урегулирование старинной и грозной битвы, ставшей темой нашего обсуждения - Войны Объектов и Функций. Пока же мы подготовим кампанию опорочивания функций в качестве базиса декомпозиции, и, соответственно, восхваления объектов для достижения этих целей. И все-таки нам не следует забывать сделанное выше наблюдение, в конечном счете, в нашем решении проблем должно найтись место, как объектам, так и функциям, хотя и не на равных основаниях. Для установления нового мирового порядка необходимо определить роли граждан первого и второго сорта.
Функциональная декомпозиция
Вначале мы рассмотрим достоинства и ограничения традиционного подхода, использующего функции в качестве основы архитектуры программных систем. Это не только приведет нас к пониманию того, почему требуется еще кое-что - объектная технология, но и поможет избежать некоторых методологических ловушек, таких как преждевременное упорядочение операций, которым, как известно, грешат даже опытные разработчики ОО-ПО.
Непрерывность
Ключевой проблемой при ответе на вопрос: "вокруг чего следует структурировать системы: вокруг функций или вокруг данных?" является проблема расширяемости, более точно - цель, названная непрерывностью в предшествующем обсуждении. Как вы помните, метод проектирования удовлетворяет этому критерию, если он приводит к устойчивой архитектуре, обеспечивающей объем изменений в проекте, соразмерный объему изменений в спецификации.
Обеспечение непрерывности - это главная забота при рассмотрении реального жизненного цикла программных систем, включающего не только производство приемлемой первоначальной версии, но и эволюцию системы на протяжении долгого времени. Большинство систем подвергаются многочисленным изменениям после их первоначальной поставки. Поэтому всякая модель разработки ПО, которая рассматривает только период, предшествующий этой поставке, и игнорирующая последующую эру изменений и пересмотров, весьма далека от реальной жизни, как те романы, которые заканчиваются женитьбой героя на героине в тот момент, когда, как каждый знает, только и должно начинаться самое интересное.
Чтобы оценить качество архитектуры (и породившего ее метода), нужно понять не только то, насколько просто было изначально получить эту архитектуру, не менее важно выяснить, насколько легко ее можно изменить.
Традиционным ответом на этот вопрос была функциональная декомпозиция "сверху вниз", кратко определенная в одной из предыдущих лекций. Насколько хорошо разработка сверху вниз отвечает требованиям модульности?
Проектирование сверху вниз
Там был также весьма изобретательный архитектор, придумавший новый способ постройки домов. Постройка должна была начинаться с крыши и кончаться фундаментом. Он оправдывал мне этот способ ссылкой на приемы двух мудрых насекомых - пчелы и паука.
Джонатан Свифт, "Путешествия Гулливера"
При подходе сверху вниз система строится с помощью последовательных уточнений. Этот процесс начинается с самого общего утверждения об ее абстрактной функции, такого как
[C0]
"Оттранслировать СИ-программу в машинный код"
или
[P0]
"Обработать команду пользователя"
и продолжается путем последовательных шагов уточнения. На каждом шаге уровень абстракции получаемых элементов должен уменьшаться, каждая операция на нем разлагается на композицию одной или нескольких более простых операций. Например, следующий шаг в первом примере (транслятор с СИ) может привести к декомпозиции
[C1]
"Прочесть программу и породить последовательность лексем"
"Разобрать последовательность лексем и построить абстрактное синтаксическое дерево"
"Снабдить дерево семантической информацией"
"Сгенерировать по полученному дереву код"
или, используя другую структуру (и сделав упрощающее предположение, что СИ-программа - это последовательность определений функций):
[C'1]
from
"Инициализировать структуры данных"
until
"Определения всех функций обработаны"
loop
"Прочесть определение следующей функции"
"Сгенерировать частичный код"
end
"Заполнить перекрестные ссылки"
В любом случае разработчик должен на каждом шаге проверять оставшиеся не полностью уточненными элементы (такие как "Читать программу..." и "Определения всех функций обработаны") и раскрывать их, используя тот же процесс уточнения до тех пор, пока все не окажется на достаточном низком уровне абстракции, допускающем непосредственную реализацию.
Процесс уточнения сверху вниз можно представить как построение дерева. Вершины представляют элементы декомпозиции, ветви показывают отношение "B есть уточнение A".
Рис. 5.2. Разработка сверху вниз: структура дерева
У метода проектирования сверху вниз имеется ряд достоинств. Он логичен, хорошо организует дисциплину мышления, поддается эффективному изучению, поощряет систематическое проектирование систем, помогает разработчику найти пути преодоления больших сложностей, возникающих обычно на начальной стадии разработки систем.