АВТОМАТИЗАЦИЯ ПРОЦЕССА ПРОГРАММИРОВАНИЯ
Ю.А. Великоруссов Научный руководитель - к. т.н., доцент Б.А. Крылов
В работе рассматривается одна из наиболее актуальных и перспективных задач современного этапа развития САПР - автоматизация процесса программирования предметной области изображения. Для решения данного вопроса выбраны методы и инструменты порождающего программирования. Эта технология учитывает преимущества автоматизации применительно к разработке программных средств
Введение
Сегодня компьютерные науки находятся на пороге кардинального обновления, причем в наибольшей степени это касается области программирования и принципов проектирования. Тенденция к переходу от объектов и вещей к понятиям и характеристикам набрала большие обороты. Именно на этой теории основывается система порождающего программирования; в значительной степени она сформировала такие методики, как инженерия предметной области.
Принципы разработки программного обеспечения, применяемые в настоящее время (включая распространенные объектно-ориентированные методы анализа и проектирования), нацелены на разработку конкретной системы в расчете на определенную задачу и фиксированный контекст. Это методики формирования одиночных систем. Напротив, инженерия предметной области устремлена на создание программных продуктов многократного применения. Она применяется при решении разнообразных задач различных групп заказчиков [1].
Первый международный симпозиум по порождающей и компонентной программной инженерии был проведен в Германии в 1999 году. В нем исследователи попытались свести свои идеи по разработке программного обеспечения воедино, отказавшись от выведения очередных методик путем их противопоставления предшественникам. Объединение новых концепций по многократному применению программных продуктов происходит на многочисленных семинарах и конференциях.
Технологии порождающего программирования способствуют автоматизации процесса программирования предметной области изображения. Они обеспечивают автоматизацию производства промежуточных и конечных продуктов: компонентов и приложений.
Порождающее программирование
Порождающее программирование - это автоматизированное производство программных продуктов из отдельных компонентов. Переход к автоматическому производству программного обеспечения основывается на выполнении следующих шагов: во-первых, необходимо перейти от разработки одиночных систем к разработке семейств систем - это позволит подготовить «правильные» компоненты реализации; во-вторых, нужно автоматизировать сборку компонентов реализации при помощи генераторов.
Порождающее программирование фокусирует внимание на семействах программных систем, а не на уникальных продуктах. Элементы семейства не строятся с нуля, они генерируют на основе общей порождающей доменной модели, т. е. модели семейства системы компонентов изображения. Она обладает тремя составляющими: средствами определения членов семейства или пространством задачи; компонентами реализации, из которых может быть собран каждый член; и базой знаний о конфигурациях или пространством решений, отображающим спецификацию для члена семейства в конечный продукт [1].
Пространство решений состоит из компонентов реализации во всех возможных комбинациях. Компоненты реализации разрабатываются в расчете на максимальную сочетаемость, минимальную избыточность и предельное увеличение возможностей повторного использования. В пространство задачи входят прикладные понятия и характеристики, посредством которых разработчики прикладного программного обеспечения могут выражать свои потребности. Знания о конфигурациях устанавливают недопустимые сочетания характеристик, настройки по умолчанию, зависимости по умолчанию (расчет некоторых «параметров по умолчанию» может производиться с учетом других характеристик), правила конструирования (некоторые сочетания характеристик превращаются в определенные сочетания компонентов реализации) и правила оптимизации (одни сочетания компонентов реализации могут оказаться лучше других).
Порождающее программирование эффективно применяется для разработки и реализации порождающей доменной модели системы обработки изображений. Основными этапами разработки метода порождающего программирования предметной области изображения являются следующие:
1. моделирование характеристик и понятий предметной области изображения (регистрация изображения, восстановление, улучшение и сжатие изображения, обработка цветного изображения, сегментация, представление и описание, распознавание объектов);
2. проектирование общей архитектуры и выявление компонентов реализации;
3. определение предметно-ориентированных нотаций, при помощи которых будет производиться «заказ» системы;
4. установление знаний о конфигурациях;
5. реализация компонентов реализации;
6. реализация предметно-ориентированных нотаций;
7. реализация знаний о предметной области при помощи генераторов.
Этап моделирования предметной области направлен на разработку характеристических моделей ее основных понятий.
Компоненты системы обработки изображения (подсистема регистрации изображения, специализированные устройства обработки изображения, подсистема отображения, подсистема массовой памяти и выдачи твердой копии, программы для обработки изображения) должны быть совместимы и сочетаемы друг с другом максимальное количество раз. Необходимо минимизировать дублирование кода и максимизировать его повторное использование [2].
Порождающее программирование помогает разработать «правильные» компоненты для системы изображения и после этого создать на их основе автоматическое предоставление лучших компонентов.
DEMRAL как образец метода инженерии предметной области
Инженерия предметной области изображения - это деятельность по сбору, систематизации и сохранению наработанного опыта создания систем или частей систем в форме средств многократного применения в рамках данной предметной области, а также по обеспечению методов для повторного использования этих средств (поиска, классификации, распространения, адаптации, сборки) в процессе создания новых систем.
Инженерия предметной области применяется при решении разнообразных задач, таких как разработка предметно-ориентированных каркасов и языков, библиотек компонентов и генераторов. Предметно-ориентированные языки в порождающем программировании обеспечивают возможность «заказа» конкретных членов семейства системы формирования и обработки изображения.
DEMRAL (Domain Engineering Method of Reusable Algorithmic Libraries), т.е. «метод разработки алгоритмических библиотек многократного применения на основе ин-
женерии предметной области» - это метод, специализированный для разработки порождающих алгоритмических библиотек [1]. К категории алгоритмических относятся библиотеки численного анализа, контейнеров, обработки изображений, распознавания изображений, распознавания речи, вычислений графов и т.д.
При помощи предметно-ориентированных языков конфигурирования специфицируются конкретные экземпляры понятий - в частности, структуры данных, алгоритмы, объекты и т.д. Ввиду ограниченности вариантов соединения компонентов реализации их правильные конфигурации можно описать на так называемом языке конфигурирования компонентов реализации - 1ССЬ. Предметно-ориентированный язык конфигурирования относится к пространству задачи, а 1ССЬ - к пространству решений. Перевод с одного из этих языков на другой осуществляется через генератор. Предметно-ориентированный язык призван обеспечить пользователю возможность обозначить свои потребности на оптимальном уровне детализации. Задача 1ССЬ, напротив, заключается в том, чтобы добиться максимальной гибкости и возможности повторного использования компонентов реализации (рис. 1).
Транслятор Порождающий компонент
Рис. 1. Реализация предметно-ориентированного языка конфигурирования
порождающим компонентом
Благодаря предметно-ориентированным языкам конфигурирования пользователи компонентов имеют возможность указания своих потребностей с оптимальной степенью детализации. Клиентская программа не вводит лишних зависимостей от параметров реализации серверного компонента. Предположим, что клиент хочет запросить у порождающего матричного компонента конкретную матрицу. В ответ на этот запрос матричный компонент должен создать матрицу с некими допустимыми параметрами по умолчанию - к примеру, прямоугольной формы, с действительными значениями элементов, с динамическим количеством строк столбцов и т.д. У клиента должна быть возможность пропускать те или иные характеристики спецификации; в таком случае порождающий компонент определяет эту характеристику как прямое умолчание или вычисляемое умолчание. При обозначении характеристик можно указать некоторые подробности наподобие профиля применения - например, отметить, что нужна плотная или разреженная матрица, матрица, оптимизированная по быстродействию или размещению. У клиента должна быть возможность напрямую указывать те или иные характеристики реализации. Наконец, клиент волен предлагать собственные реализации не-
которых характеристик. Различные уровни детализации при задании конфигурации приводятся на рис. 2.
Неточная [спецификация]
Точная [спецификация]
Указания отсутствуют (выбор матрицы стандартного формата, стандартной формы и других умолчаний)
Более точные указания (выбор формата на основе спецификации сложности, плотности и формы)
Прямые указания (прямая спецификация формата - например, «С-массив»)
Предложенная клиентом реализация (клиент представляет собственный вариант реализации формата)
Профиль применения (выбор формата исходя из флага оптимизации (быстродейст-вие/пространст во), плотности
(плотная/разреженна я) и формы)
Рис. 2. Детализация при задании изменяемых характеристик
Перечислим отличительные черты алгоритмических библиотек, наиболее часто применяемых для обработки изображения.
1. Основные понятия предметной области в достаточном для поставленных задач объеме фиксируются в виде абстрактных типов данных и оперирующих с ними алгоритмов.
2. Свойства абстрактных типов данных зачастую схожи со свойствами контейнеров -в их числе могут быть матрицы, изображения, графы и т.д.
3. Построения делаются на основе развитых математических теорий - например, на основе линейной алгебры, математических моделей построения изображения, базисных функций, гистограмм изображения [3].
4. Абстрактные типы данных и алгоритмы отличаются многообразием. Например, в большом количестве представлены матрицы, которые различаются по плотности (плотная или разреженная), форме (диагональная, квадратная, симметричная, ленточная), формату хранения и другим параметрам [2].
Для проектирования библиотек БЕМЯЛЬ обеспечивает достижение следующих целей.
1. Предоставление клиенту высокоуровневого ментального интерфейса библиотеки: клиентский код определяет задачи с точки зрения высокоуровневых понятий предметной области; интерфейс обеспечивает эффективную поддержку многочисленных вариантов понятий; клиентский код определяет задачи с оптимальной степенью детализации (он может «заказывать» реализации понятий по умолчанию или указывать столько деталей, сколько нужно в данной ситуации - не больше и не меньше).
2. Оптимизация времени исполнения и потребления памяти: наличие большого количества вариантов не должно способствовать снижению эффективности; возможности оптимизации должны подвергаться анализу, а те из них, которые будут признаны полезными, - реализовываться; неиспользуемая функциональность должна удаляться.
3. Достижение наиболее высокого качества кода библиотеки: обеспечение максимальной адаптируемости и расширяемости; сведение дублирования и усложнения кода к минимуму.
БЕМЯЛЬ - это уникальный метод, аккумулирующий концепции инженерии предметной области, генераторов, метапрограммирования, аспектно-ориентированного программирования, объектно-ориентированной разработки программных средств и других областей.
Генераторы
Современные универсальные языки программирования не предполагают достаточной степени гибкости, ментального, четкого кодирования и высокой производительности. В частности, чтобы повысить производительность кода, приходиться прибегать к его ручной оптимизации, которая разрушает четкую структуру кода. Аналогичное воздействие на код оказывает внедрение аспектов - например, обработки ошибок и синхронизации. Ввиду невозможности замены аспекта альтернативной реализацией страдает гибкость.
Чтобы избежать этих трудностей, работу, связанную с оптимизацией и переплетением, передают генераторам - они вычислят наиболее эффективную реализацию программы обработки изображения на основе высокоуровневой спецификации. Полный цикл работы генератора представлен на рис. 3.
Высокоуровневая Низкоуровне-
Неформальные формальная спе- вая формальная
треб°вания цификация спецификация Реализация
Новые требования
Рис. 3. Модель трансформационного жизненного цикла
Генератор может взять программу, написанную на высокоуровневом языке программирования, и сгенерировать ее реализацию на машинном языке или в виде байт-кода. Генераторы, вырабатывающие реализации моделей (которые довольно часто отображаются в графическом виде) на том или ином языке программирования, присутствуют в большинстве средств автоматизированного проектирования и создания программ обработки изображения. Реализации графически специфицируемых конфигураций компонентов предусматриваются в различного рода компонентных средах и компоновщиках графических пользовательских интерфейсов [1].
В цифровой обработке изображения генераторы выполняют три существенных функции.
1. Повышение ментальности описаний систем. Ментальные описания отличаются тем, что задачи в них излагаются точно и ясно, без лишнего мусора и несущественных деталей реализации. Они аккумулируют все наилучшие качества кода: понятность простота анализа, модифицируемость, удобство сопровождения и т.д. Средством достижения ментальности являются предметно-ориентированные нотации, за реализацию которых и отвечают генераторы.
2. Определение эффективности реализации. Минимальное изменение спецификации может повлечь за собой необходимость в кардинальной переделке реализации.
3. Снятие проблемы масштабируемости библиотек. Чтобы избежать экспоненциального роста объема библиотеки, ее можно разложить на компоненты, соответствующие характеристикам, а затем при помощи вызовов функций или методов скомпоновать. Генераторы обеспечивают сочетание эффективного разложения с высочайшей производительностью.
Аспектно-ориентированное программирование
Аспектно-ориентированное программирование содержит различные методы и методики разбиения задач на ряд функциональных компонентов, которые выражаются в виде объектов, модулей, процедур и т.д., а также аспектов, которые «пересекают» функциональные компоненты и предусматривают их композицию в целях получения реализаций систем. В настоящее время существует несколько методик, ориентированных на инкапсуляцию различных свойств систем, в том числе и аспектов, которые пересекаются с модульными функциональными элементами.
Фильтры композиции ориентированы на разрешение трудностей, связанных с координацией сообщений в традиционной объектной модели. Объект в рамках модели фильтров композиции изображен на рис. 4.
Центральный Интерфейсный Входящие сообщения
Рис. 4. Элементы объекта в рамках модели фильтров композиции
К примеру, чтобы выразить синхронизацию на интерфейсном уровне объекта, соответствующий код требуется вставить во все подлежащие синхронизации методы. Ручное встраивание кода в методы приводит к смещению функционального и синхронизационного кода и, следовательно, ограничивает возможность многократного применения. Как правило, при расширении класса путем определения его подкласса и его методов приходится обновлять в расчете на этот подкласс всю схему синхронизации и переопределять большинство унаследованных методов, хотя базовые функциональные возможности последних не претерпевают никаких изменений. Причина, по которой код синхронизации приходится обновлять, заключается в том, что он разбросан по различ-
ным методам. Эта и другие подобные проблемы называются аномалиями наследования. Одним из наиболее существенных недостатков традиционной объектной модели является отсутствие механизмов, обеспечивающих отделение функциональной части от кода координации сообщений.
Благодаря фильтрам композиции традиционная объектная модель дополняется рядом различных фильтров сообщений, через которые проходят пересылаемые от объекта к объекту сообщения. Он состоит из интерфейсного уровня и центрального объекта. Центральным объектом может быть любой обычный объект, определяемый в традиционных объектно-ориентированных языках программирования, наподобие Java и C++. Интерфейсный уровень содержит произвольное количество входных и выходных фильтров сообщений. Фильтры могут вносить в проходящие сообщения некоторые изменения - например, менять их имена или переопределять целевые объекты.
Следовательно, одна из их возможных функций заключается в переадресации сообщений другим объектам - внутренним, т.е. существующим в рамках интерфейсного уровня, и внешним, т.е. тем, на которые на интерфейсном уровне установлены ссылки; кроме того, фильтры используются для трансляции сообщений путем замены их имен. Фильтры способны отбрасывать и буферизовать сообщения, порождать исключения. То, какому из упомянутых действий будет отдаваться предпочтение, зависит от типа конкретного фильтра. Существует ряд предопределенных типов фильтров - в частности, фильтры ожидания (для буферизации сообщений), фильтры ошибок (для порождения исключений). Решение о том, будет ли сообщение исправлено или оставлено в первоначальном виде, принимается в зависимости от конкретного сообщения и от условий составления центрального объекта.
Методика фильтрации в обработке изображения крайне эффективна; она позволяет реализовать и обеспечить четкую локализацию синхронизационных ограничений, ограничений реального времени, проверки ошибок по предусловиям и других аспектов. К элементам изображения применяется сглаживающая пространственная фильтрация для расфокусировки изображения и подавления шума, а также фильтры низких высоких частот, частотные фильтры повышения резкости и др. [2].
Рис. 5. Делегирование и наследование в рамках модели фильтров композиции
При участии переадресации сообщений реализуются делегирование и динамическое наследование. Делегирование предполагает переадресацию отдельных получаемых делегирующим объектом сообщений другому - уполномоченному - объекту согласно установленной в рамках первого ссылки на последний.
В рамках модели фильтров композиции под делегированием понимается переадресация сообщений внешним объектам и обеспечение отсылки self к исходному получателю. Наследование, напротив, предполагает перенаправление сообщений внутренним объектам, но при этом зарезервированное слово self также должно отсылаться к исходному получателю [1].
На основе тех или иных условий состояния фильтр может делегировать сообщения к различным внутренним объектам. Следовательно, имеет место динамическое наследование, при котором суперкласс объекта способен меняться в зависимости от состояния этого объекта (рис. 5).
Метапрограммирование
В настоящее время потребность в системах обработки изображения, обеспечивающих возможность быстрой настройки с расчетом на конкретную среду размещения или предполагающих динамическую самонастройку в отношении изменяющейся среды в период прогона, постоянно растет. Необходима возможность корректировки различных аспектов компонентов, конфигурирования и сборки этих компонентов средствами автоматических процессов и анализа работы конечных систем. Некоторые библиотеки способны автоматически адаптировать код, который они поставляют в компиляторную систему. В частности, отбирая алгоритмы и представления данных, наилучшим образом подходящие к целевой платформе, они корректируют свои компоненты.
Автоматическое конфигурирование и сборка, параметризация аспектов, динамическая и статическая приспосабливаемость и адаптивность - чтобы все это можно было провести в жизнь, требуются технологии объявления функциональности компонентов, управления их параметрами и/или реализациями. Этим задачам отвечает метарпограм-мирование - оно позволяет писать программы, представляющие другие программы и управляющие ими же или сами собой [1].
Приставка «мета» выражает «описание чего-то чем-то» - таким образом, метапро-граммы - это программы о программах. Практических примеров метапрограммирова-ния - великое множество: генераторы, компиляторы и интерпретаторы программ, представляющие и управляющие программами на соответствующих языках, а также программы, оснащающие другие программы в целях их тестирования и профилирования, аспектные программы, воздействующие на семантику компонентов, оптимизаторы, средства автоматического рефакторинга.
Заключение
В данной работе проведен краткий обзор автоматизации процесса развития программных средств возможностями порождающего программирования. Рассмотрены методы анализа и проектирования предметной области изображения, предметно-ориентированные языки, в частности, DEMRAL как образец метода инженерии предметной области, соответствующего задачам порождающего программирования. Также проанализированы некоторые технологии реализации программного продукта, такие как генерация, аспектно-ориентированное программирование и метапрограммирование.
Идея порождающего программирования - строить порождающие модели для семейств систем и генерировать конкретные системы по этим моделям. Для каждого сгенерированного члена многократно используются компоненты реализации и знания о конфигурациях.
Разработка многократно используемых компонентов требует выявление не только общности членов семейств, но и существенных параметров изменчивости. Выявление предметной области и моделирование характеристик предоставляют систематический
способ определения того, какие характеристики и изменяемые параметры нуждаются в немедленной реализации, а какие должны быть запланированы на будущее.
Автоматизация развития станет возможной лишь в случае представления систем при помощи высокоуровневых предметно-ориентированных нотаций, которые позволят явным образом выражать основные свойства систем и фиксировать все проектные решения периода разработки. Чем больше высокоуровневой проектной информации содержится в исходном коде систем, тем шире возможности автоматизации.
Расширяемые среды программирования, стандартизация архитектуры для предметной области и рост рынка компонентов также будут способствовать большей автоматизации и специализации в разработке программного обеспечения.
Литература
1. Чарнецки К., Айзенекер У. Порождающее программирование: методы, инструменты, применение. СПб: Питер, 2005. 731 с.
2. Гонсалес Р., Вудс Р. Цифровая обработка изображения. М.: Техносфера, 2006. 1072 с.
3. Ritter G., Joseph N. Wilson. Handbook of Computer Vision Algorithms in Image Algebra / CRC Press, Boca Raton. 1997. P. 437-442.