From charlesreid1

You can use Graphviz's Dot package to create UML diagrams.

Use the pyreverse utility, part of the pylint suite.

pip install pylint

Example diagram here: https://charlesreid1.com/wiki/Olipy

Class Diagram Examples

Simple Class

You can make a simple class UML diagram like this:

<graphviz>

digraph G {

rankdir="LR"
node [shape=record];

Arches [shape=record,label="<f0> Arches | <f1> problemSetup() : void \\
 \lscheduleInitialize() : void \\
 \linitialize() : void \\
 \lscheduleComputeStableTimestep() : void \\
 \lcomputeStableTimestep() : void \\
 \lscheduleTimeAdvance() : void \\
 \ltimeAdvance() : void \\
                                        |  \\
 <f2> sharedState_ : SimulationState  \\
 \lmyMaterial_ : Material \\
                                    "];
}

</graphviz>
<graphviz>

digraph G {

rankdir="LR" node [shape=record];

Arches [shape=record,label="<f0> Arches | <f1> problemSetup() : void \\

\lscheduleInitialize() : void \\
\linitialize() : void \\
\lscheduleComputeStableTimestep() : void \\
\lcomputeStableTimestep() : void \\
\lscheduleTimeAdvance() : void \\
\ltimeAdvance() : void \\
\\
<f2> sharedState_ : SimulationState  \\
\lmyMaterial_ : Material \\
                                   "];

}

</graphviz>

Inheritance Diagram

Class inheritance can be illustrated with a UML diagram with a black arrow pointing from the child to the parent.

This code:
<graphviz>
digraph G {

node [shape=record];

BaseClass [shape=record,label="{<f0> BaseClass \\
    | <f1> + doSomething() : void \\
    }"];

DerivedClass [shape=record,label="{<f0> ScalarEqn \\
    | <f1> + doSomethingDerived() : void \\
    }"];


BaseClass->DerivedClass  [dir=back];
}
</graphviz>
Makes this diagram:

<graphviz>

digraph G {

node [shape=record];

BaseClass [shape=record,label="{<f0> BaseClass \\

<f1> + doSomething() : void \\
   }"];

DerivedClass [shape=record,label="{<f0> ScalarEqn \\

<f1> + doSomethingDerived() : void \\
   }"];


BaseClass->DerivedClass [dir=back]; }

</graphviz>

Composition & Aggregation

Composition

Composition is a strong relationship between two entities, usually linked strongly by lifecycle. To say "an instance of class A MUST have an instance of class B" means that B composes A. It is a 1-to-1 (or 1-to-N) relationship. Think of a situation where you call class A's constructor, and class A's constructor calls class B's constructor; and vice-versa with the destructor (A's destructor calls B's destructor).

A concrete example would be a car and an engine. The two are related by composition: there is a strong lifecycle dependency between the two, and the relationship is 1-to-1.

Composition can be illustrated in a UML diagram as follows:

<graphviz>

digraph G {

node [shape=record];

Car    [shape=record,label="Car"];
Engine [shape=record,label="Engine"];

Car->Engine [dir=back];
}

</graphviz>


</graphviz>
<graphviz>

digraph G {

node [shape=record];


Car [shape=record,label="Car"]; Engine [shape=record,label="Engine"];

Car->Engine [dir=back,arrowtail="diamond"];

}

</graphviz>

And if you want you can even describe the relationship by adding head and tail labels, following http://en.wikipedia.org/wiki/Class_diagram :

<graphviz>

digraph G {

node [shape=record];


Car    [shape=record,label="Car"];
Engine [shape=record,label="Engine"];

Car->Engine [dir=back,arrowtail="diamond"];

}

</graphviz>


<graphviz>

digraph G {

node [shape=record];


Car [shape=record,label="Car"]; Engine [shape=record,label="Engine"];

Car->Engine [dir=back,arrowtail="diamond",headlabel="1..1",label=" ",taillabel="1..1"];

}

</graphviz>



Aggregation

Aggregation is a weaker, many-to-many relationship: for example, ducks and ponds. There is not necessarily a strong lifecycle dependency between the two classes, and it represents a relationship best described as "is part of": "class B is part of class A".

<graphviz>

digraph G {

node [shape=record];

Duck   [shape=record,label="Duck"];
Pond   [shape=record,label="Pond"];

Duck->Pond [dir=back,arrowtail="odiamond"];

}

</graphviz>

<graphviz>

digraph G {

node [shape=record];

Duck [shape=record,label="Duck"]; Pond [shape=record,label="Pond"];

Duck->Pond [dir=back,arrowtail="odiamond"];

}

</graphviz>


And again modifying the head and tail to show more information about the relationship is possible:

<graphviz>

digraph G {

node [shape=record];


Duck   [shape=record,label="Duck"];
Pond   [shape=record,label="Pond"];

Duck->Pond [dir=back,arrowtail="odiamond",taillabel="1..*",label=" ",headlabel="0..*"];

}

</graphviz>



<graphviz>

digraph G {

node [shape=record];


Duck [shape=record,label="Duck"]; Pond [shape=record,label="Pond"];

Duck->Pond [dir=back,arrowtail="odiamond",taillabel="1..*",label=" ",headlabel="1..*"];

}

</graphviz>

Non-Specific Relationship

You can keep the interaction unspecific by making the line plain. This is a relationship that would not otherwise be called out, but you want to draw attention to it.


<graphviz>

digraph G {

node [shape=record];

CEO  [shape=record,label="CEO"];
Peon [shape=record,label="Peon"];

CEO->Peon [arrowhead="none",label="Weekly Message from the CEO"];

}

</graphviz>


<graphviz>

digraph G {

node [shape=record];

CEO [shape=record,label="CEO"]; Peon [shape=record,label="Peon"];

CEO->Peon [arrowhead="none",label="Weekly Message from the CEO"];

}

</graphviz>


Useful Links