How to represent 2 classes with references to each other in UML? - uml

I am trying to represent my program in a UML diagram. I have 2 classes as below:
Mesh.h
class Mesh
{
public:
Mesh();
~Mesh();
VertexArrayObject* vao;
};
VertexArrayObject.h
class VertexArrayObject
{
public:
VertexArrayObject(Mesh* mesh);
~VertexArrayObject();
Mesh* mesh;
};
I'd imagine it'd be drawn like this:
However that doesn't look right at all. How is it best to represent a relationship where both classes have references to each other using UML?

No. That's plain wrong. Composite aggregation can only be on one side. (Imagine the car/wheel example: each aggregating the other is nonsense.) Remove the diamonds and you're done.
You can go further and put dots instead of the diamonds. That will mean that both sides have attributes referring the class at the other side. See this answer.

This depends a lot on what the logical construct is you are wanting to represent. You could specify the relationship between Mesh and Vertex in many ways and get the message across; what I understand from the model you have posted is that you think composition may be an important aspect of the relationship, e.g. Vertex is a composite part of Mesh (or vice versa).
In UML you can’t really have a bidirectional composition since this leads to a logical paradox — I.e. you cant simultaneously have two classes that are at the same time both composite parts of each other. If composition is important then you will need to choose which is composed of which.
Given my (poor) understanding of 3D (I guess that’s what your program is about), I would assume that a Mesh includes a collection of Verticies, so the composition would run from the Vertex type to the Mesh type with the solid diamond at the Mesh end. You might also want to add multiplicities (so that it is obvious that multiple Vertex may exist within the Mesh) and also consider whether the relationship is composite or a shared aggregate (can a Vertex exist outside a Mesh? If so a shared aggregate (white diamond) is needed).
You probably don’t need to represent the relationship from Mesh to Vertex, as this is an implementation detail that may be safely abstracted away in UML. The fact that you’re using a pointer to an array is probably not relevant to the logic that Mesh is composed of many Vertex.
That said, if you do want to specify what you have in code precisely then this can be done in UML. I would recommend abstracting out the Array of Vertex from Vertex — there are three logical types in your code — Mesh, Vertex and VertexArray. You might illustrate Mesh having a basic association with VertexArray (with an arrow to identify direction of reference), and this in turn being composed of Vertex (black diamond at VertexArray end).
Of course, I am assuming that VertexArray represents an array of Vertex objects, not a single Vertex!

Related

What is the difference between st_isvalid and st_issimple?

In Postgis there are two very similar functions. One is st_isValid, the other one is st_isSimple. I'd like to understand the difference between both for Polygons. For the st_isValid we have:
Some of the rules of polygon validity feel obvious, and others feel arbitrary (and in fact, are arbitrary).
Polygon rings must close.
Rings that define holes should be inside rings that define exterior boundaries.
Rings may not self-intersect (they may neither touch nor cross one another).
Rings may not touch other rings, except at a point.
For the st_isSimple we've got:
Returns true if this Geometry has no anomalous geometric points, such as self intersection or self tangency. For more information on the OGC's definition of geometry simplicity and validity, refer to "Ensuring OpenGIS compliancy of geometries"
Does it mean that any valid polygon is automatically simple?
Both functions check for similar OGC definition compliancy of geometries, but are defined for different geometries (by dimension);
By OGC definition
a [Multi]LineString can (should) be simple
a [Multi]Polygon can (should) be valid
This implies that
a simple [Multi]LineString is always considered valid
a valid [Multi]Polygon is always considered simple (as in, it must have at least one simple closed LineString ring)
thus the answer is yes.
Strictly speaking, using the inherent checks of the OGC defined functionality on the 'wrong' geometry type is useless.
PostGIS, however, liberally extends the functionality of ST_IsValid to use the correct checks for all geometry types.

How to modelize smart contracts in UML?

I am looking for a way to modelize ethereum smart contracts interaction using a modeling language like UML.
I have the following serivce Contract:
contract ServiceContract {
constructor (address _storeC, address _quizC, address _signC) {
StorageContract storeC = StoreContract(_storeC);
QuizContract quizC = QuizContract(_quizC);
SignatureContract signC = SignatureContract(_signC);
}
function storeData (bytes32 data) public {
storeC.save(data);
}
function getAnswer( bytes32 question) public constant returns (bytes32) {
return quizC.get(question);
}
function sign (bytes32 data) public returns (bytes32) {
return signC.sign(data);
}
}
I modelized it with this class diagram, is it correct?
[Edited for extra clarification]
Modelling a system is describing it in a formal way using a modelling language, and in some cases following some common guidelines. In this case you suggest the use of UML (See UML Specification).
UML diagrams can be divided into three categories:
Structural: The common structure, the values, the classifiers and the packages are in this category
Behavioral: The common behavior, the actions, state machines, the activities and the interactions are in this category.
Suplemental: The use cases, the deployments and the information flows are in this category.
As a modeler you decide which diagrams do you you need for what target you want to apply.
In your question you say that you are looking for a way to modelize an interaction. That is within the behavioral category. However you provide a sample code and a proposed class diagram, which is within the structural category.
That being said, is it your proposed diagram correct? I would say that it is inaccurate and incomplete (but not necessarily incorrect). Let me explain this a bit further.
In your proposed diagram you have four classes: ServiceContract, StorageContract, QuizContract and SignatureContract. You have drawn a relationship between the classes that is known as a dependency. And this dependency is of a specific type: usage (represented by the «use» keyword). What does this mean in UML?
A dependency in UML is defined as a relation where "the semantics of the clients are not complete without the suppliers" (Section 7.7.3.1 of the UML specification). Moreover, a usage dependency is defined as a relation where "one NamedElement requires another NamedElement (or set of NamedElements) for its full implementation or operation" (Section 7.7.3.2).
Hence, if we apply those defintions to your proposed diagram, you may read the relation between the ServiceContract and the StorageContract as "ServiceContract uses StorageContract". But nothing else. With this diagram you don't know how ServiceContract uses StorageContract, if it uses more than one instance of StorageContract, and so on.
Since you know how those classes are related, you should use a more accurate and complete diagram.
The first step is to use an association instead of a dependency. In UML an association is defined as "a semantic relationship that can occur between typed instances". And you know the semantic relationship between the classes that you are modelling in your class diagram. Therefore it makes more sense to use an association.
An association is represented with a solid line (indeed the UML specification says that it may be drawn as a diamond, but for binary associations it says that normally it is drawn just with a solid line). So let's start changing your diagram to the new one. In the next figure you can see the four classes with the association relationship (still incomplete):
Now that we have the association, we need to define it further. Has the association a name? Can the association be read in both ways? Do we know the multiplicity values for each end of the association? Do the ends of the associations have contraints?
In this example we don't need a name for the association, it seems that it can be read in both ways, and also that the multiplicity values are exactly 1 for all the ends. Then we do not to add anything to the diagram related to these questions. But what about the constraints?
Let's take a look at the source code. When you put this:
contract ServiceContract {
constructor (address _storeC, address _quizC, address _signC) {
StorageContract storeC = StoreContract(_storeC);
QuizContract quizC = QuizContract(_quizC);
SignatureContract signC = SignatureContract(_signC);
}
}
you can express it as "the ServiceContract has (owns) a property named storeC that is of a type of StoreContract", and so on. An ownership in an association is represented by a small filled circle (called a dot), at the point where the line meets the Classifer that is owned. Also you can add the name of the property that holds the ownership (Section 11.5.4). At this point the diagram is like this:
(See the answer from Thomas Kilian)
Since we cannot infer the visibility of the properties from the source, we can just let it as undefined (otherwise we can use a + sign before the name of the property for a public property, a - sign for a private property, a # for a protected property, and a ~ for a package).
Also we can show the properties within the Classifier for ServiceContract instead of at the end of the owned Classifier in the association. This will look like this:
Both styles are allowed by the UML specification (Section 9.5.3), and it also does not enforce any convention. However it mentions the convention for general modelling scenarios "that a Property whose type is a kind of Class is an Association end, while a property whose type is a kind of DataType is not".
This diagram is correct in the sense that it complies with the UML specification, and that it describes a system in which you have:
A Classifier named ServiceContract that owns three properties:
A Property named storeC whose type is a Classifier named StorageContract.
A Property named quizC whose type is a Classifier named QuizContract.
A Property named signC whose type is a Classifier named SignatureContract.
And remember, it is your choice, as a modeler, if this is enough for your target or not.
From the source I can say that the previous diagram is still incomplete and inaccurate. Why?
Because the source includes three Operations (the functions) that are not represented in the diagram. This can be improved in terms of completeness.
Because you cannot say from the diagram if the Classifiers that are owned by the ServiceContract are owned to group together a set of instances of the owned Classifiers or not. And given the case, if the owned Classifiers share the same scope or not. This can be improved in terms of accuracy.
First we are going to add the operations (the functions) to the diagram:
[NOTE: You may also add the _constructor_ to the operations.]
I guess that the functions are public, so I have included the + modifier at the beginning of each operation name.
Now for the accuracy, it seems to me that the ServiceContract groups together the StorageContract, the QuizContract and the SignatureContract in order to provide a common Classifier to access to certain operations (functions). If that is the case, then we are talking about aggregation. In UML aggregation is defined as an association where "one instance is used to group together a set of instances" (Section 9.5.3).
An aggregation can be of two types: shared (or just commonly known as aggregation from previous versions of the specification), and composite (or just commonly known as composition from previous versions of the specification).
The UML specification provides a more or less specific semantics for what it means for an aggregation to be of the type composite: "the composite object has responsibility for the existence and storage of the composed objects".
Let's say that in your case the existence and storage of the StorageContract, the QuizContract and the SignatureContract is responsability of the ServiceContract. Then in that case you have a composite aggregation, that is represented by a black diamond:
And it is read as "ServiceContract is composed by an owned property of classifier type StorageContract called storeC", and so on.
Keep in mind that using a composite type of aggregation you are saying that the ServiceContract object is responsible for the existence and storage. That means that whenever an instance of the ServiceContract is removed/destroyed, the associated StorageContract, QuizContract and SignatureContract must be destroyed also.
If that is not the case, and given that still the assocation matches the aggregation definition, then the only other option available is that the aggregation must be shared. The UML specification explictly does not provide a precise semantics of what a shared aggregation is, leaving the application area and the modeler with the responsability of giving those semantics.
So, if the StorageContract, the QuizContract, and the SignatureContract exist independently of the ServiceContract, and if you agree that the ServiceContract aggregates those objects according to definition given in the UML specification, you must use a shared aggregation.
A shared aggregation is represented by a hollow diamond at the end of the association of the Classifier that aggregates other Classifiers. And this it's how it looks:
And this diagram can be read as:
There are four Classifiers: ServiceContract, StorageContract, QuizContract and SignatureContract.
ServiceContract aggregates three owned properties:
storeC, of type StorageContract.
quizC, of type QuizContract.
signC, of type SignatureContract.
ServiceContract has one constructor that requires three arguments:
_storeC of type address.
_quizC of type address.
_signC of type address.
ServiceContract has three public functions:
storeData, that requires one argument of type bytes32 called data and returns nothing.
getAnswer, that requires one argument of type bytes32 called question and returns a bytes32 data type.
sign, that requires one argument of type bytes32 called data and returns a bytes32 data type.
Keep in mind that maybe for your desired target this final diagram is too detailed. It is your responsability as modeler to decide wether to include some details or not into the diagram.
You simply have associations to these three classes:
(I just drew a single relation)
The role name to the right tells in conjunction with the dot that it's a owned property of the class to the left. Not sure about the visibility (if that's private per default replace the + with a -).
While it may be goodness to spend some time to learn what exact arrow should used for particular Solidity relationship in UML (inheritance, composition etc), general trend is to let standard tool to care about this.
There is sol2uml UML generator https://github.com/naddison36/sol2uml
that is already used on https://etherscan.io
e.g. for USDT
https://etherscan.io/viewsvg?t=1&a=0xdAC17F958D2ee523a2206206994597C13D831ec7
(See image below)
So don't spend time manually drawing lines, use wiser tools to do it quicker for you.

Association definition in UML specification

An association defines a semantic relationship between classifiers. The instances of an association are a set of tuples relating instances of the classifiers. Eachtuple value may appear at most once. The Association represents a set of connections among instances of the Classifiers. An instance of an Association is a Link, which is atuple of Instances drawn from the corresponding Classifiers
I wonder if there is someone helps me understand every word of the association definition especially the highlighted ones?because I read about it from different resources but all of them say the same words but I would like a more elaborated definition
semantic relationship
This means there's a structural relationship between the things being associated that arises from the problem space. For example: the association Person owns Dog. In a dog licensing application, this relationship is the central concept; the application exists to manage the links between people and dogs. It's a 'semantic' relationship because it has meaning which originates from the problem space.
set of tuples relating instances of the classifiers
A tuple is 'an ordered set of elements' (wikipedia). An example of the Dog-Ownership association could be ("Fido", "Fred") where "Fido" represents a Dog and "Fred" a Person. An association can be represented as a set of tuples in that there is one tuple for each combination of Dog & Person for which the relation holds; e.g.
[("Fido", "Fred"), ("Angel", "Chuck Norris"), ("Boatswain", "Lord Byron")]
Note there are no tuples for pairs where the relationship doesn't hold; e.g. ("Fido", "Lord Byron").
each tuple value may appear at most once
It's not possible for the set to contain duplicates as this would just be saying the same thing twice. So there's no point adding ("Fido", "Fred") again to the list above; we already know Fred owns Fido.
The Association represents a set of connections among instances of the Classifiers
This is just another way to think about the relationship. For each tuple in the set, you can think of a link - or connection - between the related objects.
An instance of an Association is a Link, which is a tuple of Instances
See above. Each tuple represents one linked pair of objects. Links are to Associations as Objects are to Classes. Classes have many objects; Associations have many Links.
Fundamentally associations exist to show where things are systematically linked to other things. Tuples and sets are a way to think about and/or represent those linked things. (In fact I'd quibble somewhat with the definition in your OP: the links in an association can be represented as as a set of tuples: but that's not what they are, it's how they're modelled. The same information could equally be modelled by a Graph, where each object was represented by a vertex (node) and each association an edge.
hth.
EDIT:
Responding to your questions. Looks like you understand it pretty well; some observations.
First, here's how I would model it:
Now to each of your points:
Name: is the name of Association relationship(optional,you can give it a name or not)
I prefer verb phrase based naming as it brings out the meaning of the relationship. My model can be read directly as:
Each Person owns many Dogs (where 'many' means 0 or more)
Each Dog is owned by exactly one Person
Doing so removes the need to name the association explicitly, although you can still do so if you want.
visibility(I am not care about it,at least for now, I didn't realize its importance until now).
I would agree. Personally, I never annotate models with visibility.
Name:(here is the name of MemberEnd ),so,I left its default name in the screenshot
See comment about association naming above. I prefer verb-based naming to role-based: 'owns' is much more explicit in describing the purpose of a relationship than naming the association end 'dog' or 'dogs'.
the owner of memberEnd [...]
Personally: I don't use this. There's a whole other discussion about this that tbh I don't believe has a material impact in most cases.
Navigable [...]
Again I don't use this personally. In reality navigability should be derived from the underlying behaviour. Does it require navigating one way/both? Then set navigability accordingly. However some people like to specify it explicitly, on basis it makes the implementation clearer (If only navigable one way it can be implemented with reference(s) in one class only; if bi-directional it needs references in both directions - with attendant logic to keep things consistent).
Multiplicity
I agree with your selection.
Hope that helps.

Using variables in UML multiplicities

I was running a tutorial today, and a we were designing a Class diagram to model a road system. One of the constraints of the system is that any one segment of road has a maximum capacity; once reached, no new vehicles can enter the segment.
When drawing the class diagram, can I use capacity as one of the multiplicities? This way, instead of having 0..* vehicles on a road segment, I can have 0..capacity vehicles.
I had a look at ISO 1905-1 for inspiration, and I thought that what I want is similar to what they've called a 'multiplicity element'. In the standard, it states:
If the Multiplicity is associated with an element whose notation is a text string (such as an attribute, etc.), the multiplicity string will be placed within square brackets ([]) as part of that text string. Figure 9.33 shows two multiplicity strings as part of attribute specifications within a class symbol. -- section 9.12
However, in the examples it gives, they don't seem to employ this feature in the way I expected - they annotate association links rather than replace the multiplicities.
I would rather get a definitive answer for the students in question, rather than make a guess based on the standard, so I ask here: has anyone else faced this issue? How did you overcome it?
According to the UML specification you can use a ValueSpecification for lower and upper bounds of a multiplicity element. And a ValueSpecification can be an expression. So in theory it must be possible although the correct expression will be more complex. Indeed it mixes design and instance level.
In such a case it is more usual to use a constraint like this:
UML multiplicity constraint http://app.genmymodel.com/engine/xaelis/roads.jpg

In terms of OO design, can two-d and the three-d point classes be derived from single base class?

I`m currently working out the design for simple graphic editor, who support trivial operations for two-dimensional and three-d shapes.
The point is, I want to render prototype of these shapes, as MsPaint does. And at the moment it is rendering I need to store somewhere pixels from the canvas which get covered by prototype, just in case when prototype changes to restore their state on the canvas. So, I want all my shapes to support this kind of buffering (Graphic Operation is the base class for all rendering operations):
public abstract class Shape: GraphicOperation {
protected List<SomePoint> backup;
public Shape(Color c): base(c) { }
public Color FigureColor {
get { return color; }
protected set { color = value; }
}
public abstract void renderPrototype(Bitmap canvasToDrawOn);
}
The main idea is that in terms of OO design it would be great to provide the support of the buffer on base class (Shape) level, I mean for TwoDShape and ThreeDShape classes this list must be initialized in different way - for TwoDShape with TwoDPoint instances, and for ThreeDShape with ThreeDPoint instances.
But to do this, SomePoint must be base class for both two-dimensional point and three-dimensional point classes. Is it acceptable in terms of OO to derive both these classes from single base class?
May be there are too many words, but I just wanted the problem to be clear for everyone.
Edit: btw, is this the good idea to derive point classes from their king of shapes? I personally see no other options, but may be it would be better if I derive it directly from shape? Now it is:
public abstract class TwoDShape : Shape {
protected List<SomePoint> backup;
public TwoDShape(Color c) : base(c) { }
}
public class TwoDPoint: TwoDShape {
//...
}
and the same is for ThreeDPoint.
I don't see any reason not to. But if the only difference between Shapes is in the type of Points they contain, why not make the Shape class itself a template, or a "generic" in Java parlance?
What do 2d and 3d points have in common, exactly? If it is just "when drawing them onto a surface, they replace pixels which should be backed up", that sounds more like composition than inheritance to me. Both 2d and 3d shapes have a buffer of pixels they're displacing.
Anyway, can you always use both 2d and 3d shapes when the base class is expected?
If so, give them a common base class. Otherwise don't.
Base your class design on how the objects are used. If they are used in a context where they have a common base, implement it as a common base class. If it is just a matter of "I can't be bothered adding a data member to both", inheritance is probably not the right tool.
I can't think of any way to do this that doesn't violate the Liskov substitution principle in some subtle (or not-so-subtle) way. This is a classic example of why not to go crazy with inheritance, just because two classes share some fields, e.g., here or here.
In the end, even if you make it work, it'll probably have so many gotchas and restrictions on the methods you do write, I can't imagine it'll be a net win.
There's an entirely general rule of OOD that states: Favor composition over inheritance.
What this means in practice is that you shouldn't use inheritance for code reuse. It is still legal and valid to use inheritance if the motiviation for doing so is to take advantage of polymorphism.
In your case, if you can manage to write the abstract class/interface SomePoint in such a way that you can deal only with it on that level, and never need to downcast, you should definitely go for it.
If, on the other hand, you find that you need to downcast instances to, say, TwoDPoint or ThreeDPoint, then you gain nothing from inheritance, and you would be breaking the Liskov Substitution Principle. If this is the case, you should consider a design where you can implement reuse without resorting to inheritance - perhaps using a Service or a Strategy.
In games the 2d point and 3d pointtypically don't inherit from eachother, but to be honest I can't think of any fundamental reason for this. So yeah it should be fine, as for naming they are typically vector2 and vector3 so they can hold dimensions, points and colors, all in the same object.
Couldn't you make ThreeDimensionalPoint derive itself from TwoDimensionalPoint?
public class ThreeDimensionalPoint : TwoDimensionalPoint
{
}
I could see a lot of reusable code (methods/properties) in 2D that will be the same in 3D... And you might want to look at a 3D from a 2d standpoint and then all you would need to do is cast it. Just my thougts...
A simpler solution, and one that will avoid some subtle design issues is to just treat all points as 3D and simply ignore the Z coordinate if you're working within a 2D context. You can consider a 2D shape to simply be a 3D shape that happens to lie on a flat plane.

Resources