2016-07-14 2 views
1

Я хотел бы использовать OCL для связывания двух диаграмм классов, которые представляют одну и ту же модель на двух уровнях абстракции.Можно ли использовать один и тот же класс в разных пакетах OCL?

Чтобы проиллюстрировать, рассмотрим абстрактную модель A, которая содержит класс Person, у которого есть ассоциация родителей. И более конкретная модель B, в которой есть классы Person, Male и Female, с мужчинами и женщинами, наследующими от Личности, и две ассоциации, один «отец» между Лицом и Маме и одна «мать» между Лицом и Женщиной.

Я хотел бы использовать OCL, чтобы связать две модели вместе. То есть, я хотел бы сказать, что «мать» и «отец» в конкретной модели представляют собой «родительскую» ассоциацию в абстрактной модели.

Я знаю, что можно поставить все ассоциации в одной модели, а затем, чтобы сказать что-то вроде

context Person inv: 
self.mother->forAll(m | m in self.parents) and 
self.father->forAll(f | f in self.parents) and 
self.parents->forAll(p | p in self.mother or p in self.mother) 

Но я специально хочу, чтобы отделить модели. Идея состоит в том, что конкретная модель не должна нести абстракции явно с ней.

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

Есть ли способ, который я могу сказать, что два имени класса в разных пакетах представляют один и тот же класс? это тот же набор объектов? например, достигнет ли это следующее выражение или просто будет всегда ложным?

Abstract::Person.allInstances() = Concrete::Person.allInstances() 

ответ

1

Я думал об использовании пакетов, чтобы поместить каждую модель в отдельном пространстве имен, но, насколько я понимаю, я в конечном итоге с двух различных классов Person, по одному в каждом пакете.

Право. Если вы не определите объединение пакета из пакета Abstract в пакет Concrete.

Пакета Merge определен в разделе 12.2.3 в UML:

Эта возможность предназначена для использования, когда элементы, определенные в различных пакетах имеют одинаковые имена и предназначена для представления ту же концепцию (...) Таким образом, любая ссылка на элемент модели , содержащийся в принимающем Пакете, подразумевает ссылку на результаты слияния, а не на приращение, содержащееся в этом пакете . [UML 2.5]

package Abstract 
context Person 
inv: not self->closure(parent)->contains(self) 

package Concrete -- merges from package Abstract 
context Person 
inv: parents->asSet() = Set {mother, father} 

Но если объединить пакет Abstract в пакет Concrete, то Concrete::Person принесет parents из Abstract::Person, и вы не хотите этого.

Я специально хочу отделить модели. Идея состоит в том, что конкретная модель не должна нести абстракции явно с ней.

Обратите внимание, что instace не ограничивается одним надтипа, то вы можете указать, что каждый Concrete::Person является Abstract::Person, и каждый Abstract::Person является Concrete::Person

package Abstract 
context Person inv: self->oclIsKindOf(Concrete::Person) 

package Concrete 
context Person 
inv: self->oclIsKindOf(Abstract::Person) 
inv: self->oclAsType(Abstract::Person).parents->asSet() = Set {mother, father} 

Актерский требуется, потому что Concrete::Person не знать об ассоциациях в Abstract::Person (они разные, даже если они применяются к тем же экземплярам).

Кроме того, первый инвариант на Concrete::Person на самом деле излишним, потому что oclAsType вернется invalid если само не соответствует Abstract::Person.

+0

Привет Хавьер, спасибо за подробный ответ. Я думаю, что ваш подход «слияния» подходит ближе всего к тому, что я хочу, но я не думаю, что подход 'oclIsKindOf' будет работать, потому что согласно стандарту OCL 2.4: _ Свойство 'oclIsKindOf' определяет, является ли' t' либо прямой тип, либо один из супертипов объекта. Другими словами, это предикат, поэтому его использование в инварианте будет просто сделать инвариантом ложным. –

+0

, если 'Concrete :: Person' не является * прямым типом или одним из супертипов * экземпляра' Abstract :: Person', то инвариант ложный ... но мы уже говорили, что ** каждый ** экземпляр of 'Abstract :: Person' также является« Concrete :: Person »(потому что это та же концепция), тогда инвариант всегда верен; и это необходимо для того, чтобы требовать согласования модели. – Javier

+0

Но как мы сказали, что каждый экземпляр «Abstract :: Person» также является «Concrete :: Person»? было сказано с выражением OCL? или мы просто сказали, что вне формальной структуры? –

0

(RSS позволяет предположить, что это новая тема!)

Проблема заключается в том, что вы абстрактные/конкретные варианты в каком-то смысле разных классов, но в другом смысле, одни и те же классы. Поэтому вы должны разделить своих потребителей в соответствии с тем, хотят ли они видеть абстрактные/конкретные как разные/одинаковые классы и определять, что «одинаково» означает для каждого потребителя.

Для людей вы можете использовать соглашения о орфографии, чтобы сделать разные классы «одинаковыми». Или аннотации или множество ассоциаций UML.

Если вам нужна определенная функциональная идентичность, позволяющая использовать «абстрактный»/«конкретный» класс, который может быть взаимозаменяемым в некоторых симуляторах, вам, возможно, нужны как «абстрактные», так и конкретные классы для наследования из общего интерфейса, для которого у вас есть разные «абстрактные»/«конкретные» реализации.

Если идентичность предназначена для документирования, вы можете рассмотреть язык преобразования модели, который преобразует один в другой. Многие M2M - это просто внешний язык для OCL, обеспечивающий поддержку импорта/экспорта модели и мутации. M2M может захватывать регулярные идиомы, которые связывают «абстрактные» и «конкретные», и могут поддаваться математическому доказательству и/или автоматическому генерации кода. Он, безусловно, должен удовлетворять требованиям, требующим удовлетворения.

Смежные вопросы