Package Merge semantics with nested packages and package imports - uml

I feel I understand the basic mechanics of package merge, mostly thanks to Zito's outstanding paper on the topic:
UML's package extension mechanism - taking a closer look at package merge
I'm trying to understand the semantics of merge when nested packages and package imports are involved, specifically with MOF.
Background
Referencing these specifications:
MOF 2.5.1 xmi file
UML 2.5.1 xmi file
Take as an example MOF's 'Reflection' package, where it is the receiving package and all of UML is the merged package: <mergedPackage href="http://www.omg.org/spec/UML/20131001/UML.xmi#_0"/>.
I know from the MOF specification document that the Element and Type classes will get merged with their UML counterparts in the resulting MOF Reflection package, but I can't find the specific semantic rules of how this result occurs.
Following the transformation rules, the resulting MOF Reflection package would look something like this (many elements removed for clarity):
Package name="Reflection"
Class name="Factory" (unchanged from MOF)
Class name="Type" (merged with UML CommonStructure "Type")
Class name="Object" (unchanged from MOF)
Class name="Element" (merged with UML CommonStructure "Element")
Package name="Activities" (nested package will be deep copied from UML since there is no matching nested package in receiving MOF Reflection)
Package name="Values" (nested package will be deep copied...)
Package name="CommonStructure" (nested package will be deep copied...)
Class name="Element" (ambiguity here - see below)
... etc.
Nested packages are recursively merged, thus since MOF-Reflection does not contain nested packages matching the UML package names, these are deep copied as-is from UML. I note that nested UML packages are omitted in the 'CMOF.ecore' file I look to as an example, but the package merge transformation rules clearly state that nested packages are merged and the CMOF constraints haven no rule that they are removed.
Ambiguity #1 - Package imports and name matching
I'm assuming that since the UML package imports all of its nested packages to its root package, that the merge will match the names of MOF-Relection-Element with UML-CommonStructure-Element (and the same for Type), even though the definitions are not in the same package scope during merge?
So merge is effectively performed on Namespace.member (which includes imported members), and not on Package.packagedElement?
Examples I've seen indicate that package and element imports are unioned in the resulting package, but including imported elements' names in the name matching isn't described.
Ambiguity #2 - Updating references to resulting element, across package boundaries
What is the transformation rule when the resulting nested package has an element with the same name as one in its outer containing package, as in the case of the resulting Reflection-CommonStructure-Element (and Type)?
The MOF specification document indicates that the goal of using package merge is to add Object as a supertype of all elements, and extend Element with additional capability.
This suggests that the "Element" in the resulting Reflection package must replace all references to a class named "Element", even in nested packages.
I can't find any rules describing this
Do we assume all nested package elements with the same name as the outer package represent the same and are replaced during merge? Or is the Reflection-CommonStructure-Element removed during merge because it is not distinguishable from the outer receiving and resulting element?
Much thanks
Conclusions
I'm awarding the answer to Axel for helping, and also raising an issue with OMG. Also thanks #querty_so for offering the bounty.
I've reviewed all published papers on package merge, all OMG issues (closed and open, in MOF and UML), and reviewed the UML 2.5.1 specification many times for any clue and simply cannot find any rule that makes the result of the MOF::Reflection merge of UML correct.
I must conclude that the MOF.xmi file is malformed.
I believe that MOF::Reflection::Element and MOF::Reflection::Type should have been defined in a nested package 'MOF::CommonStructure', and not at the root of the MOF::Reflection package. If I understand package merge semantics, this would then properly merge them with UML when the two 'CommonStructure' nested packages match by name, and the UML package's imports at its root package would carry over to MOF::Reflection. Thus, all resulting merged UML elements in the nested packages would be visible with unqualified names in the resulting MOF::Reflection, and Element and Type would be merged without ambiguity or name clashes.
It hard to accept that such a foundational MOF.xmi file has this oversight, but I suppose there are only a handful of people who have ever tried to execute this merge programmatically. In my opinion, defining abstract syntax without proving its 'implementation validity' in a concrete reference implementation will result in this type of situation.
I hope a future commenter will weigh in with more insights to confirm or correct these conclusions.

Update 10.10.22: I got an answer from the chair of the MOF-taskforce. He says, that members are matched and therefore, there is no bug. I think at least the specification leaves room for interpretation here.
In the light of this explanation, I have to revise my answer:
There is no ambiguity: MOF::Reflection::Element is different from MOF::Reflection:CommonStructure::Element. This poses no problem. They have distinct qualified names and it is perfectly clear what you get. The latter refers to the unmerged original version.
There is an example in the specification, that illustrates this (figure 12.2). If you merge Class A from Package P1 into Package P2, then P1::A still refers to the original version.
And in your second example, you have two versions of Comment, one that inherits from MOF::Reflection::CommonStructure::Element and one from MOF::Reflection::Element. The PackageImport doesn't cause a clash, since the clashing elements would simply not be imported:
If indistinguishable Elements would be imported into a Namespace as a
consequence of ElementImports or PackageImports, the Elements are not
added to the importing Namespace.
So again, there is no ambiguity.
Previous obsolete answer
(I didn't delete it, so that the discussion still makes sense)
I think you found a bug in the MOF-specification. I reported it to the omg: https://issues.omg.org/browse/INBOX-1518
The specification states clearly:
UML 2.5.1 page 245: Imported elements are not merged (unless there is
also a PackageMerge to the Package owning the imported element).
update: This refers to elementImport of the receiving Package. Therefore, it doesn't apply here. I was mistaken to cite it here.
The reason why earlier versions of MOF didn't have this problem is that the UML taskforce wanted to avoid the merge relationship in the definition of UML. In UML 2.4 all sub packages were merged into the UML package. In UML 2.5 all sub packages are only imported. It seems this change was overlooked by the MOF taskforce.
So, to make it completely clear: Elements are only merged if both the merged package and the receiving package own a mergeable element with the same name and metatype. If both packages own matching sub packages, this rule is applied recursively.
In order to solve this problem, I suggested to mirror the UML packages in the MOF definition. Until this has been done by the taskforce, you could edit your copy of the MOF.

Related

Should access to properties of other classes through association be made explicit or are they implicit?

I'm working on a project where I'm using an SDK that provides things I need via some classes. I've named these ProviderProvider and Provider, that grant access to OneThing that is an IThing.
An example is shown here
.
My question is: What is the correct (or best) way to show that the Model provides the list of OneThings to the View through those classes?
Do you show this explicitly as in my example, by drawing a dependency arrow from Model to OneThing? That doesn't seem right to me and quickly becomes visually cluttered.
Do you not explicitly define that relationship, but is it simply implicitly defined through the other relationships?
Do you define that relationship semi-explicitly through attributes, notes or some other way?
What relations and attributes should I add/remove specifically and why?
You already have the implicit relationship since you use this class as a type of data returned by Model so you do not need to add that relationship explicitly.
It may be useful though, especially for classes that are core in the system, to add a diagram with dependencies only. Then you don't care about relationships between other classes, you only show on one diagram all classes that depend on the core one (it may be even more than one diagram).
One hint - in Case tool (like EA) even if you don't intend to show the relationship on the diagram since it is indicated implicitly it is still good to create the explicit dependency and just remove the arrow. This will support the traceability through tools like traceability matrix or dependency tree.

How can I version software components in Sparx Enterprise Architect (EA)?

I am working at modelling a software system using Sparx Enterprise Architect 13. This system contains different versions of software components. We typically add services and/or APIs when we release a new version of a software component.
Currently, to reflect the fact that component ServiceV1 exposes an interface A and ServiceV2 exposes interfaces A (the same as ServiceV1) and B, I make ServiceV2 extend ServiceV1. But that is not straightforward:
the generalization link is not available in diagrams between components, so I have to use Advanced > Parent...
it lacks flexibility, because I cannot override interface A with a newer version of the interface
Is there a better way to do so? What is the standard way of maintaining several versions of the same component?
Thank you!
I don't think this is standardized by some standards body, but I would recommend to introduce two levels of abstraction: the unversioned component level and the versioned component level.
On the unversioned component level, you have just a single element in the project repository for each component (not for each component version).
On the versioned component level, you have a single element in the project repository for each version of each component.
Each versioned component, e.g. MyComponentV2 has a ≪trace≫ dependency to the unversioned one, e.g. MyComponent.
To prevent unnecessary design work, you may decide to draw relationships between different components only between versioned component elements, not between unversioned component elements, or only vice versa. But this depends on the needs of your organization.
When you create a new version of a component, you copy the most recent version of the component (MyComponentV2) with all its connections, including the ≪trace≫-dependency to the unversioned component (MyComponent) and give it the right name (MyComponentV3).
I have applied this in a large project.
Actually there is no standard for modeling such a scenario. At best you can have conventions - which may differ from domain to domain. However, here's how I would model it:
ServiceV2 has a <<trace>> relation to ServiceV1. UML 2.5.1 says on p. 682:
«Trace» | Abstraction | Specifies a trace relationship between model elements or sets of model elements that represent the same concept in different models. Traces are mainly used for tracking requirements and changes across models. As model changes can occur in both directions, the directionality of the dependency can often be ignored. The mapping specifies the relationship between the two, but it is rarely computable and is usually informal.
So that should mean in this context ServiceV2 is created using ServiceV1 (I formerly used <<derive>> here since it seemed logical. But actually the UML semantic is defined differently; see p. 680 of UML 2.5.1). You could well invent your own stereotype here and explain it in the domain context (e.g. <<version of>>).
You would probably create a copy of ServiceV1 or model it manually as new element (you don't do that on a mass scenario, do you?). Here I added provided interfaces that both realize the common interface A. The quick linker does not offer those relations. You need to either go the clumsy Ctrl-I way or you grab the realization from the toolbox.
The <<derive>> dependency is not offered directly (unless you have your own MDG and defined it in QL or toolbox). So you create a dependency and choose derive from the stereotype menu.
This is a broad field and versioning is not as simple as just adding a numbering schema. In any case if you create a new component it will be something different. So the <<derive>> is probably the best option here.
EA supports this. See documentation of "Time aware models" here:
https://sparxsystems.com/enterprise_architect_user_guide/13.0/model_domains/time_aware_models.html
Allows maintaining separate versions of each package

Meaning of Part and Port?

I have a .lib file containing internal C++ classes and a few C++ classes are interfaces to the functionality that software library provides.
How should I illustrate this with UML?
Using Enterprise Architect, I tried type 'Component' (pasted to the component diagram as simple link) and then dragged and dropped the internal classes of that library from the model tree to that component rectangle as element type Composite part, and the interface classes of that library as Port. Now the weird thing is what happened the model tree contains kind of object instances of that classes called Part1 and Port1 of UML type 'class', which is nonsense since a software library don't instantiate, it just provides its classes via .lib file, like a pool. I think UML element type 'component' is not the right thing here, is it?
The same happens if I use 'Package', also here parts and ports become things like object instances although classes in a library are not.
Following my comment to the O/P, I'd do something like the below. Please note that I'd probably not depict all of this on the same diagram, the class content of the package for example I might present on a separate diagram so that this is not so cluttered. But the logic is the same.
Update: Following commentary below I've added the this diagram which illustrates an alternative way of representing this. I think in some cases I've seen the delegation represented as a dependency rather than a reference association too. But hey ho. Internally, components are represented as interacting between each other via required/provided interfaces (though this is not shown as in the model below we only have one internal component illustrated).
It's not weird. You happened to drop a class as Part (in EA terms).
That's actually a Property. Just open its properties:
See UML 2.5 on p. 147:
9.9.17 Property [Class]
9.9.17.1 Description
A Property is a StructuralFeature. A Property related by ownedAttribute to a Classifier (other than an association) represents an attribute and might also represent an association end. ...
I'd probably just drop them as link to appear as class inside the enlarged component, YMMV
A class dropped as port will show as what the name said. So no confusion here. Anyway, I'd also drop it consistently as link to show just the contents. Further I'd probably stereotype the component itself with <<lib>> or the like. That's because you actually use a lib during compile time to extract the needed parts and it does not work as component by itself. A library though has an interface, namely to extract the compiled class modules it has inside.
Ah, and as #muszeo said: use ctrl-drag to show the above dialog.

Should dependencies in UML have multiplicities shown

I know a dependency relationship is depicted using a striped arrow e.g.:
Client -----<<create>>----> Server
I see that multiplicity is typically needed for other relationships (association, composition, aggregation) however, I'm unsure if it's needed or required for a dependency relationship. Should I put a '1' on each side of the above diagram?
No, there's no point in multiplicity on a dependency. Dependency merely states that a classifier (usually a class) in some way depends on another classifier. There is no way to say you depend on specific amount of those other classifiers since it doesn't touch the instances level.
In the UML specification (Section 7.5.1.) we have:
Types and multiplicity are used in the declaration of Elements that contain values, in order to constrain the kind and number of values that may be contained.
As association (including its stronger versions shared and composite aggregation) is semantically equivalent to a classifier's feature it support multiplicity. But this is not applicable to dependency.
Of the types of relationships in Class diagrams, multiplicity doesn’t apply to generalisations and realisations. You can apply multiplicity to dependencies but it often is not useful to do so, since dependencies are about how changes to one thing impact another.

UML dependency reliationship

I can't find answer for my question . Is there a limit to how much dependency reliationship can be between two classes ? Does UML class-diagrams in general can't have more than one reliationship of the same type between two classes but they can have 2 or more reliationship of different types (for example between two classes they both can have composition and generalization reliantionship ?
You can have many associations between two classes, as well as many dependencies. You should stereotype those dependencies to differentiate them.
In general the UML specification does not restrict how many relationships of a specific type can be between the same classes, but due to the logic and meaning of a relationship you can assume some limitations.
Generalization, realization have a meaning where if there exists this relationship between two classes, it directly implies some consequences. Repeating the same relationship for the second time will have no further impact so it doesn't make any sense. It's also hard to specialize further those relationships through stereotypes.
Simple dependency provide some information that again cannot be "repeated" by having next dependency. Yet stereotyped dependency can bring more value and information so you can have more than one of dependency but with different stereotypes. Once you have one dependency of specific stereotype repeating the same one doesn't provide additional value, yet another dependency of different stereotype is a fully understandable and reasonable case. In theory the same dependency could be applied twice in two different directions, but I would then investigate deeply - it is usually showing that there is something wrong with the project.
Associations (including aggregation - both shared and composite) between two classes can have many different meanings. They should be differentiated either by association name, association roles, stereotype or by mixing those methods. So you can have multiple associations of the same "type" between the same two classes and they will have significant meaning. So many associations between the same classes are absolutely OK and it is a typical situation.
Mixing different relationships are also absolutely OK, however sometimes one relationship implies other. In general any (or almost any) relationship imply non-stereotyped dependency (in the same direction) so using it explicitly doesn't give any additional information or effect.
There is no limit to how many dependencies can be between two classes. But you have to consider a couple of important moments. On the website https://vaughnvernon.co of a principal architect Vaughn Vernon I have found interesting comments about usage of UML dependencies:
While dependency may have a broad meaning, it is best not to overuse
the dependency relationship. In an analysis model class diagram such
as a domain model diagram, you may be tempted to convey that all the
classes just depend on each other. Interestingly, however, the
Rational Unified Process (RUP) specifies that the general class
relationship that should be used in the analysis model is association,
and not dependency. Therefore, even when you are modeling higher-level
concepts it is best not to use the dependency relationship loosely. It
is just too nebulous.
Further, unless you use the dependency relationship in a constrained
manner your model consumers (yourself or other developers) will simply
have too broad an interpretation of its meaning. Generally those
filling architect and designer roles in a project are there to give
guidance to less experienced developers. Thus the dependency
relationship should be used to convey a specific kind of guidance from
architects and designers to developers.
So what should a dependency relationship represent? In our UML example
above the dependency means that class A uses class B, but that class A
does not contain an instance of class B as part of its own state. It
also means that if class B’s interface changes it will likely impact
class A and require it to change. I suggest that you constrain your
use of dependency relationships to non-state related concerns. You
would use dependency to indicate that, for example, class A receives
an instance of class B as a parameter to at least one of its methods.
You would also use dependency to indicate that class A creates an
instance of class B local to one of its methods. You
would not, however, use dependency to indicate that class A declares
an instance variable of class B, as that would indicate a
state-related concern. Again, use association to do that.

Resources