Объектно-ориентированный анализ
Программирование телевизионного вещания
Рассмотрим конкретное применение ОО-концепций в интересах чистого моделирования.
В качестве примера рассмотрим организацию планирования сетки телевизионного вещания. Поскольку это знакомая всем прикладная задача, можно начать ее решение без привлечения экспертов и будущих пользователей. Для проведения анализа достаточно полагаться на понимание рядового телезрителя.
Хотя данная попытка является лишь прелюдией к созданию автоматизированной системы управления телевизионным вещанием, в данном случае это несущественно, поскольку нас интересуют исключительно вопросы моделирования.
Графики вещания
Сосредоточимся на 24-часовом графике вещания. Его представляет класс (абстракция данных) SCHEDULE. График содержит последовательность отдельных программных сегментов:
class SCHEDULE feature segments: LIST [SEGMENT] end
При проведении анализа необходимо постоянно помнить об опасности избыточной спецификации. Не является ли избыточным использование LIST? Нет: LIST это отложенный класс, описывающий абстрактное понятие последовательности, что соответствует характеру телевизионного вещания - одновременная передача двух сегментов невозможна. Использование LIST фиксирует свойство проблемы, а не ее решение.
Попутно отметим важность повторного использования: применение классов, подобных LIST, сразу открывает доступ к целому набору операций со списками: команде put для добавления элементов, запросу count для получения номера элемента и другим.
Свести понятие графика к списку его сегментов нельзя. Объектная технология, как следует из обсуждения абстрактных типов данных, является неявной; она описывает абстракции путем перечисления их свойств. График передач - это нечто большее, чем список его сегментов, так что необходим отдельный класс. Другие свойства представляются естественным образом:
indexing description: "24-часовой график ТВ вещания" deferred class SCHEDULE feature segments: LIST [SEGMENT] is -- Последовательность сегментов deferred end air_time: DATE is -- Дата вещания deferred end set_air_time (t: DATE) is -- Установка даты вещания require t.in_future deferred ensure air_time = t end print is -- Вывод графика на печать deferred end end
Отметим использование отложенной реализации. Это связано с природой анализа, не зависящего от реализации, а часто и от проектирования, так что отложенная форма записи является удобным инструментом. Можно, конечно, вместо отложенной спецификации использовать формализм типа краткой формы. Однако есть два важных довода в пользу полной нотации:
- При записи текста в полном соответствии с синтаксисом можно использовать весь набор средств, предоставляемый средой разработки ПО. В частности, механизм компиляции играет в этом случае ту же роль, что и совершенные CASE-средства, осуществляя контроль спецификации на использование типов и других ограничений, позволяя избежать противоречий и двусмысленностей и существенно снизить затраты времени. Средства просмотра и документирования хорошей OO среды столь же полезны для анализа, как и для этапов проектирования и реализации.
- Использование стандартной нотации существенно облегчает последующий переход к проектированию и реализации программной системы. В этом случае работа сведется к добавлению новых классов, эффективных версий отложенных реализаций и новых компонентов. Такой подход обеспечивает бесшовный процесс разработки, обсуждаемый в следующей лекции.
Класс содержит булев запрос in_future для объекта типа DATE, для указания на будущее время выхода в эфир. Следует отметить первое использование предусловия и постусловия для выражения семантических свойств системы в процессе анализа.
Сегменты
Прежде чем продолжать уточнение и расширение SCHEDULE, необходимо обратиться к понятию SEGMENT. Можно начать со следующего описания:
indexing description: "Отдельные сегменты графика вещания" deferred class SEGMENT feature schedule: SCHEDULE is deferred end -- График, содержащий данный сегмент index: INTEGER is deferred end -- Положение сегмента в графике starting_time, ending_time: INTEGER is deferred end -- Время начала и завершения next: SEGMENT is deferred end -- Следующий сегмент, если он существует sponsor: COMPANY is deferred end -- Основной спонсор rating: INTEGER is deferred end -- Рейтинг сегмента (допустимость просмотра детьми и т.д.) ... Опущены команды change_next, set_sponsor, set_rating и др. ... Minimum_duration: INTEGER is 30 -- Минимальная длительность сегмента в секундах Maximum_interval: INTEGER is 2 -- Максимальная пауза между соседними сегментами в секундах invariant in_list: (1 "= index) and (index "= schedule.segments.count) in_schedule: schedule.segments.item (index) = Current next_in_list: (next /= Void) implies (schedule.segments.item (index + 1) = next) no_next_iff_last: (next = Void) = (index = schedule.segments.count) non_negative_rating: rating >= 0 positive_times: (starting_time > 0) and (ending_time " 0) sufficient_duration: ending_time - starting_time >= Minimum_duration decent_interval: (next.starting_time) - ending_time >= Maximum_interval end
Каждый сегмент "может определить" график, частью которого он является, и свое положение с помощью запросов schedule и index. Он содержит запросы starting_time и ending_time, к которым можно добавить и запрос duration, с инвариантом, связывающим длительность сегмента с временем начала и завершения. Такая избыточность допустима в системном анализе, добавление избыточных свойств отражает особенности, представляющие интерес для пользователей или разработчиков. Отношения между избыточными элементами фиксируются в соответствующих инвариантах. Инварианты in_list и in_schedule отражают позицию сегмента в списке сегментов и в графике.
Сегмент также "знает" о следующем сегменте. Инварианты отражают требования последовательности: next_in_list указывает, что если позиция текущего сегмента - i, то следующего - i +1. Инвариант no_next_iff_last служит признаком того, является ли данный сегмент последним в графике.
Два последних инварианта выражают ограничения на продолжительности: sufficient_duration определяет минимальную продолжительность в 30 секунд для фрагмента программы, являющегося сегментом, а decent_interval - максимальную паузу в 2 секунды между двумя последовательными сегментами (темный экран).
Спецификация класса содержит два недостатка, которые почти наверняка придется устранить при следующей итерации. Во-первых, время и продолжительность выражаются целыми числами (в секундах). Целесообразнее применить более абстрактный вариант - использование библиотечных классов DATE, TIME и DURATION. Во-вторых, понятие SEGMENT охватывает два отдельных понятия: фрагмент телевизионной программы и временное планирование. Разграничение этих понятий достигается добавлением в SEGMENT атрибута
content: PROGRAM_FRAGMENT
и нового класса PROGRAM_FRAGMENT для описания программного фрагмента вне зависимости от его положения в графике. Компонент duration нужно поместить в PROGRAM_FRAGMENT, а новое инвариантное предложение в SEGMENT примет вид:
content.duration = ending_time - starting_time
Для краткости в остальной части этого эскиза содержание обрабатывается как часть сегмента. Подобные дискуссии типичны для процесса анализа, поддержанного ОО-методом: мы исследуем различные абстракции, обсуждаем, необходимы ли для них различные классы, перемещаем компоненты, если считаем, что они не на своем месте.
Сегмент имеет основного спонсора и рейтинг. Хотя здесь также более выгоден отдельный класс, рейтинг определен как целое число, большее значение рейтинга означает более строгие ограничения. Значение 0 соответствует сегменту, доступному всем зрителям.
Программы и реклама
Развивая далее понятие SEGMENT, введем два вида сегментов: программные и коммерческие (рекламные сегменты). Это наводит на мысль использовать наследование.
Использование наследования в процессе анализа всегда вызывает подозрения. Не следует создавать лишних классов там, где достаточно введения отличительного свойства. Руководящий критерий был дан при рассмотрении наследования: действительно ли каждый предложенный класс реально соответствует отдельной абстракции, характеризующейся специфическими особенностями? В данном случае использование нового класса оправдано, поскольку разумно предложить специальные свойства классу COMMERCIAL, как будет показано ниже. Наследование сопровождается преимуществами открытости: можно позже добавить нового наследника INFOMERCIAL (рекламный ролик) для описания сегмента другого вида.
Начнем работу над COMMERCIAL:
indexing description: "Рекламный сегмент" deferred class COMMERCIAL inherit SEGMENT rename sponsor as advertizer end feature primary: PROGRAM is deferred -- Программа, с которой связан данный сегмент primary_index: INTEGER is deferred -- Индекс сегмента primary set_primary (p: PROGRAM) is -- Связать рекламу с p require program_exists: p /= Void same_schedule: p.schedule = schedule before: p.starting_time <= starting_time deferred ensure index_updated: primary_index = p.index primary_updated: primary = p end invariant meaningful_primary_index: primary_index = primary.index primary_before: primary.starting_time <= starting_time acceptable_sponsor: advertizer.compatible (primary.sponsor) acceptable_rating: rating <= primary.rating end
Использование переименования является еще одним примером полезного средства нотации. Оказывается, оно необходимо не только на этапе реализации, но и для моделирования. Спонсора рекламного фрагмента уместнее называть рекламодателем.
Каждый рекламный сегмент присоединен к некоторому программному (некоммерческому) сегменту, индекс которого в графике задается значением primary_index. Два первых инварианта отражают условия последовательности, последние два - совместимости:
- Если программа имеет спонсора, то в течение ее показа приемлема далеко не любая реклама. Никто не будет рекламировать Pepsi-Cola в телешоу, спонсируемом Coca-Cola. Можно выполнить запрос к некоторой базе данных о совместимости.
- Рейтинг рекламы должен соответствовать программе: реклама бульдозера неуместна в передаче для малышей.
Понятие primary требует уточнения. На этом этапе анализа становится ясно, что нужно добавить новый уровень: вместо графика, являющегося последовательностью программных и рекламных сегментов, необходимо рассмотреть последовательность телепрограмм (описывается классом SHOW ), каждая из которых имеет собственные компоненты, спонсора и последовательность сегментов. Такое усовершенствование и уточнение, разработанное на основе лучшего понимания проблемы и опыте первых шагов, является нормальным компонентом процесса анализа.
Деловой регламент
Мы видели, как инварианты и другие утверждения могут охватить семантические ограничения прикладной области. В терминах анализа это называют деловым регламентом: для класса SCHEDULE можно планировать размещение сегмента только в будущем; в классе SEGMENT определено, что пауза между двумя сегментами не должна превышать установленного значения; в COMMERCIAL рейтинг рекламы должен соответствовать рейтингу передачи.
Принципиальным вкладом ОО-метода является возможность для таких правил использования утверждений и принципов Проектирования по Контракту наряду с заданием структуры.
Практическое предупреждение: даже если реализация не предусматривается, остается риск чрезмерной спецификации. Нужно включать в текст анализа только правила, имеющие высокую степень достоверности и долговечности. Если какое-то правило может меняться, то лучше использовать абстракцию, чтобы оставить место для необходимой адаптации. Например, могут измениться правила совместимости спонсора и рекламодателя, поэтому выбранная абстрактная форма инварианта acceptable_sponsor является приемлемой. Важнейшим преимуществом анализа является возможность выбора, какие особенности принимать во внимание, а какие игнорировать. Здесь действует то же соображение, которое было высказано при обсуждении абстрактных типов данных: нам нужна правда, только правда и ничего кроме правды.
Оценка
Пример с телевизионной программой находится еще на начальной стадии, но он содержит достаточно для понимания общих принципов подхода. Использованные ОО-концепции и нотация для решения общих задач системного моделирования являются удивительно мощными и интуитивно понятными. А ведь их первоначальное назначение - разработка ПО, и могло казаться, что они непригодны для иных целей. Здесь же метод и нотация в полной мере проявили свои универсальные возможности описания систем различных типов, задавая при этом как общую структуру систем, так и детали семантики.
Рассмотренная выше спецификация не содержит ничего, что связывало бы ее с реализацией или компьютерами. Концепции объектной технологии используются исключительно для описательных целей, компьютеры для этого не нужны.
Естественно, что, если в дальнейшем будет разрабатываться программная система управления работой телестанции, то имеющееся описание обладает неоспоримым преимуществом, поскольку форма его представления в синтаксическом и структурном отношении находится в полном соответствии с описанием ПО. Это основа для бесшовного перехода к проектированию и реализации. В завершенной системе удастся сохранить многие классы, введенные в процессе анализа, снабдив их соответствующей реализацией.