context-map-generator
context-map-generator copied to clipboard
Visualization of relations between one OHS and multiple consumers
When modeling three contexts ContextA
, ContextB
, ContextC
with ContextA
providing an OHS ServiceA
to both ContextB
and ContextC
where the relationships ContextA -> ContextB
and ContextA -> ContextC
have the same name
I would have expected a context map diagram with one OHS on ContextA
with edges to both ContextB
and ContextC
to make it obvious that both consumers consume the same OHS.
Instead, the context map diagram shows ContextA
with two OHSs, one for each relation.
I'm not sure whether this is intended behavior and just a misunderstanting of the visual notation on my side or a bug / due to limitations of how graphviz renders edges between nodes when no port is specified.
Here's an example:
ContextMap Demo {
contains ContextA
contains ContextB
contains ContextC
ContextA [U,OHS]->[D,CF] ContextB : ServiceA
ContextA [U,OHS]->[D,CF] ContextC : ServiceA
}
BoundedContext ContextA
BoundedContext ContextB
BoundedContext ContextC
Expected result:
Actual result:
A similar behavior can be observed when exporting to PlantUML where two interfaces for ServiceA
are generated with one of them being referenced by ContextB
and one by ContextC
.
Expected result:
Actual result:
Interestingly, the DDD sample linked from the examples page shows the visualization I would have expected.
Context map in the documentation:
Context map when generated from the stage 5 source of the sample using the contextmapper vscode plugin version v6.5.1 (operation "Generate Graphical Context Map"):
Hi @dwu
Thanks for reporting the issue! I'm aware of this limitation... There are two things we would have to change in order to improve the visualization:
-
The CML language currently does not support expressing that two OHS's are "the same one". If two relationships use the "OHS" role on the same context, we cannot automatically assume that this is the same API. We would have to enhance the grammar so that we can for example give an OHS an identifier that can be reused. Or make an OHS a real object in the language that can be referenced.
-
The Context Map generator is currently based on GraphViz and we use a pretty simple graph for the visualization. As far as I know GraphViz does not support having "one single point" on a vertex where multiple edges can be connected to? Or am I wrong? In that case we would have to consider to make the OHS its own vertex and find out whether we can visualize this accordingly.
Side note: The example on the examples page that shows it as you would have expected it, was created manually ;)
If you want to help us improving the Context Map generator, contributions are always welcome ;) I have to check when I would have the time to work on this one... But I see that this might be an important feature!
Best regards, Stefan
Hi @stefan-ka,
Thanks for the quick and detailed response.
Regarding your second point: as far as I know, you're right. Graphviz does not allow defining the points where edges connect to nodes explicitly apart from specifying a port
which can be one of (n | ne | e | se | s | sw | w | nw | c | _)
according to the dot language grammar. So this doesn't really help.
After some quick experiments with graphviz to get an idea how this could look like it seems that displaying OHSs as nodes in a way that is as compact and clear as the current representation will be quite tricky. At least if I'm not missing anything in the graphviz documentation.
Here's a naive example with two OHSs ServiceA
and ServiceB
represented as boxes.

Example source code
digraph "ContextMapGraph" {
graph ["imagepath"="/tmp/GraphvizJava"]
"ContextB" ["margin"="0.3","orientation"="139","shape"="egg","fontsize"="16","style"="bold","label"="ContextB\n","fontname"="sans-serif"]
"ContextC" ["margin"="0.3","orientation"="53","shape"="egg","fontsize"="16","style"="bold","label"="ContextC\n","fontname"="sans-serif"]
"ContextA" ["margin"="0.3","orientation"="130","shape"="egg","fontsize"="16","style"="bold","label"="ContextA\n","fontname"="sans-serif"]
"OHS" ["margin"="0.15","shape"="box","fontsize"="12","style"="bold","label"="OHS\nServiceA","fontname"="sans-serif"]
"OHS2" ["margin"="0.15","shape"="box","fontsize"="12","style"="bold","label"="OHS\nServiceB","fontname"="sans-serif"]
"ContextA" -> "OHS" ["fontsize"="12","style"="bold","fontname"="sans-serif","dir"="none"]
"ContextA" -> "OHS2" ["fontsize"="12","style"="bold","fontname"="sans-serif","dir"="none"]
"OHS" -> "ContextB" ["headlabel"=<<table cellspacing="0" cellborder="1" border="0">
<tr><td bgcolor="white" sides="r">D</td><td sides="trbl" bgcolor="white"><font>CF</font></td></tr>
</table>>,"labeldistance"="0","fontsize"="12","taillabel"=<<table cellspacing="0" cellborder="0" border="0">
<tr><td bgcolor="white">U</td></tr>
</table>>,"style"="bold","label"=" ","dir"="none","fontname"="sans-serif"]
"OHS" -> "ContextC" ["headlabel"=<<table cellspacing="0" cellborder="1" border="0">
<tr><td bgcolor="white" sides="r">D</td><td sides="trbl" bgcolor="white"><font>CF</font></td></tr>
</table>>,"labeldistance"="0","fontsize"="12","taillabel"=<<table cellspacing="0" cellborder="0" border="0">
<tr><td bgcolor="white">U</td></tr>
</table>>,"style"="bold","label"=" ","dir"="none","fontname"="sans-serif"]
"OHS2" -> "ContextC" ["headlabel"=<<table cellspacing="0" cellborder="1" border="0">
<tr><td bgcolor="white" sides="r">D</td><td sides="trbl" bgcolor="white"><font>CF</font></td></tr>
</table>>,"labeldistance"="0","fontsize"="12","taillabel"=<<table cellspacing="0" cellborder="0" border="0">
<tr><td bgcolor="white">U</td></tr>
</table>>,"style"="bold","label"=" ","dir"="none","fontname"="sans-serif"]
}
In my opinion it is not really obvious that ServiceA
and ServiceB
are OHSs of ContextA
. Unfortunately, there does not seem to be a way to move the OHS nodes closer to node ContextA
as the edge len
attribute is not supported by dot.
Grouping related nodes as an alternative to moving them closer together does not look too promising either as support for grouping nodes seems to be rather limited. The only way I could find in the documentation is grouping by introducing clusters (subgraphs with a name prefix of cluster_
) which results in something like this.

Example source code
digraph "ContextMapGraph" {
graph ["imagepath"="/tmp/GraphvizJava"]
"ContextB" ["margin"="0.3","orientation"="139","shape"="egg","fontsize"="16","style"="bold","label"="ContextB\n","fontname"="sans-serif"]
"ContextC" ["margin"="0.3","orientation"="53","shape"="egg","fontsize"="16","style"="bold","label"="ContextC\n","fontname"="sans-serif"]
subgraph cluster_ContextA {
"style"="rounded,bold"
"ContextA" ["margin"="0.3","orientation"="130","shape"="egg","fontsize"="16","style"="bold","label"="ContextA\n","fontname"="sans-serif"]
"OHS" ["margin"="0.15","shape"="box","fontsize"="12","style"="bold","label"="OHS: ServiceA","fontname"="sans-serif"]
"OHS2" ["margin"="0.15","shape"="box","fontsize"="12","style"="bold","label"="OHS: ServiceB","fontname"="sans-serif"]
"ContextA" -> "OHS" ["fontsize"="12","style"="bold","fontname"="sans-serif","dir"="none"]
"ContextA" -> "OHS2" ["fontsize"="12","style"="bold","fontname"="sans-serif","dir"="none"]
}
"OHS" -> "ContextB" ["headlabel"=<<table cellspacing="0" cellborder="1" border="0">
<tr><td bgcolor="white" sides="r">D</td><td sides="trbl" bgcolor="white"><font>CF</font></td></tr>
</table>>,"labeldistance"="0","fontsize"="12","taillabel"=<<table cellspacing="0" cellborder="0" border="0">
<tr><td bgcolor="white">U</td></tr>
</table>>,"style"="bold","label"=" ","dir"="none","fontname"="sans-serif"]
"OHS" -> "ContextC" ["headlabel"=<<table cellspacing="0" cellborder="1" border="0">
<tr><td bgcolor="white" sides="r">D</td><td sides="trbl" bgcolor="white"><font>CF</font></td></tr>
</table>>,"labeldistance"="0","fontsize"="12","taillabel"=<<table cellspacing="0" cellborder="0" border="0">
<tr><td bgcolor="white">U</td></tr>
</table>>,"style"="bold","label"=" ","dir"="none","fontname"="sans-serif"]
"OHS2" -> "ContextC" ["headlabel"=<<table cellspacing="0" cellborder="1" border="0">
<tr><td bgcolor="white" sides="r">D</td><td sides="trbl" bgcolor="white"><font>CF</font></td></tr>
</table>>,"labeldistance"="0","fontsize"="12","taillabel"=<<table cellspacing="0" cellborder="0" border="0">
<tr><td bgcolor="white">U</td></tr>
</table>>,"style"="bold","label"=" ","dir"="none","fontname"="sans-serif"]
}
In my opinion this however does not fit the current notation style and as far as I could see, there's no way to influence how groups are displayed apart from setting the style attribute on the cluster subgraph (style=rounded
) in the example).
All in all it unfortunately looks like the implementation options for the context map using graphviz are rather limited. :/
Kind regards Daniel