3. Миттнахт М., Хартрампф М., Васильев М. В., Михайлов Н. В. Высокоточная относительная навигация ИСЗ по спутникам системы GPS // IX Санкт-Петербургская междунар. конф. по интегрированным навигационным системам. 2002.
4. Busse F. D. Precise Formation-State Estimation in Low Earth Orbit Using Carrier Differential GPS. Ph.D. dissertation. Stanford University, 2001.
5. Leung S., Montenbruck O. Real-Time Navigation of Formation Flying Spacecraft using Global Positioning System Measurements // J. Guidance, Control and Dynamics. Vol. 28(2). P. 226—235.
6. Kroes R. Precise relative positioning of formation flying spacecraft using GPS // Publications on Geodesy Delft, 2006. P. 61.
7. Kroes R., Montenbruck O., Bertiger W., Visser P. Precise GRACE baseline determination using GPS // GPS Solutions. 2005. Vol. 9. P. 21—31.
8. Shaer S. Mapping and Predicting the Earth's Ionosphere Using the Global Positioning System. 1999 [Electronic resource]: <ftp://ftp.unibe.ch/aiub/papers/ionodiss.pdf>.
9. Михайлов Н. В., Васильев М. В., Михайлов В. Ф. Автономная навигация космических кораблей с использованием GPS // Гироскопия и навигация. 2008. № 1.
10. [Электронный ресурс]: <ftp://ftp.unibe.ch/aiub/ionosphere/doc/C0D08443.I0N, ftp://ftp.unibe.ch/aiub/ionosphere/doc/ gimman.ps>.
11. Михайлов Н. В., Михайлов В. Ф. Метод разрешения неоднозначности фазовых измерений GPS при относительной навигации космических объектов // Гироскопия и навигация. 2008. № 4.
12. Михайлов Н. В., Михайлов В. Ф. Применение метода разрешения неоднозначности фазовых измерений GPS для автономной относительной навигации космических кораблей // Гироскопия и навигация. 2009. № 1.
13. Михайлов Н. В., Михайлов В. Ф. Методы первичной обработки сигналов в радионавигационных приемниках космического базирования // Гироскопия и навигация. 2009. № 4.
Сведения об авторе
Николай Викторович Михайлов — канд. физ-мат. наук; Санкт-Петербургский государственный университет аэрокосмического приборостроения; старший преподаватель; E-mail: [email protected]
Рекомендована ГУАП Поступила в редакцию
04.04.11 г.
УДК 004.05
С. А. Власов, В. В. Бураков
ПОДХОД К СПЕЦИФИКАЦИИ СТРУКТУРНОЙ МОДИФИКАЦИИ КОДА БОРТОВОГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
Представлен подход к спецификации структурных модификаций бортового программного обеспечения, направленных на повышение показателей надежности и безопасности. Подход основан на применении модификаций, описанных графовыми продукциями над графовым представлением исходного кода.
Ключевые слова: рефакторинг, модификация, граф, продукция.
К программному обеспечению, входящему в состав бортовых комплексов, традиционно предъявляются повышенные требования по надежности и безопасности. Помимо этого, к важным свойствам таких программ относят высокое качество, поддающееся проверке, непротиворечивость, возможность повторного использования, низкую стоимость технического обслуживания, быструю интеграцию с аппаратными средствами, возможность переноса на другие платформы [1]. Вместе с тем не менее важным представляется
обеспечение такого качества бортового программного обеспечения, как сопровождае-мость. Хороший уровень сопровождаемости обеспечивается оптимальной структурой программы, для достижения которой используется рефакторинг. К процессу рефакторинга программного обеспечения бортовых систем, как и к самим программам, предъявляются повышенные требования по надежности и безопасности. Обеспечить эти требования в отсутствие непротиворечивого математического базиса представляется практически невозможным [2].
Рефакторинг исходного кода объектно-ориентированных программ заключается в изменении структуры кода в соответствии с заданными в системе шаблонами. Большую работу по созданию таких шаблонов провел М. Фаулер [3], составив один из наиболее полных каталогов шаблонов рефакторинга. Каталог состоит более чем из 120 преобразований, применение которых упрощает работу программиста.
Наиболее близкими, с функциональной точки зрения, аналогами разрабатываемой системы являются Eclipce IDE и плагин, разработанный Jet Brains к среде разработки Microsoft Visual Studio — ReSharper. Функциональность обоих программных решений включает поиск дефектов, метрический анализ исходного кода и инструмент рефакторинга. Эти системы умеют определять явные стилистические, структурные и поведенческие дефекты исходного кода, предлагая несколько вариантов их решения, а инструмент рефакторинга помогает быстро изменить структуру исходного кода, сохраняя ее работоспособность. Основным недостатком указанных систем является ограниченность набора шаблонов и невозможность их пополнения [4]. Существует несколько подходов к реализации систем с пополняемым набором шаблонов, их различие заключается в способе представления исходного кода, и как следствие — способе представления шаблонов. Наиболее подходящей (ввиду своей математической природы) является теория графов, а наглядность представления программных сущностей и их поведения положительно сказывается на простоте задания самих шаблонов рефакторига.
Модель представления исходного кода. Для описания программных сущностей и их взаимоотношений были выбраны графы, а для описания преобразований — графовые мор-физмы. В рассматриваемом подходе это будет помеченный типизированный граф. Дадим несколько определений.
Ориентированный граф G = (V,E,s,t) состоит из двух множеств, конечного множества V, элементы которого называются вершинами, и конечного множества E, элементы которого называются ребрами. Каждое ребро связано с упорядоченной парой вершин. Для обозначения вершин используются символы v1,v2,v3_, а для обозначения ребер — символы e^e2,e3... Если e1 = (vi,vj), то Vj, и Vj называются оконечными вершинами e1, при этом vt — начальная вершина, a vj — конечная вершина e1. Функции s: E^ V и t: E^ V связывают с каждым ребром в точности одну начальную и одну конечную вершины [1].
Помеченный граф. Пусть L=(VL,EL), L-помеченный граф G представляет собой двойку (g,l) такую, что имеет место:
1) g = (VE,s,t) — граф;
2) l=(vl: V-^-VL, el:E^EL) — пара функций пометки соответственно вершин и ребер, при этом vl является инъективной функцией.
Помеченный типизированный граф. Пусть T=(VT,ET) — пара непересекающихся конечных множеств предопределенных типов вершин и ребер. L-помеченный T-типизированный граф G является двойкой (g,type), такой что g является L-помеченным графом, а type=(vt:V-^VT, et:E^ET) — пара функций, vt связывает с каждой вершиной из V ее тип из VT, а et — с каждом ребром из E его тип из ET.
Подграф. H является подграфом G (обозначается H œ G) если существует инъективный графовый морфизм m:H^G, называемый соответствием H в G.
Иными словами, каждая вершина и каждая дуга имеют соответственно тип как обязательный атрибут и, по необходимости, имя; каждая вершина связана с дугой, заканчивающейся другой вершиной. В графе не допускаются петли и связь двух вершин более чем одной дугой (параллельные дуги).
В качестве примера рассмотрим следующий участок исходного кода.
class Phone {
public:
void dialNumber(int number); bool busy;
Device dial; };
public: void Phone::dialNumber(int number) {
dial->getDevice();
busy = dial->line(number);
}
Вершины характеризуют такие программные сущности, как классы, методы, параметры. Примеры типов вершин приведены в табл. 1.
Таблица 1
Тип Описание Пример
Cl Класс class Phone
Ty Тип void
Va Переменная busy
Si Сигнатура метода dialNumber(int number)
Pa Параметр number
Bo Тело метода dial->getDevice();
Ex Выражение busy = dial->line(number);
Vi Область видимости public
Дуги графа характеризуют отношения между двумя вершинами, такие как наследование, связь переменной с типом, область видимости и т.д. На рис. 1 изображен граф, соответствующий представленному выше исходному коду. Таким образом, ввиду отсутствия ограничений на типы дуг и вершин и их конечное число можно говорить о полноте, или адекватности, данной графовой модели исходному коду. Пример дуг представлен в табл. 2.
Рис. 1
_Таблица 2
Тип Описание
si:Si^Bo Связь сигнатуры и тела метода
ge:Cl^a Наследование для классов
me:Bo^Cl Принадлежность метода классу
me:Va^Cl Принадлежность поля классу
ty:Pa^Cl Классовый тип формального параметра
ty:Pa^Ty Стандартный тип формального параметра
ty:Va^Ty Стандартный тип переменной
pa:Si^Pa Формальный параметр
pa:Ex^Ex Фактический параметр
ex:Bo^Ex Выражение в теле метода
co:Ex^Ex Подвыражение
ru:Ex^Si Вызов метода
ac:Ex^Va Доступ к переменной
up:Ex^Va Модификация переменной
Программная реализация описанного выше графа была создана в рамках разрабатываемой системы модификации исходного кода для среды разработки Microsoft Visual Studio IDE. Как и большинство программных решений этого типа, система выполнена в виде плагина к среде разработки.
Основные функции системы:
— построение графовой модели исходного кода проекта, открытого в среде разработки;
— исполнение рефакторингов на графовой модели исходного кода;
— преобразование измененной графовой модели исходного кода в текст программы;
— ведение пополняемого каталога шаблонов рефакторинга;
— средство визуального моделирования шаблонов рефакторинга.
Спецификация преобразований исходного кода. Для описания преобразований (ре-факторингов) используется теория перезаписи (перезаписывания) графов. Рефакторинг состоит из набора графовых продукций, представляющих собой логически законченные этапы преобразования исходного кода в соответствии с сутью самого преобразования.
Продукцияp:(L^R) состоит из имени продукцииp и инъективного частичного графового морфизма r, называемого морфизмом продукции. Графы L и R — соответственно левая и правая части продукции.
При перезаписи графа в левой части продукции описываются те вершины и ребра, которые должны присутствовать в исходном графе, а в правой — вид этой части графа после применения продукции. Частичный морфизм описывает отношения объектов левой части продукции L к правой R. Соблюдается ряд правил:
— объекты, не описанные морфизмом, удаляются;
— объекты правой части продукции, не имеющие прообраза в левой части, создаются заново;
— объекты, не изменяемые морфизмом, формируют контекст продукции.
Любой рефакторинг имеет ряд ограничений, или условий применимости к конкретному исходному коду. Например, переименование переменной не должно создать переменную с одинаковым именем в одной и той же области видимости имен, приводя тем самым к ошибке. Таким образом, к набору продукций добавляются условия, описанные одиночными, недопустимыми графами. Присутствие вершин и ребер недопустимого графа в графе исходного кода показывает невозможность выполнения данного рефакторинга, соответственно поиск недопустимых графов в графе исходного кода производится до выполнения преобразований.
Для практического применения графовое описание рефакторинга должно иметь обобщенный характер, т.е. отвечать двум критериям:
— не зависеть от таких деталей кода, как имена программных сущностей, их тип, и порядка следования операторов исходного кода;
— поддерживать множественную параметризацию.
Для обеспечения множественности входных параметров в качестве входных данных также выбран граф. Пользователь выделяет участок кода, который в преобразованном виде поступает на вход и служит шаблоном для заполнения графов рефакторинга. Первый критерий обеспечивается путем выделения трех категорий имен вершин и дуг:
— вершины, заполняемые из графа входных параметров;
— вершины, требующие дополнительного ввода (например, имени новой переменной при переименовании);
— вершины, логическим значением которых является „все".
Для простоты задания в имя вводится расширение „%" или „@", или „*". В свою очередь, сами имена, дополненные данным расширением, являются абстрактными обозначениями, определяющими соответствие между графами продукций, самими продукциями и графами условий. Вершины, имеющие подобные обозначения, заполняются в соответствии с графом входных параметров.
Пример спецификации преобразования кода. В качестве примера рассмотрим распространенный рефакторинг „выделение метода". Суть данного рефакторинга заключается в выделении части кода, в основном самодостаточной, вынесении ее в новый метод, а также формировании списка формальных и фактических параметров.
Создание нового метода. Первым преобразованием необходимо создать заготовку для нового метода, т.е. описать прототип и тело метода, пока пустое. Левая и правая части этого преобразования представлены на рис. 2.
Рис. 2
Морфизм, определенный данной продукцией, создает в графе исходного кода вершины сигнатуры и реализации метода с именем @method и типом void. Связь вершин %old_method с вершиной %Class в обеих частях продукции определяет класс местоположения нового метода (в том же классе, что и оригинальный метод).
Перемещение кода в новый метод. На следующем шаге необходимо переместить выделенный пользователем исходный код в новый метод. Данное преобразование достаточно просто реализовать, поскольку в принятом описании вершин и дуг для обозначения строчки кода используется последовательность вершин Bo.Ex^Ex. Таким образом, каждая строка кода представляется набором выражений, соединенных одной дугой с вершиной „тело метода" (Bo). Следовательно, для перемещения кода в графе исходного кода необходимо для каждой вершины (подходящей для преобразования) произвести преобразование (рис. 3).
Рис. 3
В левой части продукции есть отношение me^.Bo^■EX, обозначающее одно выражение в теле метода (одну строку кода). Имя вершины %old_method заполняется на этапе выполнения и принимает значение имени метода оригинального расположения кода. Вершина с именем *A обозначает необходимость выполнить данное преобразование для всех вершин такого типа из графа входных параметров. В правой части дуга перемещена из вершины старого метода в вершину нового.
Добавление параметров функции. Последним преобразованием необходимо создать формальные и фактические параметры нового метода и подставить его вызов в нужное место. Для этого выполним преобразование, показанное на рис. 4.
Рис. 4
Для сохранения работоспособности программы необходимо все переменные из перемещаемого кода проверить на локальную принадлежность к старому методу и вынести их в список параметров нового метода. В левой части фактически определяются локальные переменные (отношение me:Bo^Va). В правой — для найденных вершин создаются новые отношения: pa:Si^Pa (формальный параметр метода), me:Pa^Va (связь вершины формального параметра и вершины переменной), pa:Bo^Pa (фактический параметр метода).
В заключение нужно отметить, что представленный в этой статье пример рефакторинга можно отнести к сложно описываемым, но даже для его воплощения потребовалось всего три набора продукций. Данный подход в полной мере пригоден для описания любых структурных преобразований, он позволяет создавать группировки преобразований и новые (например, исправляющие стилистику кода) преобразования. Описанный подход является важным элементом системы контроля и улучшения качества программного обеспечения, способен обеспечить необходимую математическую основу для создания системы автоматизации преобразований, гарантировать требуемые уровни безопасности и надежности бортового программного обеспечения.
список литературы
1. Титов А. Все, что вы хотели спросить о сертификации бортового программного обеспечения, но боялись узнать // Компьютерра. 2007. № 45.
2. Бураков В. В. Управление качеством программных средств. СПб: СПбГУАП, 2009. 206 с.
3. ФаулерМ. Каталог паттернов рефакторинга 2010 [Электронный ресурс]: <refactoring.com>.
4. Рефакторинг с использованием шаблонов. М.: Вильямс, 2008. 510 с.
Станислав Александрович Власов
Вадим Витальевич Бураков
Сведения об авторах аспирант; Санкт-Петербургский государственный университет аэрокосмического приборостроения, кафедра компьютерной математики и программирования; E-mail: [email protected] канд. техн. наук, доцент; Санкт-Петербургский государственный университет аэрокосмического приборостроения, кафедра компьютерной математики и программирования; E-mail: [email protected]
Рекомендована ГУАП
Поступила в редакцию 04.04.11 г.