Book a Demo

Author Topic: PrimitiveType can be generalized, but not be specialized - why?  (Read 33863 times)

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #15 on: August 18, 2020, 02:56:33 pm »
There it is  ;D

That indeed explains why you can do MyPrimitiveType --|> MyDataType but not the other way around.
I'm still not sure it makes much sense in the real world, but it seems to be syntactically valid UML.

Thanks Eve

Geert

Modesto Vega

  • EA Practitioner
  • ***
  • Posts: 1183
  • Karma: +30/-8
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #16 on: August 19, 2020, 07:17:57 pm »
It was a very good explanation from Uffe.
Just to add a couple of points to it, from chapter 10.2 DataTypes (in UML 2.5), emphasis added in red.
Quote
10.2.3 Semantics
10.2.3.1 DataTypes
A DataType is a kind of Classifier. DataType differs from Class in that instances of a DataType are identified only by their value. All instances of a DataType with the same value are considered to be equal instances. If a DataType has attributes (i.e., Properties owned by it and in its namespace) it is called a structured DataType. Instances of a structured DataType contain attribute values matching its attributes. Instances of a structured DataType are considered to be equal if and only if the structure is the same and the values of the corresponding attributes are equal.

10.2.3.2 Primitive Types
A PrimitiveType defines a predefined DataType, without any substructure. A PrimitiveType may have algebra and operations defined outside of UML. The run-time instances of a PrimitiveType are values that correspond to mathematical elements defined outside of UML (for example, the Integers).
As Uffe pointed out above,
  • Primitive types are mathematical numbers - e.g., all types of real numbers, including all rational numbers, and transcendental numbers are primitive types - and they "may have algebra and operations defined outside of UML"
  • DataTypes are actual implementations of primitive types - i.e., somebody has made a decision on how to implement the algebra and operations defined outside UML
For instance,
  • In C# float, double and decimal all implement/represent real numbers,
  • In C int implements/represents an integer (a type of real number)
  • In SQL Server bigint, int, smallint and tinyint all implement integers (which are a type of real numbers)
Needless to say, that converting between data types is a non-trivial problem.

This may be a bit awkward and counterintuitive but as long as Sparx lets me do it I am fine
----------------- --|> C# float
|                   | --|> C# double
|                   | --|> C# decimal
|real number| --|> C int
|                   | --|> SQL Server bigint
|                   | --|> SQL Server int
----------------- --|> SQL Server smallint
« Last Edit: August 19, 2020, 08:01:21 pm by Modesto Vega »

Uffe

  • EA Practitioner
  • ***
  • Posts: 1859
  • Karma: +133/-14
  • Flutes: 1; Clarinets: 1; Saxes: 5 and counting
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #17 on: August 19, 2020, 08:07:01 pm »
It was a very good explanation from Uffe.
Thank you kindly. :)

Quote
Needless to say, that converting between data types is a non-trivial problem.

This may be a bit awkward and counterintuitive but as long as Sparx lets me do it I am fine
----------------- --|> C# float
|                   | --|> C# double
|                   | --|> C# decimal
|real number| --|> C int
|                   | --|> SQL Server bigint
|                   | --|> SQL Server int
----------------- --|> SQL Server smallint

I'd be careful with that.

If we're talking on the one hand about the mathematical concept of real numbers, and about computer representations of numerical values on the other, then we are shifting domains.
That's fine, but you can't use Generalizations between domains. The correct relationship in that case would be Realization: a C# float realizes a real number.

/Uffe
My theories are always correct, just apply them to the right reality.

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +397/-301
  • I'm no guru at all
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #18 on: August 19, 2020, 09:00:48 pm »
In any case: the generalization looks the wrong way around. The "real number" does not inherit anything from its implementations in various domains.

q.

Paolo F Cantoni

  • EA Guru
  • *****
  • Posts: 8626
  • Karma: +259/-129
  • Inconsistently correct systems DON'T EXIST!
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #19 on: August 19, 2020, 09:36:39 pm »
In any case: the generalization looks the wrong way around. The "real number" does not inherit anything from its implementations in various domains.

q.
Wot dey sed!   (Qwerty's and Uffe's observations)

Paolo
Inconsistently correct systems DON'T EXIST!
... Therefore, aim for consistency; in the expectation of achieving correctness....
-Semantica-
Helsinki Principle Rules!

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #20 on: August 19, 2020, 10:13:01 pm »
As predicted, here I am.

9.9.4.7 - Operations (for Classifier)
Quote
maySpecializeType(c : Classifier) : Boolean
The query maySpecializeType() determines whether this classifier may have a generalization relationship to
classifiers of the specified type. By default a classifier may specialize classifiers of the same or a more general
type. It is intended to be redefined by classifiers that have different specialization constraints.
body: self.oclIsKindOf(c.oclType())

There's a matching constraint that uses this operation, but I hope you get the idea. Interestingly, I'm not aware of any redefinitions of this rule, except for those that extend the same idea to stereotypes. (eg. a SysML block has the same constraint to its specializations) It's actually common enough that the metamodel relationships allow you to create stereotyped relationship that follows it by linking to a metaclass with the name "source.metatype.general".

"source.metatype.general"
I kept thinking about this.
As it is written here, that would indeed mean that a PrimitiveType may specialize a DataType, but not the other way around.

But I feel like the constraint doesn't make any sense that way, and should be reversed.

Please follow me in this train of thought
- PrimitiveType and DataType are both concrete types
- any PrimitiveType is also a Datatype.
- PrimitiveTypes know about Datatypes, but DataTypes don't know about Primitivetypes
- Specialization from DataType to Datatype is obviously allowed
- From the standpoint of a Datatype, any PrimitiveType would be considered a Datatype
- The Lyskov Substitution principle also tells us that subtypes must be substitutable for their base types, so any place we are allowed to use a DataType we should also be allowed to use a Primitivetype
- So since a Primitive IS A Datatype, a Datatype specializing a PrimitiveType should be allowed

The other way around (as it is stated now) is not at all intuitive.

Does this make sense? Should be consider this a bug in the UML specification?
It feels to me like it would far more logical to reverse the constraint, or simply state that it is only allowed between elements of the same concrete metatype.

Geert

Modesto Vega

  • EA Practitioner
  • ***
  • Posts: 1183
  • Karma: +30/-8
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #21 on: August 19, 2020, 11:42:03 pm »
[SNIP]
That's fine, but you can't use Generalizations between domains. The correct relationship in that case would be Realization: a C# float realizes a real number.
I think this quote encapsulates the problem.

The definition of Primitive Type suggests a change of domain (bold emphasis below) but it is also ambiguous (italics emphasis below) because it refers to DataTypes and implies that a PrimitiveType is more abstract than a DataType (a PrimitiveType has no structure but a DataType has).
Quote
10.2.3.2 Primitive Types
A PrimitiveType defines a predefined DataType, without any substructure. A PrimitiveType may have algebra and operations defined outside of UML. The run-time instances of a PrimitiveType are values that correspond to mathematical elements defined outside of UML (for example, the Integers).


[SNIP]
The correct relationship in that case would be Realization: a C# float realizes a real number.
My brain hurts less with the concept of realization.

However, this statement from Chapter 10 makes my brain hurt:
Quote
A PrimitiveType defines a predefined DataType, without any substructure.
The first headache is the use of the word "defines", if a PrimitiveType defines a DataType, the generalization seems to be the wrong way around because PrimitiveTypes are structureless and therefore more abstract than DataTypes. As pointed out by Uffe and qwerty, there is nothing to inherit (other than relationships to other elements). From this angle, I agree with Geert.

The second headache is the use of the word "predefined", if DataTypes are predefined, the generalization could be the right may around because DataTypes come first and PrimitiveTypes are just used to classify DataTypes.

Just to make the whole thing more entertraining, Chapter 21 of the UML specification states
Quote
The PrimitiveTypes package is an independent package that defines a set of reusable PrimitiveTypes that are commonly used in the definition of metamodels. The UML metamodel uses the PrimitiveTypes package." It also refers to them as "domains" and enumerates 5 of them: Integer, Boolean, String, UnlimitedNatural and Real. Unfortunately none of the examples are about how to use them to "extend" data types.
This quote also implies the relationship is the other way around.


I also think we need to separate definition from usage, something Uffe alluded to. How you define a float and how you use a float are 2 different things? As Uffe pointed out Speed is not a float, it contains an attribute that is a float. But the decision to use a float attribute is arbitrary, an integer could have been used to express speed in metres per second.
« Last Edit: August 19, 2020, 11:44:12 pm by Modesto Vega »

Uffe

  • EA Practitioner
  • ***
  • Posts: 1859
  • Karma: +133/-14
  • Flutes: 1; Clarinets: 1; Saxes: 5 and counting
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #22 on: August 20, 2020, 07:21:31 am »
Hello again,


I think there's a bit of confusion in this thread between the definition of UML and the application of UML.

In the definition of UML, there is a subtype of Classifier called DataType, which in turn has subtypes PrimitiveType and Enumeration, each with their own characteristics. A characteristic of PrimitiveType is that it may not have an internal structure.

In the application of UML, ie a model in the UML language, there is no DataType or PrimitiveType -- but there may be «dataType»s and «primitive»s. Here, the fact that a «primitive» is not permitted to contain attributes means that it cannot be the source of a generalization (unless the target is also a «primitive»), since a generalization inherits the attributes of the target.

That's fine, but you can't use Generalizations between domains. The correct relationship in that case would be Realization: a C# float realizes a real number.
I think this quote encapsulates the problem.

The definition of Primitive Type suggests a change of domain (bold emphasis below) but it is also ambiguous (italics emphasis below) because it refers to DataTypes and implies that a PrimitiveType is more abstract than a DataType (a PrimitiveType has no structure but a DataType has).
Quote
10.2.3.2 Primitive Types
A PrimitiveType defines a predefined DataType, without any substructure. A PrimitiveType may have algebra and operations defined outside of UML. The run-time instances of a PrimitiveType are values that correspond to mathematical elements defined outside of UML (for example, the Integers).

Not quite. Neither DataType nor PrimitiveType are abstract; they are both concrete. What this means is that in a UML model, you are allowed to create «dataType»s and «primitive»s, but not «classifier»s because in the UML definition, Classifier is abstract.

DataType is, however, more general than PrimitiveType. In a UML model, all «primitive»s are also «dataType»s; wherever a «dataType» is required, you may use a «primitive». But the opposite does not hold true: if a «primitive» is required somewhere you may not substitute a non-primitive «dataType». That is what the metamodel relationship means, and that is all the metamodel relationship means.

Quote
The correct relationship in that case would be Realization: a C# float realizes a real number.
My brain hurts less with the concept of realization.

However, this statement from Chapter 10 makes my brain hurt:
Quote
A PrimitiveType defines a predefined DataType, without any substructure.
The first headache is the use of the word "defines", if a PrimitiveType defines a DataType, the generalization seems to be the wrong way around because PrimitiveTypes are structureless and therefore more abstract than DataTypes. As pointed out by Uffe and qwerty, there is nothing to inherit (other than relationships to other elements). From this angle, I agree with Geert.
(Emphasis added.)
Again, I think it's the definition vs application that's tripping you up.

A «primitive» is not more general because it has no attributes (we dealt with abstractness vs generalness above). The number of attributes is not a measure of generalness; the only measure of generalness is a classifier's position in a chain of generalizations. The nearer to the ultimate source, the more general. In the UML definition, DataType is more general than PrimitiveType, but Classifier is more general still.

The language in the spec simply emphasises the fact that «primitive»s are also «dataType»s. In the corresponding text for Enumerations, the same notion is expressed using different language: "Enumeration is a kind of DataType." Is a kind of -- defines a. Same thing.

Quote
The second headache is the use of the word "predefined", if DataTypes are predefined, the generalization could be the right may around because DataTypes come first and PrimitiveTypes are just used to classify DataTypes.

I hear you, but that can't be the intended reading of "predefined." If they were truly predefined, you should not be able to create new ones -- in other words, no «primitive»s in an applied UML model, just Boolean, Integer, Real, String and UnlimitedNatural.
I think what's intended here is rather "externally defined." Meaning that there is an external (external to the model) definition which can be as complex as you wish, but the complexity is not captured in the UML model -- a «primitive» ComplexNumber could be an example of this.

Quote
Just to make the whole thing more entertraining, Chapter 21 of the UML specification states
Quote
The PrimitiveTypes package is an independent package that defines a set of reusable PrimitiveTypes that are commonly used in the definition of metamodels. The UML metamodel uses the PrimitiveTypes package." It also refers to them as "domains" and enumerates 5 of them: Integer, Boolean, String, UnlimitedNatural and Real. Unfortunately none of the examples are about how to use them to "extend" data types.
This quote also implies the relationship is the other way around.
Again, I don't see this.

Chapter 21 defines five «primitive»s and states, quite unequivocally, that they cannot be drawn in a diagram -- there "is no notation". And this is in fact how they are implemented in EA. You can use them as attribute types, but they aren't elements that you can place in diagrams. And since they aren't elements you can't specialize them.

To sum up, it's important to keep track of what domain you're in. Are you in the MOF domain, defining UML, with DataType and PrimitiveType and Enumeration?
Or are you in the UML domain, with «dataType»s, «primitive»s and «enumeration»s?
And if you are in the UML domain, is your model a conceptual one or an implementation one?



My brain hurts.
My theories are always correct, just apply them to the right reality.

Modesto Vega

  • EA Practitioner
  • ***
  • Posts: 1183
  • Karma: +30/-8
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #23 on: August 21, 2020, 12:09:33 am »
Thanks Uffe, I think that you and I are saying more of less the same things but, perhaps, you are expressing it better.

There is also Sparx usability problem. In 15.1, I can create a class diagram with any number of classes, any number of primitive types, any number of data types and any number of valid relationships among them. I have no problems with Sparx doing this in a MOF context (including when I am defining an MDG). However, the fact that Sparx allows me to do this in a "using UML context", your UML domain, is a bit confusing.

Furthermore, 2 very confusing aspects are:
1) I can select any of the UML primitive types as attribute data types irrespective of whether my model contains a primitive type in the model or not.
2) If I create any number of data types and primitive types in a model, Sparx does not allow me to assign any of them to an attribute (presumably because they are not part of language).

[SNIP]
Chapter 21 defines five «primitive»s and states, quite unequivocally, that they cannot be drawn in a diagram -- there "is no notation". And this is in fact how they are implemented in EA. You can use them as attribute types, but they aren't elements that you can place in diagrams. And since they aren't elements you can't specialize them.
I hear you but Chapter 21 starts with something that looks suspiciously like a diagram with 5 boxes with a <<primitive>> stereotype. A diagram that is very easy to put together with Sparx 15.1.

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #24 on: August 21, 2020, 12:36:26 am »
2) If I create any number of data types and primitive types in a model, Sparx does not allow me to assign any of them to an attribute (presumably because they are not part of language).

I don't get it. Why can't you set the type of your attributes to your datatypes and primitives?
I do that all the time (via the "select type" option; the last option in the dropdown). In fact in the models we use, this is the only valid way to set an attribute type.

Geert

Modesto Vega

  • EA Practitioner
  • ***
  • Posts: 1183
  • Karma: +30/-8
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #25 on: August 21, 2020, 01:17:23 am »
2) If I create any number of data types and primitive types in a model, Sparx does not allow me to assign any of them to an attribute (presumably because they are not part of language).

I don't get it. Why can't you set the type of your attributes to your datatypes and primitives?
I do that all the time (via the "select type" option; the last option in the dropdown). In fact in the models we use, this is the only valid way to set an attribute type.

Geert
"Select type" is very Sparxian, it is not "select data type", it does not allow me to just select a data type or a primitive. In fact, it does what it says in the tin, it allows me to select a type (not a data type); in other words, it allows the selection of pretty much any element within a project as a data type - e.g., a requirement, a component, a use case, and so on. This is an example of Sparx using terms inconsistently: a type and data type are not the same thing.

The way I think Sparx should work is that any Data Type or non-built-in Primitive should appear and be selectable through the list without having to use "select type".

Eve

  • EA Administrator
  • EA Guru
  • *****
  • Posts: 8110
  • Karma: +119/-20
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #26 on: August 21, 2020, 08:28:57 am »
The way I think Sparx should work is that any Data Type or non-built-in Primitive should appear and be selectable through the list without having to use "select type".
The problem is that that list becomes far too large in any non-trivial example. It just doesn't work.

qwerty

  • EA Guru
  • *****
  • Posts: 13584
  • Karma: +397/-301
  • I'm no guru at all
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #27 on: August 21, 2020, 05:06:36 pm »
The way I think Sparx should work is that any Data Type or non-built-in Primitive should appear and be selectable through the list without having to use "select type".
The problem is that that list becomes far too large in any non-trivial example. It just doesn't work.
Well, looking at the unsorted list of stereotypes I see each time in EA I wonder what kind of argument that is.

q.

Modesto Vega

  • EA Practitioner
  • ***
  • Posts: 1183
  • Karma: +30/-8
    • View Profile
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #28 on: August 21, 2020, 06:26:22 pm »
The way I think Sparx should work is that any Data Type or non-built-in Primitive should appear and be selectable through the list without having to use "select type".
The problem is that that list becomes far too large in any non-trivial example. It just doesn't work.
This should be very easy to improve without using the list. We just need and extra item in the context menu called "Select Data Type" that restricts the "Select Type" search to just the following stereotypes <<data type>> and <<primitive>>.

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: PrimitiveType can be generalized, but not be specialized - why?
« Reply #29 on: August 21, 2020, 07:03:20 pm »
The way I think Sparx should work is that any Data Type or non-built-in Primitive should appear and be selectable through the list without having to use "select type".
The problem is that that list becomes far too large in any non-trivial example. It just doesn't work.
This should be very easy to improve without using the list. We just need and extra item in the context menu called "Select Data Type" that restricts the "Select Type" search to just the following stereotypes <<data type>> and <<primitive>>.
Don't forget enumerations.

That would help a little, but not much. In a repository I usually have many different data models that at different abstraction levels, that each use should only use their own set of datatypes as types of the attributes. It would be useful for me if we could limit the types to select to only those that are defined in that model, and nothing else.

Geert

PS. both «dataType» and «primitive» are keywords rather then stereotypes.