Меню
Главная
Авторизация/Регистрация
 
Главная arrow Информатика arrow Архитектура и проектирование программных систем

Формализация процесса рефакторинга на основе символьной записи структуры классов

В большом количестве опубликованных работ рассматриваются использование UML-диаграмм для решения задачи синтеза и декларативные подходы к решению задачи анализа объектно ориентированных программных систем. Однако решение задачи анализа на основе UML не формализовано, а сами диаграммы дают небольшие возможности выполнять формальные преобразования над классами с целью рефакторинга проекта. Исключением в определенной части являются инструментальные средства IBM Rational. Один из возможных подходов к автоматизации процессов рефакторинга предложен в работе [28].

Автор работы на основе ряда публикаций делает вывод, что класс -это триплет вида С ={Pv,Pt, Рь}, где Pv,Pt,Pb - множество частных, защищенных и публичных данных и методов класса. С другой стороны, основываясь на свойстве инкапсуляции, класс - это пара C = {F, М},

где F - множество полей, а М- множество методов класса. Таким образом,

С = {PvF u PvM, PtF u PtM, PbF u PbM, (7.1)

где PvF, PtF, PbF - множество частных, защищенных и публичных полей класса; PvM, PtM, PbM - множество частных, защищенных и публичных методов класса.

Очевидно, что PvF е F, PtF е F, PbF е F, PvM е М, PtM е М, PbM е М, PvF п PtF = 0, PvF n PbF = 0, PtF n PbF = 0, PvM n PtM = 0, PvM n PbM = 0, PtM n PbM = 0, PvF и PtF и PbF = F, PvM и PtM и PbM = F.

Для описания структуры класса в виде символической записи предлагается следующая нотация. Символ, обозначающий атрибут класса, записывается как N*ype, где N - имя поля, a type - тип поля. Метод класса предлагается записывать как Meth'^em (рагат), где Meth - идентификатор метода, рагат - перечень формальных параметров, a prim с [virtual, abstract, override]. Допустимо, что prim = 0 и (или) рагат = 0. Класс определяется как СпатеСргть где Cprint- abstraet|0.

Синтаксис символьной записи структуры класса определяется грамматикой, представленной в табл. 1.

Таблица 7.1. Грамматика символьной записи структуры класса

^>=+ {[>]; [,>; [,>]}

—>

< PrvF>^

^0

< PrtF>—>

< ME THODS>^

—> ~^

< ME THODS>—>,

< PrvM >-*

^

< PrtM >^

—> abstarct0

< PubM >—>

virtual abstract override 0

—>,

^>+ |0

Таким образом, в символьном виде описание нового класса пе?С1а88, порожденного от базового класса ЬазеСаЬэ, - это выражение вида пе!СІа$.ч = ЬазеСІазз + {[/V/7, РуМ], [РР7, РіМ, \_PbF, РЬМ).

Рассмотрим пример символьной записи структуры классов, показанной в виде иМЬ-диаграммы на рис. 7.1.

иМЬ-диаграмма представления классов геометрических

Рис. 7.1. иМЬ-диаграмма представления классов геометрических

фигур

[ [fx* ? frm' ]? a-lshow^ о .Mdetima O.getrjL, ().l

TPoint =

1 setXM (newXa ), 0- )] j

%

[fia ./rrmishow^o.o,

TLine = Tpoint + ?

getXV^ai 0- setx lxirtual (newXl* ). getYlS*, 0, sef Y^-iinual (newYl“* )]

(7.

гагс/e = Tpoint +1 hide^j'Q.getR*^ 0-

(newR"* )]

Очевидно, что символьная запись структуры классов компактнее соответствующей ей иМЬ-диаграммы. Определим на основании предложенной символьной записи операции над классами для решения задачи анализа структуры проекта и его последующего рефакторинга. Определим для двух произвольных классов С1 и С2 операцию пересечения, которую будем записывать как С1 п С2. Введем в рассмотрение функцию 1{хх, х2) = [*! (х, пх2), х21 ги2)]. Пусть операция С1 п С2 в соответствии со спецификацией (1) определяется как

baseC = <

  • ?
  • ([PvFcl П PvFC2,PvMcl П PvMC2, [PtFci П PtFC2, PtMcl П PtMC2], [PbFcl П PbFC2, PЬМС1 П PbMC2

Cl П C2 — baseC +*

(7.2)

[I(PvFcl,PvFc2),I(PvMcl,PvMc2)],) [I(PtFcl,PtFc2),I(PtMcvPtMc2)], [l(PbFcv PbFCI). I(PbMcv PbMc2)]J

Базовый класс baseC - это ближайший общий предок в дереве иерархии или единый базовый класс BaseObject (NSObject, java.lang.Object, System.Object, TObject и т.п.), если такого не существует. Если реализация методов с одинаковым объявлением PvM, PtM, РЬМ различна для операндов операции пересечения, то в результате пересечения они получают дополнительный префикс abstract. Проиллюстрируем операцию строгого пересечения на примере UML-диаграммы классов, представленных на рис. 7.2.

TLine

TEllipse

TCircle

-fX 1 : int

-fX1 : int

-fX1 : int

-fYl : int

-fY1 : int

-fY1 : int

-1X2 : Int

-fR1 : int

-fR : Int

-fY2 : int

-fR2 : int

+shiow{)

?show()

+show()

+hide<)

+hlde()

+hide()

+move{)

? move()

+move()

Рис. 7.2. иМЬ-диаграмма классов без общего предка

[paint,/n

TEllipse П TLin = BaseObject + <

[showvirtual

,adstractQ’ ]

hideVirtUal,adstractO'^noreO] I TEllipse П TCircle = TEllipse П TLine,

TLine П TCircle — TEllipse П TLine. (7-3)

Результатом пересечения классов, как правило, является новый класс или общий предок классов, заявленных в качестве операндов. Таким же образом определяем операцию вычитания классов С1С2:

С1С2 =

[PvFclPvFC2,PvMclPvMcl + V мієСіМ І abstract] [PtFclPtFC2,PtMCiPtMc2 + УМІЄСІ^^abstract 1 [PbFclPbFc2.PbMclPbMcl +

^ MieCl^ ^abstract]

>

(7.4)

Операция вычитания есть традиционное вычитание множеств полей и методов класса с учетом необходимости перегрузки абстрактных методов. Образование новых классов в результате выполнения операции пересечения является основой для процесса рефакторинга, описанного в [28]. При этом следует действовать по следующему формальному алгоритму вне зависимости от лингвистических сред и особенностей реализации.

Шаг 1. Выполнить преобразование в символьную запись всех объявлений классов программной системы.

Шаг 2. Для всех классов, имеющих общего предка в дереве иерархии выполняется операция строгого пересечения:

ТРагепЮЦеМ = п'С,. (7.5)

Шаг 3. Если результат операции пересечения не равен ТРагепЮЬ-]еії Ф Ва5еОЬ]есі, определяем новый класс предка.

Шаг 4. Выполняем рефакторинг путем вычитания из каждого класса С, класса ТРагеп іОІу есі.

Рассмотрим пример рефакторинга программных классов, представленных на рисунке 7.2.

ІТ^иге = Ва$еОЪ]есТ +

ТЬіпе = ТП&ге+ {[1X2™ ,/У2ш]ШзЬ<Мокггі<кО-Ьі(іеотгіЛ0]}

ТЕІ1ір8Є = ІРі&іге+ {[/К1ШІ./К2т'].[].[57ї0М’

ТСігсІе = ТТ^кге+ {ЦІЇ™ ]Ш^ом'твггиіе (). ЬШе0^е ()]} (7.6)

Таким образом, формальный подход к решению задачи рефакторинга программных систем на основе символьной записи структуры классов является основой для построения программного продукта, позволяющего выполнять автоматизированный рефакторинг архитектуры программных систем практически без участия программиста.

 
Если Вы заметили ошибку в тексте выделите слово и нажмите Shift + Enter
< Пред   СОДЕРЖАНИЕ   След >
 

Популярные страницы