My attempt:
Animal <|-- Cat
Animal <|-- Dog
Result:
┌────────┐
│ Animal │
└────────┘
Δ Δ
│ │
┌──┴──┐┌──┴──┐
│ Cat ││ Dog │
└─────┘└─────┘
That is not how a class diagram is supposed to look like.
This is:
┌────────┐
│ Animal │
└────────┘
Δ
┌──┴───┐
┌──┴──┐┌──┴──┐
│ Cat ││ Dog │
└─────┘└─────┘
As suggested, I asked if this is possible on the PlantUML forum.
You can do something like this:
#startuml
class Animal
together {
class Dog
class Cat
}
Animal <|-- Cat
Dog -- (Animal, Cat)
#enduml
There's skinparam groupInheritance 2 which will serve your purpose, although it doesn't work with skinparam linetype ortho as one might expect. Alas, GraphViz is the rendering engine, so that has limitations.
#startuml
skinparam style strictuml
hide empty members
skinparam groupInheritance 2
class Animal
class Cat extends Animal
class Dog extends Animal
#enduml
An interesting thing to do in plantUML but "this is not how class diagram is supposed to look like" is not correct (to my knowledge, at least).
The notation is clear for inheritance/generalization but whether you join the lines before the arrow or have separate lines with separate arrows is a matter of visual preference/making it easier to understand:
Try to sketch the image on top of that wiki you linked with distinct arrow from each child to it's parent, it will be much more messy
Scroll down a bit on wiki to https://en.wikipedia.org/wiki/Class_diagram#Generalization/Inheritance
Related
I have two class diagrams in PlantUML and would like to define a class in one file and reuse it in the other. See the example below.
diagram1.puml:
#startuml diagram1
class "Foo" as foo {
...attributes
}
#enduml
and diagram2:
#startuml diagram2
!include diagram1!foo
class "Bar" as bar {
...attributes
}
#enduml
Now my expectation is that diagram2 will show me both classes Foo and Bar in the diagram. However, the included class is not shown in the render.
How can this be solved?
The plantuml include statement includes code as if it was typed in that included place (like include files for e.g C / C++ etc. do too). So the code should be like:
For Diagram2:
#startuml diagram2
!include diagram1!foo
class "Bar" as bar {
...attributes
}
#enduml
and for diagram1
class "Foo" as foo {
...attributes
}
When you want also show diagram1 as a separate file you have to add an extra file with:
#startuml diagram1_show
!include diagram1!foo
#enduml
I have the following setting:
an owl-ontology (accessed via owlready with this class hierarchy:
owl:Thing
├── ClassA1
└── ClassB1
└── ClassB2
└── ClassB3
└── ClassB4
one instance of each class, say A1, B1 , etc.
a property prop1 which relates A1 to B4: prop1(A1, B4)
I want a SWRL-rule which, given prop1(A1, B4), relates A1 to B3 and B2 via prop1.
I imagine there must be something like this (partially invented syntax):
ClassA(?a), prop1(?a, ?i1), rdfs:type(?i1, ?c),
direct_subclass(?c ,?d), rdfs:type(?i2, ?d), not rdfs:type(?i2, ClassB1) -> prop(?a, ?i2)
However, I did not find anything about "variables representing classes" in SWRL (cf direct_subclass(?c, ?d) or rdfs:type(?i2, ?d)).
How can I formulate my rule?
I'm evaluating if PlantUML can be a good alternative to GraphViz.
It's promoted as "intuitive" but honestly the very first example from the homepage is already confusing.
Why does the following create "Bob" and "Alice" twice?
I'm seeing 2 nodes in the text, and 4 in the output.
Also, the arrow doesn't go between the nodes, but between relations between duplications of the nodes.
Bob->Alice : hello
It makes zero sense to me.
What is the meaning of this example, and what would be a more trivial example with just 2 nodes and an arrow between them?
I see you have fallen for the classical trap of "The first page of the manual is not representative of the tool".(1)
Besides various UML diagrams (like the sequence diagram you encounered), PlantUML has support for various other Software development related formats (such as archimate, Block diagram, bpmn, c4, Computer network diagrams, erd, gantt chart, Mind maps, and wbd), as well as visualization of json and yaml files.
In fact, it even understands Graphviz syntax!(2)
Because of all of this, "intuitive" doesn't happen until you have some basic knowledge of PlantUML.
So back to your issue... What you are seeing isn't what you think it is.
What is that?
Relating things to Graphviz, instead of this:
digraph d {
Bob -> Alice : hello
}
You are actually seeing this:(3)
#startuml
digraph sequenceDiagramExample {
bobHead [ label="Bob" pos="0,1.5!" shape="record" ];
bobPoint0 [ pos="0,0.75!" shape="point" width="0" ]
bobFoot [ label="Bob" pos="0,0!" shape="record" ];
aliceHead [ label="Alice" pos="1,1.5!" shape="record" ];
alicePoint0 [ pos="1,0.75!" shape="point" width="0" ]
aliceFoot [ label="Alice" pos="1,0!" shape="record" ];
bobHead -> bobPoint0 -> bobFoot [ dir="none" style="dashed" ]
aliceHead -> alicePoint0 -> aliceFoot [ dir="none" style="dashed" ]
bobPoint0 -> alicePoint0 [ label="hello" labelloc="c" style="solid" ]
}
#enduml
Gimme an example!
What an example with just two nodes and an arrow between them looks like depends on the kind of graph chosen...
What you have to remember is that, with Graphviz, you have to apply all meaning to a diagram yourself. With PlantUML, the meaning is provided by PlantUML for you. All you need to do is tell PlantUML what you mean.
With a few basic pointers, this becomes intuitive quite quickly. You just need to know what kind of diagram you want to draw before starting...
As you can see from the examples below, PlantUML is a very powerful tool to add to your software developer toolbelt.
I hope the examples will help to make things more intuitive, and that your first misstep won't keep you from exploring PlantUML further!
Activity
#startuml
:Alice;
:Bob;
#enduml
Archimate
#startuml
archimate #Application Alice
archimate #Business Bob
Alice -> Bob
#enduml
Class
#startuml
Alice -|> Bob: Hello
#enduml
Component
#startuml
[Alice] -> [Bob]: Hello
#enduml
Deployment
#startuml
folder Alice
file Bob
Alice -> Bob: Hello
#enduml
Ditaa
#startuml
ditaa
+-------+ +-----+
| | hello | |
| Alice +------>| Bob |
| | | |
+-------+ +-----+
#enduml
Gantt
#startgantt
[Alice]->[Bob]
#endgantt
JSON
#startjson
{
"Alice": ["Bob"]
}
#endjson
MindMap
#startmindmap
+ Alice
++ Bob
#endmindmap
Network
#startuml
nwdiag {
network hello {
Alice;
Bob;
}
}
#enduml
Object
#startuml
object Alice
object Bob
Alice -> Bob
#enduml
Sequence
#startuml
Bob -> Alice : hello
#enduml
State
#startuml
[*] -> Alice
Alice -> Bob: hello
Bob -> [*]
#enduml
Timing
#startuml
concise Hello
0 is Alice
+100 is Bob
#enduml
Use Case
#startuml
:Alice: -> :Bob: : Hello
#enduml
WBS
#startwbs
+ Alice
++ Bob
#endwbs
Footnotes
It's not realy a classic, I just made that up. But it is something that commonly happens.
Reference the manual here: https://plantuml.com/dot
Rendered in neato not dot, see https://stackoverflow.com/a/53470455/153049
They are not “four nodes”, they are top and bottom headers for every participant in the sequence. This is useful for readability in larger sequence diagrams, see some examples here https://plantuml.com/en/sequence-diagram
You can style your diagram to comply with strict UML with
skinparam style strictuml
Full code
#startuml
skinparam style strictuml
Bob -> Alice : hello
Alice -> Bob : ok
#enduml
Taking this small example to illustrate my problem.
common.puml
#startuml common
!startsub COMMON
abstract Common {
id : uuid
}
!endsub
#enduml
myclass1.puml
#startuml myclass1
!includesub common.puml!COMMON
class MyClass1 extends Common {
text: string
}
#enduml
myclass2.puml
#startuml myclass1
!includesub common.puml!COMMON
class MyClass2 extends Common {
value: int
}
#enduml
all.puml
#startuml all
!include ./sub/common.puml
!include ./sub/myclass1.puml
!include ./sub/myclass2.puml
#enduml
When redering the all.puml diagram, I have a strange result in the Common part.
Attributes are rendered 3 times !
Any idea ?
It's either a feature or a bug. Include files just put the code from the file inside another. Since common.puml ends up being included three times (once in all, once in myclass1, and once in myclass2), you wind up more or less with:
abstract Common {
id : uuid
}
abstract Common {
id : uuid
}
abstract Common {
id : uuid
}
which will produce
Maybe you can prevent this from happening by defining a variable, e.g., !$common = 1 inside the part of common.puml that you don't want to repeat, and check before doing the !includesub, e.g.
...
!if (%not($common == 1))
!includesub common.puml!COMMON
!endif
...
(Note - I didn't test this!)
I want to have deployment and sequence stuff in one and the same rendered plantuml picture. So I tried the following but it does not work, the rendering shows the sequence stuff for A, B and C as deployment.
How can I force rendering for "A->B" and "B->C" as sequence diagram stuff?
#startuml
file main.c
note right: I want to have description text here
A -> B : main()
note left : program\nentry function
B -> C : load()
note left : another important function
#enduml
I think you need to add your note later:
#startuml
title file main.c
A -> B : main()
note left : program\nentry function
B -> C : load()
note left : another important function
note right: I want to have description text here
#enduml
Result: