Еще более эффективной концепцией, развивающей идею декомпозиции, является многоуровневый подход. После представления исходной задачи в виде множества модулей эти модули группируют и упорядочивают по уровням, образующим иерархию. В соответствии с принципом иерархии для каждого промежуточного уровня можно указать непосредственно примыкающие к нему соседние вышележащий и нижележащий уровни (рис. 4.2).
Группа модулей, составляющих каждый уровень, для решения своих задач должна обращаться с запросами только к модулям соседнего нижележащего уровня. С другой стороны, результаты работы каждого из модулей, отнесенных к некоторому уровню, могут быть переданы только модулям соседнего вышележащего уровня. Такая иерархическая декомпозиция задачи предполагает четкое определение функций и интерфейсов не только отдельных модулей, но и каждого уровня.
Рис. 4.2. Многоуровневый подход — создание иерархии задач |
Межуровневый интерфейс, называемый также интерфейсом услуг, определяет набор функций, которые нижележащий уровень предоставляет вышележащему (рис. 4.3).
|
|
К уровню к+2 К уровню к - 1 Рис. 4.3. Концепция многоуровневого взаимодействия |
Такой подход дает возможность проводить разработку, тестирование и модификацию отдельного уровня независимо от других уровней. Иерархическая декомпозиция позволяет, двигаясь от более низкого уровня к более высокому, переходить ко все более и более абстрактному, а значит, и более простому представлению исходной задачи.
Пример
Рассмотрим задачу считывания логической записи из файла, расположенного на локальном диске. Ее (очень упрощенно) можно представить в виде следующей иерархии частных задач.
1. Поиск по символьному имени файла его характеристик, необходимых для доступа к данным: информации о физическом расположении файла на диске, размере и др. Поскольку функции этого уровня связаны только с просмотром каталогов, представление о файловой системе на этом уровне чрезвычайно абстрактно: файловая система имеет вид графа, в узлах которого находятся каталоги, а листьями являются файлы. Никакие детали физической и логической организации данных на диске данный уровень не интересуют.
2. Определение считываемой части файла. Для решения этой задачи необходимо снизить степень абстракции файловой системы. Функции данного уровня оперируют с файлом как с совокупностью определенным образом связанных физических блоков диска.
3. Считывание данных с диска. После определения номера физического блока файловая система обращается к системе ввода-вывода для выполнения операции чтения. На этом уровне уже фигурируют такие детали устройства файловой системы, как номера цилиндров, дорожек, секторов.
|
|
Среди функций, которые может запросить прикладная программа, обращаясь к верхнему уровню файловой системы, может быть, например, такая:
ПРОЧИТАТЬ 22 ЛОГИЧЕСКУЮ ЗАПИСЬ ФАЙЛА DIR1/MY/FILE ТХТ
Верхний уровень не может выполнить этот запрос «только своими силами», определив по символьному имени DIR1/MY/FILE.TXT физический адрес файла, он обращается с запросом к нижележащему уровню:
ПРОЧИТАТЬ 22 ЛОГИЧЕСКУЮ ЗАПИСЬ ИЗ ФАЙЛА.
ИМЕЮЩЕГО ФИЗИЧЕСКИЙ АДРЕС 174 И РАЗМЕР 235
В ответ на запрос второй уровень определяет, что файл с адресом 174 занимает на диске пять несмежных областей, а искомая запись находится в четвертой области в физическом блоке 345. После этого он обращается к драйверу с запросом о чтении требуемой логической записи.
В соответствии с этой упрощенной схемой взаимодействие уровней файловой системы было однонаправленным — сверху вниз. Однако реальная картина существенно сложнее. Действительно, чтобы определить характеристики файла, верхний уровень должен «раскрутить» его символьное имя, то есть последовательно прочитать всю цепочку каталогов, указанную в имени файла. А это значит, что для решения свой задачи он несколько раз обратится к нижележащему уровню, который в свою очередь несколько раз «попросит» драйвер считать данные каталогов с диска. И каждый раз результаты будут передаваться снизу вверх.
Задача организации взаимодействия компьютеров в сети тоже может быть представлена в виде иерархически организованного множества модулей. Например, модулям нижнего уровня можно поручить вопросы, связанные с надежной передачей информации между двумя соседними узлами, а модулям следующего, более высокого уровня — транспортировку сообщений в пределах всей сети. Очевидно, что последняя задача — организация связи двух любых, не обязательно соседних узлов — является более общей и поэтому ее решение может быть полу-
А В Рис. 4.4. Взаимодействие произвольной пары узлов |