├── .github
├── FUNDING.yml
└── workflows
│ └── build.yml
├── .gitignore
├── .gitpod.Dockerfile
├── .gitpod.yml
├── .java-version
├── .servicecutter.yml
├── LICENSE
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
└── main
└── cml
├── architectural-refactorings
├── AR-01-Split-Aggregate-by-Entities
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
├── AR-02-Split-Bounded-Context-by-Features
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
├── AR-03-Split-Bounded-Context-by-Owner
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
├── AR-04-Extract-Aggregates-by-Volatility
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
├── AR-05-Extract-Aggregates-by-Cohesion
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
├── AR-06-Merge-Aggregates
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
├── AR-07-Merge-Bounded-Contexts
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
├── AR-08-Extract-Shared-Kernel
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
├── AR-09-Suspend-Partnership
│ ├── README.md
│ ├── example-input.cml
│ ├── example-output-a.cml
│ ├── example-output-b.cml
│ └── example-output-c.cml
├── AR-10-Change-Shared-Kernel-To-Partnership
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
├── AR-11-Change-Partnership-To-Shared-Kernel
│ ├── README.md
│ ├── example-input.cml
│ └── example-output.cml
└── README.md
├── bounded-context-canvas-example
├── Bounded-Context-Canvas-Example-Stage-1.cml
└── README.md
├── context-mapper-example
├── ContextMapper-Example-Stage-1.cml
├── ContextMapper-Example-Stage-2.cml
├── ContextMapper-Example-Stage-3.cml
├── ContextMapper-Example-Stage-4.cml
├── README.md
├── ServiceCutterLibraryContract.mdsl
└── images
│ ├── ContextMapper-Example-Simple_ComponentDiagram.puml
│ └── ContextMapper-Example-Simple_ContextMap.png
├── ddd-sample
├── DDD-Sample-Stage-1.cml
├── DDD-Sample-Stage-2.cml
├── DDD-Sample-Stage-3.cml
├── DDD-Sample-Stage-4.cml
├── DDD-Sample-Stage-5.cml
├── DDD-Sample_Alternative-Relationship-Syntax.cml
├── README.md
└── images
│ ├── DDD-Cargo-Tracking-ContextMap-Illustration.png
│ └── DDD-Cargo-Tracking-ContextMap-Illustration.svg
├── ddd-service-cutting-sample
├── DDD-Sample.cml
└── DDD-Sample.scl
├── insurance-example
├── Insurance-Example-Stage-1.cml
├── Insurance-Example-Stage-2.cml
├── Insurance-Example-Stage-3.cml
├── Insurance-Example-Stage-4.cml
├── Insurance-Example-Stage-5.cml
├── Insurance-Example_Alternative-Relationship-Syntax.cml
├── Insurance-Example_Team-Map.cml
├── README.md
└── images
│ ├── ContextMap-Illustration.png
│ ├── ContextMap-Illustration.svg
│ ├── TeamMap-Illustration-1.png
│ └── TeamMap-Illustration-2.png
├── lakeside-mutual
├── LakesideMutual.cml
├── QuoteRequestFlow.cml
├── README.md
├── images
│ ├── ContextMap-Illustration.png
│ └── event-storming-result.jpg
└── ooad-example.cml
├── microservice-generation
└── JDL-example
│ ├── generated-insurance-microservices.jdl
│ ├── generated-insurance-microservices.png
│ └── insurance-example-for-JDL-generation.cml
├── ooad-sample-claims
├── README.md
├── claims-use-case-entities.jdl
├── claims-use-case-entities.png
└── claims-use-case.cml
├── same-day-delivery-shop
└── stakeholders-and-values.cml
├── service-coordination-example
└── InsuranceClaimCoordination.cml
└── workflow-samples
├── ClaimsManagement_with_Commands.cml
├── ClaimsManagement_with_ServiceOperations.cml
├── InsuranceQuoteRequest.cml
├── InsuranceQuoteRequest_StateMachineWithoutEventsAndCommands.cml
└── InsuranceQuoteRequest_StateMachineWithoutEventsAndCommands_Entity.cml
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: stefan-ka
2 |
3 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | pull_request:
6 | schedule:
7 | - cron: '0 0 * * 0' # weekly
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: Set up JDK
16 | uses: actions/setup-java@v4
17 | with:
18 | java-version: 17
19 | distribution: 'temurin'
20 | - name: Build with Gradle
21 | run: ./gradlew clean build
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 | /bin
4 | /src-gen
5 | /out
6 |
7 | # Log file
8 | *.log
9 |
10 | # BlueJ files
11 | *.ctxt
12 |
13 | # Mobile Tools for Java (J2ME)
14 | .mtj.tmp/
15 |
16 | # Package Files #
17 | *.jar
18 | *.war
19 | *.nar
20 | *.ear
21 | *.zip
22 | *.tar.gz
23 | *.rar
24 |
25 | # Gradle #
26 | .gradle
27 | build
28 |
29 | # Eclipse #
30 | *.project
31 | *.classpath
32 | **/.settings
33 |
34 | # IntelliJ #
35 | **/.idea
36 |
37 | # VS Code #
38 | **/.vscode
39 |
40 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
41 | hs_err_pid*
42 |
43 | #MacOS
44 | .DS_Store
45 |
--------------------------------------------------------------------------------
/.gitpod.Dockerfile:
--------------------------------------------------------------------------------
1 | FROM gitpod/workspace-full
2 |
3 | # Install Graphviz
4 | RUN sudo apt-get update \
5 | && sudo apt-get -y install graphviz
6 |
7 | # Install Java
8 | RUN bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh && \
9 | sdk install java 17.0.8-tem && \
10 | sdk default java 17.0.8-tem"
11 |
--------------------------------------------------------------------------------
/.gitpod.yml:
--------------------------------------------------------------------------------
1 | tasks:
2 | - init: ./gradlew build
3 | image:
4 | file: .gitpod.Dockerfile
5 | vscode:
6 | extensions:
7 | - jebbs.plantuml
8 | - contextmapper.context-mapper-vscode-extension
9 | - vscjava.vscode-java-pack
10 | - asciidoctor.asciidoctor-vscode
11 |
--------------------------------------------------------------------------------
/.java-version:
--------------------------------------------------------------------------------
1 | 11.0
2 |
--------------------------------------------------------------------------------
/.servicecutter.yml:
--------------------------------------------------------------------------------
1 | algorithm: MARKOV_CLUSTERING
2 | algorithmParams:
3 | leungDelta: 0.55
4 | mclExpansionOperations: 2.0
5 | mclPowerCoefficient: 2.0
6 | leungM: 0.1
7 | cwNodeWeighting: 0.0
8 | priorities:
9 | Identity & Lifecycle Commonality: M
10 | Security Constraint: M
11 | Storage Similarity: XS
12 | Security Criticality: XS
13 | Latency: M
14 | Structural Volatility: XS
15 | Consistency Criticality: XS
16 | Predefined Service Constraint: M
17 | Availability Criticality: XS
18 | Semantic Proximity: M
19 | Consistency Constraint: M
20 | Shared Owner: M
21 | Content Volatility: XS
22 | Security Contextuality: M
23 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "java"
3 | id "org.xtext.builder" version "4.0.0"
4 | }
5 |
6 | group 'org.contextmapper.dsl'
7 | version '1.0-SNAPSHOT'
8 |
9 | sourceCompatibility = '11'
10 | targetCompatibility = '11'
11 |
12 | repositories {
13 | mavenCentral()
14 | }
15 |
16 | dependencies {
17 | xtextLanguages "org.contextmapper:context-mapper-dsl:${cmlVersion}"
18 |
19 | implementation "org.eclipse.xtend:org.eclipse.xtend.lib:${xtendLibVersion}"
20 | implementation "org.contextmapper:context-mapper-dsl:${cmlVersion}"
21 |
22 | testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
23 | testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
24 | }
25 |
26 | xtext {
27 | languages {
28 | cml {
29 | fileExtensions = [ 'cml' ]
30 | setup = 'org.contextmapper.dsl.ContextMappingDSLStandaloneSetup'
31 | generator.outlet.producesJava = true
32 | }
33 | }
34 |
35 | sourceSets {
36 | main {
37 | srcDir 'src/main/cml'
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # dependency versions
2 | cmlVersion=6.12.0
3 | junitVersion=5.5.2
4 | xtendLibVersion=2.19.0
5 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Oct 10 14:46:22 CEST 2019
2 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
3 | distributionBase=GRADLE_USER_HOME
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'context-mapper-examples'
2 |
3 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-01-Split-Aggregate-by-Entities/README.md:
--------------------------------------------------------------------------------
1 | # AR-1: Split Aggregate by Entities
2 | Splits an aggregate which contains multiple entities and produces one aggregate per entity.
3 |
4 | ## Context & Rationales
5 | On the level of entities we typically try to group attributes or [nanoentities in the terminology of ServiceCutter](https://servicecutter.github.io/)
6 | together, which belong to the same identity and share a common lifecycle. Thereby we aim to reduce the coupling between the entities
7 | and increase the cohesion within the entities.
8 |
9 | * **See also**: Coupling criterion [Identity and Lifecycle Commonality](https://github.com/ServiceCutter/ServiceCutter/wiki/CC-1-Identity-and-Lifecycle-Commonality)
10 | of [ServiceCutter](https://servicecutter.github.io/).
11 |
12 | The same approach can be applied on the aggregate level. The aggregates within one bounded context shall be structured in a way which
13 | reduces coupling between the aggregates and increases the cohesion within them.
14 |
15 | As your bounded context develops you may face the problem that an aggregate contains entities which exhibit an unsatisfying
16 | cohesiveness. In such a case you may want to split your aggregate into multiple aggregates in order to improve coupling and cohesion.
17 |
18 | ## Goal
19 | This Architectural Refactoring (AR) splits an aggregate and creates one aggregate for each entity. This AR can be applied when
20 | the entities within an aggregate exhibit unsatisfying cohesiveness and you decide to create multiple aggregates for the single
21 | entities.
22 |
23 | **Inverse AR's:**
24 | * [AR-6: Merge Aggregates](./../AR-6-Merge-Aggregates)
25 |
26 | ## Preconditions
27 | * The input aggregate must contain **at least two entities**.
28 |
29 | ## Input
30 | * The aggregate which shall be split.
31 |
32 | ## Output
33 | * Multiple aggregates which contain one entity each.
34 | * All entities become **aggregate roots** within their own aggregates.
35 |
36 | ## Example
37 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
38 |
39 | ### Input
40 | The following bounded context contains one aggregate with two entities:
41 | ```
42 | BoundedContext CustomerManagementContext {
43 | type = FEATURE
44 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
45 | implementationTechnology = "Java, JEE Application"
46 | responsibilities = "Customers, Addresses"
47 |
48 | /* With a Right-Click on the 'Customers' aggregate you can call the 'Split Aggregate by Entities' refactoring in the
49 | * 'Context Mapper: Refactor' context menu. The refactoring will create a new aggregate and move one of the two entities
50 | * to the new aggregate (see the result in the 'split-aggregate-by-entities-output-example.cml' file).
51 | */
52 | Aggregate Customers {
53 | Entity Customer {
54 | aggregateRoot
55 |
56 | String firstname
57 | String lastname
58 | - List
addresses
59 | }
60 | Entity Address {
61 | String street
62 | int postalCode
63 | String city
64 | }
65 | }
66 | }
67 | ```
68 |
69 | ### Output
70 | Applying the AR **Split Aggregate by Entities** produces two aggregates, one for each entity:
71 | ```
72 | BoundedContext CustomerManagementContext {
73 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
74 | responsibilities = "Customers, Addresses" implementationTechnology = "Java, JEE Application"
75 | Aggregate Customers {
76 | Entity Address {
77 | aggregateRoot
78 |
79 | String street
80 | int postalCode
81 | String city
82 | }
83 | }
84 | /* The newly created aggregate after applying 'Split Aggregate by Entities' on the aggregate in the input file
85 | * 'example-input.cml'.
86 | *
87 | * Note that the refactoring does not produce meaningful aggregate names. You can use the 'Rename Element'
88 | * refactoring (SHIFT-ALT-R) to rename the new aggregate.
89 | */
90 | Aggregate NewAggregate1 {
91 | Entity Customer {
92 | aggregateRoot
93 |
94 | String firstname
95 | String lastname
96 | - List addresses
97 | }
98 | }
99 | }
100 | ```
101 |
102 | ### Example Sources
103 | * Example input source: [example-input.cml](./example-input.cml)
104 | * Example output source: [example-output.cml](./example-output.cml)
105 |
106 | ## Further documentation
107 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
108 | * [AR-1: Split Aggregate by Entities](https://contextmapper.org/docs/ar-split-aggregate-by-entities/)
109 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-01-Split-Aggregate-by-Entities/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Split Aggregate by Entities' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerManagementContext
4 |
5 | }
6 |
7 | BoundedContext CustomerManagementContext {
8 | type = FEATURE
9 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
10 | implementationTechnology = "Java, JEE Application"
11 | responsibilities = "Customers, Addresses"
12 |
13 | /* With a Right-Click on the 'Customers' aggregate you can call the 'Split Aggregate by Entities' refactoring in the
14 | * 'Context Mapper: Refactor' context menu. The refactoring will create a new aggregate and move one of the two entities
15 | * to the new aggregate (see the result in the 'split-aggregate-by-entities-output-example.cml' file).
16 | */
17 | Aggregate Customers {
18 | Entity Customer {
19 | aggregateRoot
20 |
21 | SocialInsuranceNumber sin
22 | String firstname
23 | String lastname
24 | - List addresses
25 | }
26 | Entity Address {
27 | String street
28 | int postalCode
29 | String city
30 | }
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-01-Split-Aggregate-by-Entities/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Split Aggregate by Entities' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerManagementContext
4 |
5 | }
6 |
7 | BoundedContext CustomerManagementContext {
8 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
9 | responsibilities = "Customers, Addresses" implementationTechnology = "Java, JEE Application"
10 | Aggregate Customers {
11 | Entity Address {
12 | aggregateRoot
13 |
14 | String street
15 | int postalCode
16 | String city
17 | }
18 | }
19 | /* The newly created aggregate after applying 'Split Aggregate by Entities' on the aggregate in the input file
20 | * 'example-input.cml'.
21 | *
22 | * Note that the refactoring does not produce meaningful aggregate names. You can use the 'Rename Element'
23 | * refactoring (SHIFT-ALT-R) to rename the new aggregate.
24 | */
25 | Aggregate NewAggregate1 {
26 | Entity Customer {
27 | aggregateRoot
28 |
29 | SocialInsuranceNumber sin
30 | String firstname
31 | String lastname
32 | - List addresses
33 | }
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-02-Split-Bounded-Context-by-Features/README.md:
--------------------------------------------------------------------------------
1 | # AR-2: Split Bounded Context by Features
2 | Splits a bounded context by grouping those aggregates together into one bounded context which are used by the same feature: use case(s) and/or user stories.
3 |
4 | **Hint:** An aggregate in CML can belong to multiple use cases and/or user stories (therefore the plural _Features_ in the AR name).
5 |
6 | ## Context & Rationales
7 | By decomposing a system into multiple bounded contexts we aim for loose coupling between the bounded context and a high cohesion
8 | within them. One approach to achieve this and to decompose a system into components or (micro-) services is to split by use cases and/or user stories.
9 |
10 | **See also:**
11 | * Coupling criterion [Semantic Proximity](https://github.com/ServiceCutter/ServiceCutter/wiki/CC-2-Semantic-Proximity) of [ServiceCutter](https://servicecutter.github.io/)
12 | * [How to decompose the application into services?](https://microservices.io/patterns/microservices.html#how-to-decompose-the-application-into-services) by [Chris Richardson](https://microservices.io/book)
13 | * [Single responsibility principle](https://en.wikipedia.org/wiki/Single_responsibility_principle)
14 |
15 | In Context Mapper you can assign multiple use cases and/or user stories to an aggregate, which allows you to model by which features an aggregate
16 | is used. Consult our [aggregate documentation page](https://contextmapper.org/docs/aggregate/#aggregate-use-cases) to see
17 | how this can be modeled in CML. The [user requirements](https://contextmapper.org/docs/user-requirements/) page documents how you specify your user stories and/or use cases.
18 |
19 | ## Goal
20 | This Architectural Refactoring (AR) splits a bounded context by use cases and/or user stories. This means, it creates bounded contexts containing
21 | aggregates which are used by the same cases/stories. It can be applied if your model exhibits a bounded contexts with aggregates which
22 | are used by different features.
23 |
24 | **Inverse AR's:**
25 | * [AR-7: Merge Bounded Contexts](./../AR-7-Merge-Bounded-Contexts)
26 |
27 | ## Preconditions
28 | * The bounded context must contain **at least two aggregates**.
29 | * The aggregates must be **assigned to different use cases and/or user stories**.
30 |
31 | ## Input
32 | * One bounded context.
33 |
34 | ## Output
35 | * The AR creates multiple bounded contexts. Each bounded context contains one or more aggregates which are used by the same
36 | use cases and/or user stories.
37 |
38 | ## Example
39 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
40 |
41 | ### Input
42 | The following bounded context three aggregates which are used by two different use cases:
43 | ```
44 | /* With a right-click on the 'PolicyManagementContext' bounded context you can execute the 'Split Bounded Context by Features' refactoring.
45 | * It will split the existing bounded context and group the two aggregates of the 'CreateOffer4Customer' use case together. The 'Contract'
46 | * aggregate used by the 'UpdateContract' use case will be separated.
47 | */
48 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
49 | type = FEATURE
50 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
51 | responsibilities = "Offers, Contracts, Policies"
52 | implementationTechnology = "Java, Spring App"
53 |
54 | Aggregate Offers {
55 | useCases = CreateOffer4Customer
56 |
57 | Entity Offer {
58 | aggregateRoot
59 |
60 | int offerId
61 | - Customer client
62 | - List products
63 | BigDecimal price
64 | }
65 | }
66 | Aggregate Products {
67 | useCases = CreateOffer4Customer
68 |
69 | Entity Product {
70 | aggregateRoot
71 |
72 | - ProductId identifier
73 | String productName
74 | }
75 | ValueObject ProductId {
76 | int productId key
77 | }
78 | }
79 | Aggregate Contract {
80 | useCases = UpdateContract
81 |
82 | Entity Contract {
83 | aggregateRoot
84 |
85 | - ContractId identifier
86 | - Customer client
87 | - List products
88 | }
89 | ValueObject ContractId {
90 | int contractId key
91 | }
92 |
93 | Entity Policy {
94 | int policyNr
95 | - Contract contract
96 | BigDecimal price
97 | }
98 | }
99 | }
100 | ```
101 |
102 | ### Output
103 | Applying the AR **Split Bounded Context by Features** produces two bounded context, one for each use case:
104 | ```
105 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
106 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
107 | responsibilities = "Offers, Contracts, Policies"
108 | implementationTechnology = "Java, Spring App"
109 |
110 | Aggregate Contract {
111 | useCases = UpdateContract
112 |
113 | Entity Contract {
114 | aggregateRoot
115 |
116 | - ContractId identifier
117 | - Customer client
118 | - List products
119 | }
120 | ValueObject ContractId {
121 | int contractId key
122 | }
123 |
124 | Entity Policy {
125 | int policyNr
126 | - Contract contract
127 | BigDecimal price
128 | }
129 | }
130 | }
131 |
132 | /**
133 | * A new bounded context created by the 'Split Bounded Context by Features' refactoring applied to 'example-input.cml'.
134 | *
135 | * Note that the refactoring does not produce meaningful bounded context names. You can use the 'Rename Element' refactoring (SHIFT-ALT-R)
136 | * to rename the new aggregate.
137 | */
138 | BoundedContext NewBoundedContext1 {
139 | Aggregate Offers {
140 | useCases = CreateOffer4Customer
141 |
142 | Entity Offer {
143 | aggregateRoot
144 |
145 | int offerId
146 | - Customer client
147 | - List products
148 | BigDecimal price
149 | }
150 | }
151 | Aggregate Products {
152 | useCases = CreateOffer4Customer
153 |
154 | Entity Product {
155 | aggregateRoot
156 |
157 | - ProductId identifier
158 | String productName
159 | }
160 | ValueObject ProductId {
161 | int productId key
162 | }
163 | }
164 | }
165 | ```
166 |
167 | ### Example Sources
168 | * Example input source: [example-input.cml](./example-input.cml)
169 | * Example output source: [example-output.cml](./example-output.cml)
170 |
171 | ## Further documentation
172 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
173 | * [AR-2: Split Bounded Context by Features](https://contextmapper.org/docs/ar-split-bounded-context-by-use-cases/)
174 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-02-Split-Bounded-Context-by-Features/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Split Bounded Context by Features' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains PolicyManagementContext
4 |
5 | }
6 |
7 | /* With a right-click on the 'PolicyManagementContext' bounded context you can execute the 'Split Bounded Context by Features' refactoring.
8 | * It will split the existing bounded context and group the two aggregates of the 'CreateOffer4Customer' use case together. The 'Contract'
9 | * aggregate used by the 'UpdateContract' use case will be separated.
10 | */
11 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
12 | type = FEATURE
13 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
14 | responsibilities = "Offers, Contracts, Policies"
15 | implementationTechnology = "Java, Spring App"
16 |
17 | Aggregate Offers {
18 | useCases = CreateOffer4Customer
19 |
20 | Entity Offer {
21 | aggregateRoot
22 |
23 | int offerId
24 | Customer client
25 | - List products
26 | BigDecimal price
27 | }
28 | }
29 | Aggregate Products {
30 | useCases = CreateOffer4Customer
31 |
32 | Entity Product {
33 | aggregateRoot
34 |
35 | - ProductId identifier
36 | String productName
37 | }
38 | ValueObject ProductId {
39 | int productId key
40 | }
41 | }
42 | Aggregate Contract {
43 | useCases = UpdateContract
44 |
45 | Entity Contract {
46 | aggregateRoot
47 |
48 | - ContractId identifier
49 | Customer client
50 | - List products
51 | }
52 | ValueObject ContractId {
53 | int contractId key
54 | }
55 |
56 | Entity Policy {
57 | int policyNr
58 | - Contract contract
59 | BigDecimal price
60 | }
61 | }
62 | }
63 |
64 | /* Domain & Subdomain Definitions */
65 | Domain InsuranceDomain {
66 | Subdomain PolicyManagementDomain {
67 | type = CORE_DOMAIN
68 | domainVisionStatement = "Subdomain managing contracts and policies."
69 | }
70 | }
71 |
72 | UseCase UpdateContract
73 | UseCase CreateOffer4Customer
74 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-02-Split-Bounded-Context-by-Features/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Split Bounded Context by Features' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains PolicyManagementContext
4 |
5 | }
6 |
7 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
8 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
9 | responsibilities = "Offers, Contracts, Policies"
10 | implementationTechnology = "Java, Spring App"
11 |
12 | Aggregate Contract {
13 | useCases = UpdateContract
14 |
15 | Entity Contract {
16 | aggregateRoot
17 |
18 | - ContractId identifier
19 | Customer client
20 | - List products
21 | }
22 | ValueObject ContractId {
23 | int contractId key
24 | }
25 |
26 | Entity Policy {
27 | int policyNr
28 | - Contract contract
29 | BigDecimal price
30 | }
31 | }
32 | }
33 |
34 | /**
35 | * A new bounded context created by the 'Split Bounded Context by Features' refactoring applied to 'example-input.cml'.
36 | *
37 | * Note that the refactoring does not produce meaningful bounded context names. You can use the 'Rename Element' refactoring (SHIFT-ALT-R)
38 | * to rename the new aggregate.
39 | */
40 | BoundedContext NewBoundedContext1 {
41 | Aggregate Offers {
42 | useCases = CreateOffer4Customer
43 |
44 | Entity Offer {
45 | aggregateRoot
46 |
47 | int offerId
48 | Customer client
49 | - List products
50 | BigDecimal price
51 | }
52 | }
53 | Aggregate Products {
54 | useCases = CreateOffer4Customer
55 |
56 | Entity Product {
57 | aggregateRoot
58 |
59 | - ProductId identifier
60 | String productName
61 | }
62 | ValueObject ProductId {
63 | int productId key
64 | }
65 | }
66 | }
67 |
68 | /* Domain & Subdomain Definitions */
69 | Domain InsuranceDomain {
70 | Subdomain PolicyManagementDomain {
71 | type = CORE_DOMAIN
72 | domainVisionStatement = "Subdomain managing contracts and policies."
73 | }
74 | }
75 |
76 | UseCase UpdateContract
77 | UseCase CreateOffer4Customer
78 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-03-Split-Bounded-Context-by-Owner/README.md:
--------------------------------------------------------------------------------
1 | # AR-3: Split Bounded Context by Owner
2 | Splits a bounded context by grouping those aggregates together into one bounded context which belong to the same team.
3 |
4 | **Hint:** An aggregate in CML can belong to one owner/team (therefore the singular _owner_ in the AR name).
5 |
6 | ## Context & Rationales
7 | By decomposing a system into multiple bounded contexts we aim for loose coupling between the bounded context and a high cohesion
8 | within them. One approach to achieve this and to decompose a system into components or (micro-) services is to split by owner (team).
9 |
10 | **See also:**
11 | * Coupling criterion [Shared Owner](https://github.com/ServiceCutter/ServiceCutter/wiki/CC-3-Shared-Owner) of [ServiceCutter](https://servicecutter.github.io/)
12 | * [Conway's Law](https://en.wikipedia.org/wiki/Conway's_law)
13 | * ["Bounded contexts decouple PARTS. Parts are code **and teams**."](http://ntcoding.co.uk/speaking/talks/domain-driven-design-hidden-lessons-from-the-big-blue-book/craft-conf-budapest-may-2019)
14 | by [Nick Tune](http://www.ntcoding.co.uk/)
15 |
16 | In Context Mapper you can assign an aggregate the owning team. Consult our
17 | [aggregate documentation page](https://contextmapper.org/docs/aggregate/#aggregate-owner) to see
18 | how this can be modeled in CML.
19 |
20 | ## Goal
21 | This Architectural Refactoring (AR) splits a bounded context by the owners of the aggregates. This means, it creates bounded contexts
22 | containing aggregates which all belong to the same team. It can be applied if your model exhibits a bounded contexts with
23 | aggregates which are owned by different teams.
24 |
25 | **Inverse AR's:**
26 | * [AR-7: Merge Bounded Contexts](./../AR-7-Merge-Bounded-Contexts)
27 |
28 | ## Preconditions
29 | * The bounded context must contain **at least two aggregates**.
30 | * The aggregates must be **assigned to different teams**.
31 |
32 | ## Input
33 | * One bounded context.
34 |
35 | ## Output
36 | * The AR creates multiple bounded contexts. Each bounded context contains one or more aggregates which are owned by the same
37 | team.
38 |
39 | ## Example
40 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
41 |
42 | ### Input
43 | The following bounded context contains two aggregates which are owend by two different teams:
44 | ```
45 | /* With a right-click on the 'CustomerSelfServiceContext' bounded context you can execute the 'Split Bounded Context by Owners' refactoring.
46 | * It will split the existing bounded context according to the two owning teams 'CustomerBackendTeam' and 'CustomerFrontendTeam'.
47 | */
48 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
49 | type = APPLICATION
50 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
51 | responsibilities = "AddressChange"
52 | implementationTechnology = "PHP Web Application"
53 |
54 | Aggregate CustomerFrontend {
55 | owner = CustomerFrontendTeam
56 |
57 | DomainEvent CustomerAddressChange {
58 | aggregateRoot
59 |
60 | - UserAccount issuer
61 | - Address changedAddress
62 | }
63 | }
64 | Aggregate Acounts {
65 | owner = CustomerBackendTeam
66 |
67 | Entity UserAccount {
68 | aggregateRoot
69 |
70 | String username
71 | - Customer accountCustomer
72 | }
73 | }
74 | }
75 | ```
76 |
77 | ### Output
78 | Applying the AR **Split Bounded Context by Owner** produces two bounded contexts, one for each team:
79 | ```
80 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
81 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
82 | type = APPLICATION
83 | responsibilities = "AddressChange"
84 | implementationTechnology = "PHP Web Application"
85 |
86 | Aggregate CustomerFrontend {
87 | owner = CustomerFrontendTeam
88 |
89 | DomainEvent CustomerAddressChange {
90 | aggregateRoot
91 |
92 | - UserAccount issuer
93 | - Address changedAddress
94 | }
95 | }
96 | }
97 |
98 | /**
99 | * The new bounded context created by the 'Split Bounded Context by Owners' refactoring applied to 'example-input.cml'.
100 | *
101 | * Note that the refactoring does not produce meaningful bounded context names. You can use the 'Rename Element' refactoring (SHIFT-ALT-R)
102 | * to rename the new aggregate.
103 | *
104 | * The automated refactorings add newly created bounded contexts at the end of the 'bounded context' block, which might not always be the
105 | * desired order. You may change the order after the refactoring manually.
106 | */
107 | BoundedContext NewBoundedContext1 {
108 | Aggregate Acounts {
109 | owner = CustomerBackendTeam
110 |
111 | Entity UserAccount {
112 | aggregateRoot
113 |
114 | String username
115 | - Customer accountCustomer
116 | }
117 | }
118 | }
119 | ```
120 |
121 | ### Example Sources
122 | * Example input source: [example-input.cml](./example-input.cml)
123 | * Example output source: [example-output.cml](./example-output.cml)
124 |
125 | ## Further documentation
126 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
127 | * [AR-3: Split Bounded Context by Owner](https://contextmapper.org/docs/ar-split-bounded-context-by-owners/)
128 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-03-Split-Bounded-Context-by-Owner/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Split Bounded Context by Owner' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerSelfServiceContext
4 |
5 | }
6 |
7 | /* With a right-click on the 'CustomerSelfServiceContext' bounded context you can execute the 'Split Bounded Context by Owners' refactoring.
8 | * It will split the existing bounded context according to the two owning teams 'CustomerBackendTeam' and 'CustomerFrontendTeam'.
9 | */
10 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
11 | type = APPLICATION
12 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
13 | responsibilities = "AddressChange"
14 | implementationTechnology = "PHP Web Application"
15 |
16 | Aggregate CustomerFrontend {
17 | owner = CustomerFrontendTeam
18 |
19 | Entity CustomerAddressChange {
20 | aggregateRoot
21 |
22 | - UserAccount issuer
23 | Address changedAddress
24 | }
25 | }
26 | Aggregate Acounts {
27 | owner = CustomerBackendTeam
28 |
29 | Entity UserAccount {
30 | aggregateRoot
31 |
32 | String username
33 | Customer accountCustomer
34 | }
35 | }
36 | }
37 |
38 | /* Team Definitions */
39 | BoundedContext CustomerBackendTeam {
40 | type = TEAM
41 | }
42 |
43 | BoundedContext CustomerFrontendTeam {
44 | type = TEAM
45 | }
46 |
47 | /* Domain & Subdomain Definitions */
48 | Domain InsuranceDomain {
49 | Subdomain CustomerManagementDomain {
50 | type = CORE_DOMAIN
51 | domainVisionStatement = "Subdomain managing everything customer-related."
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-03-Split-Bounded-Context-by-Owner/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Split Bounded Context by Owner' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerSelfServiceContext
4 |
5 | }
6 |
7 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
8 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
9 | type = APPLICATION
10 | responsibilities = "AddressChange"
11 | implementationTechnology = "PHP Web Application"
12 |
13 | Aggregate CustomerFrontend {
14 | owner = CustomerFrontendTeam
15 |
16 | Entity CustomerAddressChange {
17 | aggregateRoot
18 |
19 | - UserAccount issuer
20 | Address changedAddress
21 | }
22 | }
23 | }
24 |
25 | /* Team Definitions */
26 | BoundedContext CustomerBackendTeam {
27 | type = TEAM
28 | }
29 |
30 | BoundedContext CustomerFrontendTeam {
31 | type = TEAM
32 | }
33 |
34 | /**
35 | * The new bounded context created by the 'Split Bounded Context by Owners' refactoring applied to 'example-input.cml'.
36 | *
37 | * Note that the refactoring does not produce meaningful bounded context names. You can use the 'Rename Element' refactoring (SHIFT-ALT-R)
38 | * to rename the new aggregate.
39 | *
40 | * The automated refactorings add newly created bounded contexts at the end of the 'bounded context' block, which might not always be the
41 | * desired order. You may change the order after the refactoring manually.
42 | */
43 | BoundedContext NewBoundedContext1 {
44 | Aggregate Acounts {
45 | owner = CustomerBackendTeam
46 |
47 | Entity UserAccount {
48 | aggregateRoot
49 |
50 | String username
51 | Customer accountCustomer
52 | }
53 | }
54 | }
55 |
56 | /* Domain & Subdomain Definitions */
57 | Domain InsuranceDomain {
58 | Subdomain CustomerManagementDomain {
59 | type = CORE_DOMAIN
60 | domainVisionStatement = "Subdomain managing everything customer-related."
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-04-Extract-Aggregates-by-Volatility/README.md:
--------------------------------------------------------------------------------
1 | # AR-4: Extract Aggregates by Volatility
2 | Extracts all aggregates from a bounded context by a given volatility, or likelihood for change
3 | (RARELY, NORMAL or OFTEN), and moves them to a separate context.
4 |
5 | ## Context & Rationales
6 | By decomposing a system into multiple bounded contexts we aim for loose coupling between the bounded context and a high cohesion
7 | within them. One approach of decomposing components is to isolate parts which are likely to change.
8 |
9 | **See also:**
10 | * Coupling criterion [Structural Volatility](https://github.com/ServiceCutter/ServiceCutter/wiki/CC-4-Structural-Volatility) of [ServiceCutter](https://servicecutter.github.io/)
11 | * [On the criteria to be used in decomposing systems into modules](https://dl.acm.org/citation.cfm?id=361623) by D. L. Parnas
12 |
13 | In the Context Mapper DSL you can specify how often an aggregate changes with the _likelihoodForChange_ attribute.
14 | See our page [aggregate documentation page](https://contextmapper.org/docs/aggregate/#likelihood-for-change) for more
15 | details.
16 |
17 | ## Goal
18 | This Architectural Refactoring (AR) extracts all aggregates with a given volatility which is provided as input parameter
19 | (RARELY, NORMAL or OFTEN) and moves those aggregates into a new bounded context. Thereby you are able to isolate aggregates with
20 | a certain likelihood for change in one bounded context. This AR can be applied if your model exhibits a bounded context with
21 | aggregates which have different likelihoods for change.
22 |
23 | **Inverse AR's:**
24 | * [AR-7: Merge Bounded Contexts](./../AR-7-Merge-Bounded-Contexts)
25 |
26 | ## Preconditions
27 | * The selected bounded context must contain **at least two aggregates**.
28 | * The aggregates of the selected bounded context must have **different likelihoods for change**.
29 |
30 | ## Input
31 | * One bounded context.
32 |
33 | ## Output
34 | * Another bounded context containing all the aggregates with the selected volatility.
35 |
36 | ## Example
37 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
38 |
39 | ### Input
40 | The following bounded context contains two aggregates with different likelihoods for change:
41 | ```
42 | /* With a right-click on the 'CustomerSelfServiceContext' bounded context you can execute the 'Extract Aggregates by Volatility'
43 | * refactoring. If you choose the volatility 'OFTEN', it will extract the volatile 'CustomerFrontend' aggregate and create a new bounded context for it.
44 | */
45 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
46 | type = APPLICATION
47 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
48 | responsibilities = "AddressChange"
49 | implementationTechnology = "PHP Web Application"
50 |
51 | Aggregate CustomerFrontend {
52 | likelihoodForChange = OFTEN
53 |
54 | DomainEvent CustomerAddressChange {
55 | aggregateRoot
56 |
57 | - UserAccount issuer
58 | - Address changedAddress
59 | }
60 | }
61 | Aggregate Acounts {
62 | Entity UserAccount {
63 | aggregateRoot
64 |
65 | String username
66 | - Customer accountCustomer
67 | }
68 | }
69 | }
70 |
71 | ```
72 |
73 | ### Output
74 | Applying the AR **Extract Aggregates by Volatility** with the volatility parameter **OFTEN** produces another
75 | bounded context containing the _CustomerFrontend_ aggregate:
76 | ```
77 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
78 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
79 | type = APPLICATION
80 | responsibilities = "AddressChange"
81 | implementationTechnology = "PHP Web Application"
82 |
83 | Aggregate Acounts {
84 | Entity UserAccount {
85 | aggregateRoot
86 |
87 | String username
88 | - Customer accountCustomer
89 | }
90 | }
91 | }
92 |
93 | /**
94 | * The extracted bounded context after applying 'Extract Aggregates by Volatility'
95 | * to 'example-input.cml'. The chosen volatility was 'OFTEN'.
96 | *
97 | * You may want to change the name of newly created bounded contexts after applying refactorings.
98 | */
99 | BoundedContext CustomerSelfServiceContext_Volatility_OFTEN {
100 | Aggregate CustomerFrontend {
101 | likelihoodForChange = OFTEN
102 |
103 | DomainEvent CustomerAddressChange {
104 | aggregateRoot
105 |
106 | - UserAccount issuer
107 | - Address changedAddress
108 | }
109 | }
110 | }
111 | ```
112 |
113 | ### Example Sources
114 | * Example input source: [example-input.cml](./example-input.cml)
115 | * Example output source: [example-output.cml](./example-output.cml)
116 |
117 | ## Further documentation
118 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
119 | * [AR-4: Extract Aggregates by Volatility](https://contextmapper.org/docs/ar-extract-aggregates-by-volatility/)
120 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-04-Extract-Aggregates-by-Volatility/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Extract Aggregates by Volatility' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerSelfServiceContext
4 |
5 | }
6 |
7 | /* With a right-click on the 'CustomerSelfServiceContext' bounded context you can execute the 'Extract Aggregates by Volatility'
8 | * refactoring. If you choose the volatility 'OFTEN', it will extract the volatile 'CustomerFrontend' aggregate and create a new bounded context for it.
9 | */
10 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
11 | type = APPLICATION
12 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
13 | responsibilities = "AddressChange"
14 | implementationTechnology = "PHP Web Application"
15 |
16 | Aggregate CustomerFrontend {
17 | likelihoodForChange = OFTEN
18 |
19 | Entity CustomerAddressChange {
20 | aggregateRoot
21 |
22 | - UserAccount issuer
23 | Address changedAddress
24 | }
25 | }
26 | Aggregate Acounts {
27 | Entity UserAccount {
28 | aggregateRoot
29 |
30 | String username
31 | Customer accountCustomer
32 | }
33 | }
34 | }
35 |
36 | /* Domain & Subdomain Definitions */
37 | Domain InsuranceDomain {
38 | Subdomain CustomerManagementDomain {
39 | type = CORE_DOMAIN
40 | domainVisionStatement = "Subdomain managing everything customer-related."
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-04-Extract-Aggregates-by-Volatility/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Extract Aggregates by Volatility' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerSelfServiceContext
4 |
5 | }
6 |
7 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
8 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
9 | type = APPLICATION
10 | responsibilities = "AddressChange"
11 | implementationTechnology = "PHP Web Application"
12 |
13 | Aggregate Acounts {
14 | Entity UserAccount {
15 | aggregateRoot
16 |
17 | String username
18 | Customer accountCustomer
19 | }
20 | }
21 | }
22 |
23 | /**
24 | * The extracted bounded context after applying 'Extract Aggregates by Volatility'
25 | * to 'example-input.cml'. The chosen volatility was 'OFTEN'.
26 | *
27 | * You may want to change the name of newly created bounded contexts after applying refactorings.
28 | */
29 | BoundedContext CustomerSelfServiceContext_Volatility_OFTEN {
30 | Aggregate CustomerFrontend {
31 | likelihoodForChange = OFTEN
32 |
33 | Entity CustomerAddressChange {
34 | aggregateRoot
35 |
36 | - UserAccount issuer
37 | Address changedAddress
38 | }
39 | }
40 | }
41 |
42 | /* Domain & Subdomain Definitions */
43 | Domain InsuranceDomain {
44 | Subdomain CustomerManagementDomain {
45 | type = CORE_DOMAIN
46 | domainVisionStatement = "Subdomain managing everything customer-related."
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-05-Extract-Aggregates-by-Cohesion/README.md:
--------------------------------------------------------------------------------
1 | # AR-5: Extract Aggregates by Cohesion
2 | Extracts a set of aggregates which are chosen by certain cohesion criteria and moves them to a separate bounded context.
3 |
4 | ## Context & Rationales
5 | By decomposing a system into multiple bounded contexts we aim for loose coupling between the bounded context and a high cohesion
6 | within them. There are many different approaches and different coupling criteria by which the software architect may want
7 | to decompose a system into components.
8 |
9 | **See also:**
10 | * [Coupling criteria catalog](https://github.com/ServiceCutter/ServiceCutter/wiki/Coupling-Criteria) of [ServiceCutter](https://servicecutter.github.io/)
11 |
12 | ## Goal
13 | This Architectural Refactoring (AR) allows to manually select the aggregates which should be extracted by any coupling criteria
14 | or Non-functional Requirements (NFR). The goal of this AR is to isolate a set of aggregates within a new bounded context by
15 | an individual criterion.
16 |
17 | **Inverse AR's:**
18 | * [AR-7: Merge Bounded Contexts](./../AR-7-Merge-Bounded-Contexts)
19 |
20 | ## Preconditions
21 | * The selected bounded context must contain **at least two aggregates**.
22 |
23 | ## Input
24 | * One bounded context.
25 | * A selection of aggregates which shall be extracted to a new bounded context.
26 |
27 | ## Output
28 | * A new bounded context containing the selected aggregates.
29 |
30 | ## Example
31 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
32 |
33 | ### Input
34 | The following bounded context contains three aggregates:
35 | ```
36 | /* With a right-click on the 'PolicyManagementContext' bounded context you can execute the 'Extract Aggregates by Cohesion'
37 | * refactoring. A dialog will pop up which allows you to select the aggregates to be extracted. You can further specify
38 | * the name of the new bounded context. For example: As architect you may want to extract the 'Offers' aggregate due
39 | * to other differing availability requirements.
40 | */
41 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
42 | type = FEATURE
43 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
44 | responsibilities = "Offers, Contracts, Policies"
45 | implementationTechnology = "Java, Spring App"
46 |
47 | Aggregate Offers {
48 | Entity Offer {
49 | aggregateRoot
50 |
51 | int offerId
52 | - Customer client
53 | - List products
54 | BigDecimal price
55 | }
56 | }
57 | Aggregate Products {
58 | Entity Product {
59 | aggregateRoot
60 |
61 | - ProductId identifier
62 | String productName
63 | }
64 | ValueObject ProductId {
65 | int productId key
66 | }
67 | }
68 | Aggregate Contract {
69 | Entity Contract {
70 | aggregateRoot
71 |
72 | - ContractId identifier
73 | - Customer client
74 | - List products
75 | }
76 | ValueObject ContractId {
77 | int contractId key
78 | }
79 |
80 | Entity Policy {
81 | int policyNr
82 | - Contract contract
83 | BigDecimal price
84 | }
85 | }
86 | }
87 | ```
88 |
89 | ### Output
90 | Applying the AR **Extract Aggregates by Cohesion** with the aggregate selection **[ Offers ]** produces
91 | a new bounded context with the _Offers_ aggregate:
92 | ```
93 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
94 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
95 | responsibilities = "Offers, Contracts, Policies"
96 | implementationTechnology = "Java, Spring App"
97 |
98 | Aggregate Products {
99 | Entity Product {
100 | aggregateRoot
101 |
102 | - ProductId identifier
103 | String productName
104 | }
105 | ValueObject ProductId {
106 | int productId key
107 | }
108 | }
109 | Aggregate Contract {
110 | Entity Contract {
111 | aggregateRoot
112 |
113 | - ContractId identifier
114 | - Customer client
115 | - List products
116 | }
117 | ValueObject ContractId {
118 | int contractId key
119 | }
120 |
121 | Entity Policy {
122 | int policyNr
123 | - Contract contract
124 | BigDecimal price
125 | }
126 | }
127 | }
128 |
129 | /**
130 | * New bounded context after applying 'Extract Aggregates by Cohesion' to 'example-input.cml'
131 | * with the following parameters:
132 | * - New bounded context name: 'SalesBoundedContext'
133 | * - Selected aggregates: 'Offers'
134 | */
135 | BoundedContext SalesBoundedContext {
136 | Aggregate Offers {
137 | Entity Offer {
138 | aggregateRoot
139 |
140 | int offerId
141 | - Customer client
142 | - List products
143 | BigDecimal price
144 | }
145 | }
146 | }
147 | ```
148 |
149 | ### Example Sources
150 | * Example input source: [example-input.cml](./example-input.cml)
151 | * Example output source: [example-output.cml](./example-output.cml)
152 |
153 | ## Further documentation
154 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
155 | * [AR-5: Extract Aggregates by Cohesion](https://contextmapper.org/docs/ar-extract-aggregates-by-cohesion/)
156 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-05-Extract-Aggregates-by-Cohesion/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Extract Aggregates by Cohesion' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains PolicyManagementContext
4 |
5 | }
6 |
7 | /* With a right-click on the 'PolicyManagementContext' bounded context you can execute the 'Extract Aggregates by Cohesion'
8 | * refactoring. A dialog will pop up which allows you to select the aggregates to be extracted. You can further specify
9 | * the name of the new bounded context. For example: As architect you may want to extract the 'Offers' aggregate due
10 | * to other differing availability requirements.
11 | */
12 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
13 | type = FEATURE
14 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
15 | responsibilities = "Offers, Contracts, Policies"
16 | implementationTechnology = "Java, Spring App"
17 |
18 | Aggregate Offers {
19 | Entity Offer {
20 | aggregateRoot
21 |
22 | int offerId
23 | Customer client
24 | - List products
25 | BigDecimal price
26 | }
27 | }
28 | Aggregate Products {
29 | Entity Product {
30 | aggregateRoot
31 |
32 | - ProductId identifier
33 | String productName
34 | }
35 | ValueObject ProductId {
36 | int productId key
37 | }
38 | }
39 | Aggregate Contract {
40 | Entity Contract {
41 | aggregateRoot
42 |
43 | - ContractId identifier
44 | Customer client
45 | - List products
46 | }
47 | ValueObject ContractId {
48 | int contractId key
49 | }
50 |
51 | Entity Policy {
52 | int policyNr
53 | - Contract contract
54 | BigDecimal price
55 | }
56 | }
57 | }
58 |
59 | /* Domain & Subdomain Definitions */
60 | Domain InsuranceDomain {
61 | Subdomain PolicyManagementDomain {
62 | type = CORE_DOMAIN
63 | domainVisionStatement = "Subdomain managing contracts and policies."
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-05-Extract-Aggregates-by-Cohesion/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Extract Aggregates by Cohesion' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains PolicyManagementContext
4 |
5 | }
6 |
7 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
8 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
9 | responsibilities = "Offers, Contracts, Policies"
10 | implementationTechnology = "Java, Spring App"
11 |
12 | Aggregate Products {
13 | Entity Product {
14 | aggregateRoot
15 |
16 | - ProductId identifier
17 | String productName
18 | }
19 | ValueObject ProductId {
20 | int productId key
21 | }
22 | }
23 | Aggregate Contract {
24 | Entity Contract {
25 | aggregateRoot
26 |
27 | - ContractId identifier
28 | Customer client
29 | - List products
30 | }
31 | ValueObject ContractId {
32 | int contractId key
33 | }
34 |
35 | Entity Policy {
36 | int policyNr
37 | - Contract contract
38 | BigDecimal price
39 | }
40 | }
41 | }
42 |
43 | /**
44 | * New bounded context after applying 'Extract Aggregates by Cohesion' to 'example-input.cml'
45 | * with the following parameters:
46 | * - New bounded context name: 'SalesBoundedContext'
47 | * - Selected aggregates: 'Offers'
48 | */
49 | BoundedContext SalesBoundedContext {
50 | Aggregate Offers {
51 | Entity Offer {
52 | aggregateRoot
53 |
54 | int offerId
55 | Customer client
56 | - List products
57 | BigDecimal price
58 | }
59 | }
60 | }
61 |
62 | /* Domain & Subdomain Definitions */
63 | Domain InsuranceDomain {
64 | Subdomain PolicyManagementDomain {
65 | type = CORE_DOMAIN
66 | domainVisionStatement = "Subdomain managing contracts and policies."
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-06-Merge-Aggregates/README.md:
--------------------------------------------------------------------------------
1 | # AR-6: Merge Aggregates
2 | Merges two aggregates within a bounded context together to one aggregate.
3 |
4 | ## Context & Rationales
5 | On the level of entities we typically try to group attributes or [nanoentities in the terminology of ServiceCutter](https://servicecutter.github.io/)
6 | together, which belong to the same identity and share a common lifecycle. Thereby we aim to reduce the coupling between the entities
7 | and increase the cohesion within the entities.
8 |
9 | * **See also**: Coupling criterion [Identity and Lifecycle Commonality](https://github.com/ServiceCutter/ServiceCutter/wiki/CC-1-Identity-and-Lifecycle-Commonality)
10 | of [ServiceCutter](https://servicecutter.github.io/).
11 |
12 | The same approach can be applied on the aggregate level. The aggregates within one bounded context shall be structured in a way which
13 | reduces coupling between the aggregates and increases the cohesion within them.
14 |
15 | During the evolution of your bounded context you may find multiple aggregates containing entities which belong together (for
16 | example because they share a common lifecycle) and merging the aggregates together improves coupling and cohesion.
17 |
18 | ## Goal
19 | This Architectural Refactoring (AR) merges two aggregates in a bounded context together into one aggregate. It can be applied
20 | in a situation where the entities in the two aggregates somehow belong together and a merge of the aggregates improves the
21 | coupling and cohesion.
22 |
23 | **Inverse AR's:**
24 | * [AR-1: Split Aggregate by Entities](./../AR-1-Split-Aggregate-by-Entities)
25 |
26 | ## Preconditions
27 | * Your bounded context must contain **at least two aggregates** which can be merged.
28 |
29 | ## Input
30 | * Two aggregates which belong to the same bounded context.
31 |
32 | ## Output
33 | * One aggregate containing all objects (entities, value objects, etc.) of the two input aggregates.
34 |
35 | ## Example
36 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
37 |
38 | ### Input
39 | The following bounded context contains two aggregates:
40 | ```
41 | /* With a right-click on the 'Customers' aggregate (or on the 'Addresses' aggregate, as you wish)
42 | * you can execute the 'Merge Aggregates' refactoring. A dialog will show up and ask you with
43 | * which other aggregate you want to merge. Choose the other aggregate and the refactoring will merge them.
44 | */
45 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
46 | type = FEATURE
47 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
48 | implementationTechnology = "Java, JEE Application"
49 | responsibilities = "Customers, Addresses"
50 |
51 | Aggregate Customers {
52 | Entity Customer {
53 | aggregateRoot
54 | - SocialInsuranceNumber sin
55 | String firstname
56 | String lastname
57 | - List addresses
58 | }
59 | ValueObject SocialInsuranceNumber {
60 | String sin key
61 | }
62 | }
63 | Aggregate Addresses {
64 | Entity Address {
65 | String street
66 | int postalCode
67 | String city
68 | }
69 | }
70 | }
71 | ```
72 |
73 | ### Output
74 | Applying the AR **Merge Aggregates** with the aggregate selection **[ Customers, Addresses ]**
75 | merges the objects of both aggregates into the _Customers_ aggregate:
76 | ```
77 | /*
78 | * The resulting bounded context after applying 'Merge Aggregates' to the file 'example-input.cml'.
79 | * The 'Addresses' aggregate has been merged into the 'Customers' aggregate.
80 | */
81 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
82 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
83 | responsibilities = "Customers, Addresses"
84 | implementationTechnology = "Java, JEE Application"
85 | Aggregate Customers {
86 | Entity Customer {
87 | aggregateRoot
88 | - SocialInsuranceNumber sin
89 | String firstname
90 | String lastname
91 | - List addresses
92 | }
93 | ValueObject SocialInsuranceNumber {
94 | String sin key
95 | }
96 | Entity Address {
97 | String street
98 | int postalCode
99 | String city
100 | }
101 | }
102 | }
103 | ```
104 |
105 | ### Example Sources
106 | * Example input source: [example-input.cml](./example-input.cml)
107 | * Example output source: [example-output.cml](./example-output.cml)
108 |
109 | ## Further documentation
110 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
111 | * [AR-6: Merge Aggregates](https://contextmapper.org/docs/ar-merge-aggregates/)
112 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-06-Merge-Aggregates/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Merge Aggregates' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerManagementContext
4 | contains CustomerSelfServiceContext
5 |
6 | CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext {
7 | exposedAggregates = Customers, Addresses
8 | }
9 |
10 | }
11 |
12 | /* With a right-click on the 'Customers' aggregate (or on the 'Addresses' aggregate, as you wish)
13 | * you can execute the 'Merge Aggregates' refactoring. A dialog will show up and ask you with
14 | * which other aggregate you want to merge. Choose the other aggregate and the refactoring will merge them.
15 | */
16 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
17 | type = FEATURE
18 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
19 | implementationTechnology = "Java, JEE Application"
20 | responsibilities = "Customers, Addresses"
21 |
22 | Aggregate Customers {
23 | Entity Customer {
24 | aggregateRoot
25 | - SocialInsuranceNumber sin
26 | String firstname
27 | String lastname
28 | - List addresses
29 | }
30 | ValueObject SocialInsuranceNumber {
31 | String sin key
32 | }
33 | }
34 | Aggregate Addresses {
35 | Entity Address {
36 | String street
37 | int postalCode
38 | String city
39 | }
40 | }
41 | }
42 |
43 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
44 | type = APPLICATION
45 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
46 | responsibilities = "AddressChange"
47 | implementationTechnology = "PHP Web Application"
48 |
49 | Aggregate CustomerFrontend {
50 | Entity CustomerAddressChange {
51 | aggregateRoot
52 | - UserAccount issuer
53 | - Address changedAddress
54 | }
55 | }
56 | Aggregate Acounts {
57 | Entity UserAccount {
58 | aggregateRoot
59 | String username
60 | - Customer accountCustomer
61 | }
62 | }
63 | }
64 |
65 | /* Domain & Subdomain Definitions */
66 | Domain InsuranceDomain {
67 | Subdomain CustomerManagementDomain {
68 | type = CORE_DOMAIN
69 | domainVisionStatement = "Subdomain managing everything customer-related."
70 | }
71 | }
72 |
73 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-06-Merge-Aggregates/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Merge Aggregates' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerManagementContext
4 | contains CustomerSelfServiceContext
5 |
6 | CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext {
7 | exposedAggregates = Customers
8 | }
9 |
10 | }
11 |
12 | /*
13 | * The resulting bounded context after applying 'Merge Aggregates' to the file 'example-input.cml'.
14 | * The 'Addresses' aggregate has been merged into the 'Customers' aggregate.
15 | */
16 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
17 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
18 | responsibilities = "Customers, Addresses"
19 | implementationTechnology = "Java, JEE Application"
20 | Aggregate Customers {
21 | Entity Customer {
22 | aggregateRoot
23 | - SocialInsuranceNumber sin
24 | String firstname
25 | String lastname
26 | - List addresses
27 | }
28 | ValueObject SocialInsuranceNumber {
29 | String sin key
30 | }
31 | Entity Address {
32 | String street
33 | int postalCode
34 | String city
35 | }
36 | }
37 | }
38 |
39 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
40 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
41 | type = APPLICATION
42 | responsibilities = "AddressChange"
43 | implementationTechnology = "PHP Web Application"
44 |
45 | Aggregate CustomerFrontend {
46 | Entity CustomerAddressChange {
47 | aggregateRoot
48 | - UserAccount issuer
49 | - Address changedAddress
50 | }
51 | }
52 | Aggregate Acounts {
53 | Entity UserAccount {
54 | aggregateRoot
55 | String username
56 | - Customer accountCustomer
57 | }
58 | }
59 | }
60 |
61 | /* Domain & Subdomain Definitions */
62 | Domain InsuranceDomain {
63 | Subdomain CustomerManagementDomain {
64 | type = CORE_DOMAIN
65 | domainVisionStatement = "Subdomain managing everything customer-related."
66 | }
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-07-Merge-Bounded-Contexts/README.md:
--------------------------------------------------------------------------------
1 | # AR-7 Merge Bounded Contexts
2 | Merges two bounded contexts together. The result is one bounded context containing all the aggregates of the two input bounded
3 | contexts.
4 |
5 | ## Context & Rationales
6 | By decomposing a system into multiple bounded contexts we aim for loose coupling between the bounded context and a high cohesion
7 | within them. However, sometimes a decomposition may be too fine-granular and merging bounded contexts with a high
8 | coupling together improves the cohesion within the corresponding resulting bounded context.
9 |
10 | ## Goal
11 | This Architectural Refactoring (AR) merges two bounded contexts together. The resulting bounded context contains all aggregates
12 | of the two input bounded contexts. It can be applied if two bounded context are tightly coupled and the aggregates somehow
13 | belong together. This may improve the cohesion within the resulting bounded context.
14 |
15 | **Notes:**
16 | * By applying this AR multiple times you may end with one single Bounded Context and an empty Context Map (no relationships).
17 |
18 | **Inverse AR's:**
19 | * [AR-4: Extract Aggregates by Volatility](./../AR-4-Extract-Aggregates-by-Volatility)
20 | * [AR-5: Extract Aggregates by Cohesion](./../AR-5-Extract-Aggregates-by-Cohesion)
21 | * [AR-2: Split Bounded Context by Use Cases](./../AR-2-Split-Bounded-Context-by-Use-Cases) (may need multiple merges to completely revert)
22 | * [AR-3: Split Bounded Context by Owner](./../AR-3-Split-Bounded-Context-by-Owner) (may need multiple merges to completely revert)
23 |
24 | ## Preconditions
25 | * Your model needs **at least two bounded contexts** to merge.
26 |
27 | ## Input
28 | * Two bounded contexts.
29 |
30 | ## Output
31 | * One bounded context containing all aggregates of the two input bounded contexts.
32 |
33 | ## Example
34 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
35 |
36 | ### Input
37 | Two input bounded contexts:
38 | ```
39 | /* With a right-click on the 'CustomerManagementContext' (or one of the other contexts, as you wish)
40 | * bounded context you can execute the 'Merge Bounded Contexts' refactoring. A dialog will show up and ask you with
41 | * which other bounded context you want to merge. Choose a second bounded context and the refactoring will merge them.
42 | */
43 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
44 | type = FEATURE
45 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
46 | implementationTechnology = "Java, JEE Application"
47 | responsibilities = "Customers, Addresses"
48 |
49 | Aggregate Customers {
50 | Entity Customer {
51 | aggregateRoot
52 |
53 | - SocialInsuranceNumber sin
54 | String firstname
55 | String lastname
56 | - List addresses
57 | }
58 | Entity Address {
59 | String street
60 | int postalCode
61 | String city
62 | }
63 | ValueObject SocialInsuranceNumber {
64 | String sin key
65 | }
66 | }
67 | }
68 |
69 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
70 | type = APPLICATION
71 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
72 | responsibilities = "AddressChange"
73 | implementationTechnology = "PHP Web Application"
74 |
75 | Aggregate CustomerFrontend {
76 | DomainEvent CustomerAddressChange {
77 | aggregateRoot
78 |
79 | - UserAccount issuer
80 | - Address changedAddress
81 | }
82 | }
83 | Aggregate Acounts {
84 | Entity UserAccount {
85 | aggregateRoot
86 |
87 | String username
88 | - Customer accountCustomer
89 | }
90 | }
91 | }
92 | ```
93 |
94 | ### Output
95 | Applying the AR **Merge Bounded Contexts** merges all aggregates of the _CustomerSelfServiceContext_ bounded context
96 | into the _CustomerManagementContext_ bounded context:
97 | ```
98 | /**
99 | * The merged bounded context after applying 'Merge Bounded Contexts' to 'example-input.cml'.
100 | * We selected the 'CustomerSelfServiceContext' context as second bounded context.
101 | */
102 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
103 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
104 | responsibilities = "Customers, Addresses" , "AddressChange"
105 | implementationTechnology = "Java, JEE Application"
106 | Aggregate Customers {
107 | Entity Customer {
108 | aggregateRoot
109 |
110 | - SocialInsuranceNumber sin
111 | String firstname
112 | String lastname
113 | - List addresses
114 | }
115 | Entity Address {
116 | String street
117 | int postalCode
118 | String city
119 | }
120 | ValueObject SocialInsuranceNumber {
121 | String sin key
122 | }
123 | }
124 | Aggregate CustomerFrontend {
125 | DomainEvent CustomerAddressChange {
126 | aggregateRoot
127 |
128 | - UserAccount issuer
129 | - Address changedAddress
130 | }
131 | }
132 | Aggregate Acounts {
133 | Entity UserAccount {
134 | aggregateRoot
135 |
136 | String username
137 | - Customer accountCustomer
138 | }
139 | }
140 | }
141 | ```
142 |
143 | ### Example Sources
144 | * Example input source: [example-input.cml](./example-input.cml)
145 | * Example output source: [example-output.cml](./example-output.cml)
146 |
147 | ## Further documentation
148 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
149 | * [AR-7 Merge Bounded Contexts](https://contextmapper.org/docs/ar-merge-bounded-contexts/)
150 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-07-Merge-Bounded-Contexts/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Merge Bounded Contexts' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerManagementContext
4 | contains CustomerSelfServiceContext
5 | contains PrintingContext
6 |
7 | CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext : Customer_Frontend_Backend_Relationship { // Relationship name is optional
8 | exposedAggregates = Customers
9 | }
10 |
11 | CustomerManagementContext [D,ACL]<-[U,OHS,PL] PrintingContext {
12 | implementationTechnology = "SOAP"
13 | downstreamRights = INFLUENCER
14 | exposedAggregates = Printing
15 | }
16 |
17 | }
18 |
19 | /* With a right-click on the 'CustomerManagementContext' (or one of the other contexts, as you wish)
20 | * bounded context you can execute the 'Merge Bounded Contexts' refactoring. A dialog will show up and ask you with
21 | * which other bounded context you want to merge. Choose a second bounded context and the refactoring will merge them.
22 | */
23 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
24 | type = FEATURE
25 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
26 | implementationTechnology = "Java, JEE Application"
27 | responsibilities = "Customers, Addresses"
28 |
29 | Aggregate Customers {
30 | Entity Customer {
31 | aggregateRoot
32 |
33 | - SocialInsuranceNumber sin
34 | String firstname
35 | String lastname
36 | - List addresses
37 | }
38 | Entity Address {
39 | String street
40 | int postalCode
41 | String city
42 | }
43 | ValueObject SocialInsuranceNumber {
44 | String sin key
45 | }
46 | }
47 | }
48 |
49 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
50 | type = APPLICATION
51 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
52 | responsibilities = "AddressChange"
53 | implementationTechnology = "PHP Web Application"
54 |
55 | Aggregate CustomerFrontend {
56 | Entity CustomerAddressChange {
57 | aggregateRoot
58 |
59 | - UserAccount issuer
60 | - Address changedAddress
61 | }
62 | }
63 | Aggregate Acounts {
64 | Entity UserAccount {
65 | aggregateRoot
66 |
67 | String username
68 | - Customer accountCustomer
69 | }
70 | }
71 | }
72 |
73 | BoundedContext PrintingContext implements PrintingDomain {
74 | type = SYSTEM
75 | responsibilities = "Document Printing"
76 | domainVisionStatement = "An external system which provides printing services to the other Bounded Contexts."
77 |
78 | Aggregate Printing {
79 | Entity PrintingJob {
80 | aggregateRoot
81 |
82 | int printingId
83 | - Document document
84 | - Template template
85 | }
86 |
87 | Entity Document {
88 | DomainObject source
89 | String template
90 | }
91 | }
92 | Aggregate Templating {
93 | Entity Template {
94 | aggregateRoot
95 |
96 | int templateId
97 | String templateName
98 | }
99 | }
100 | }
101 |
102 | /* Domain & Subdomain Definitions */
103 | Domain InsuranceDomain {
104 | Subdomain CustomerManagementDomain {
105 | type = CORE_DOMAIN
106 | domainVisionStatement = "Subdomain managing everything customer-related."
107 | }
108 | Subdomain PrintingDomain {
109 | type = SUPPORTING_DOMAIN
110 | domainVisionStatement = "Service (external system) to solve printing for all kinds of documents (debts, policies, etc.)"
111 | }
112 | }
113 |
114 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-07-Merge-Bounded-Contexts/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Merge Bounded Contexts' refactoring and shows a small part of the insurance example. */
2 | ContextMap {
3 | contains CustomerManagementContext
4 | contains PrintingContext
5 |
6 | CustomerManagementContext [D,ACL]<-[U,OHS,PL] PrintingContext {
7 | implementationTechnology = "SOAP"
8 | exposedAggregates = Printing
9 | }
10 |
11 | }
12 |
13 | /**
14 | * The merged bounded context after applying 'Merge Bounded Contexts' to 'example-input.cml'.
15 | * We selected the 'CustomerSelfServiceContext' context as second bounded context.
16 | */
17 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
18 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
19 | responsibilities = "Customers, Addresses" , "AddressChange"
20 | implementationTechnology = "Java, JEE Application"
21 | Aggregate Customers {
22 | Entity Customer {
23 | aggregateRoot
24 |
25 | - SocialInsuranceNumber sin
26 | String firstname
27 | String lastname
28 | - List addresses
29 | }
30 | Entity Address {
31 | String street
32 | int postalCode
33 | String city
34 | }
35 | ValueObject SocialInsuranceNumber {
36 | String sin key
37 | }
38 | }
39 | Aggregate CustomerFrontend {
40 | Entity CustomerAddressChange {
41 | aggregateRoot
42 |
43 | - UserAccount issuer
44 | - Address changedAddress
45 | }
46 | }
47 | Aggregate Acounts {
48 | Entity UserAccount {
49 | aggregateRoot
50 |
51 | String username
52 | - Customer accountCustomer
53 | }
54 | }
55 | }
56 |
57 | BoundedContext PrintingContext implements PrintingDomain {
58 | domainVisionStatement = "An external system which provides printing services to the other Bounded Contexts."
59 | type = SYSTEM
60 | responsibilities = "Document Printing"
61 | Aggregate Printing {
62 | Entity PrintingJob {
63 | aggregateRoot
64 |
65 | int printingId
66 | - Document document
67 | - Template template
68 | }
69 |
70 | Entity Document {
71 | DomainObject source
72 | String template
73 | }
74 | }
75 | Aggregate Templating {
76 | Entity Template {
77 | aggregateRoot
78 |
79 | int templateId
80 | String templateName
81 | }
82 | }
83 | }
84 |
85 | /* Domain & Subdomain Definitions */
86 | Domain InsuranceDomain {
87 | Subdomain CustomerManagementDomain {
88 | type = CORE_DOMAIN
89 | domainVisionStatement = "Subdomain managing everything customer-related."
90 | }
91 | Subdomain PrintingDomain {
92 | type = SUPPORTING_DOMAIN
93 | domainVisionStatement = "Service (external system) to solve printing for all kinds of documents (debts, policies, etc.)"
94 | }
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-08-Extract-Shared-Kernel/README.md:
--------------------------------------------------------------------------------
1 | # AR-8 Extract Shared Kernel
2 | Extracts a new Bounded Context from a Shared Kernel relationship. It further established two upstream-downstream relationships
3 | so that the existing Bounded Context can use the 'shared' functionality.
4 |
5 | ## Context & Rationales
6 | The Shared Kernel pattern describes a close relationship between two Bounded Contexts which share a certain part of their domain
7 | models. The pattern is typically implemented as a shared library which is maintained by both teams. However, both teams depend on
8 | that shared code and each team has to deal with changes of the other one. If such a shared library gets very big and difficult to
9 | maintain it may be better to create a separate Bounded Context for it. A dedicated team may maintain the model within this new
10 | Bounded Context.
11 |
12 | ## Goal
13 | This Architectural Refactoring (AR) extracts a Shared Kernel into a new Bounded Context. The resulting Context Map will no
14 | longer contain the Shared Kernel relationship, but two new upstream-downstream relationships between the new and the existing
15 | two Bounded Contexts. This AR can be applied if a Shared Kernel gets big, difficult to maintain, and it may be better to have
16 | a new team maintaining this shared part of the domain model in a separate Bounded Context. This may increase the autonomy of
17 | all involved teams.
18 |
19 | ## Preconditions
20 | * Your model needs **at least two bounded contexts** which are in a **Shared Kernel** relationship.
21 |
22 | ## Input
23 | * The Shared Kernel relationship.
24 |
25 | ## Output
26 | * A new Bounded Context for the shared domain model parts and two new upstream-downstream relationships between the new and the
27 | existing two Bounded Contexts.
28 |
29 | ## Example
30 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
31 |
32 | ### Input
33 | The input Context Map:
34 | ```
35 | ContextMap InsuranceContextMap {
36 | type = SYSTEM_LANDSCAPE
37 | state = TO_BE
38 |
39 | contains PolicyManagementContext
40 | contains DebtCollection
41 |
42 | /* With a right-click on the Shared Kernel relationship ([SK]<->[SK]) you can execute the 'Extract Shared Kernel'
43 | * refactoring. It will create a new Bounded Context for the shared code (content of new Bounded Context has to
44 | * specified manually). Two new upstream-downstream relationships will be created to connect the existing Bounded
45 | * Contexts with the new one. After applying this AR, you can use the 'Rename Element' refactoring to change
46 | * the generated name of the new Bounded Context.
47 | */
48 | PolicyManagementContext [SK]<->[SK] DebtCollection {
49 | implementationTechnology = "Shared Java Library, Communication over RESTful HTTP"
50 | }
51 |
52 | }
53 |
54 | BoundedContext PolicyManagementContext {
55 | /* ... */
56 | }
57 |
58 | BoundedContext DebtCollection {
59 | /* ... */
60 | }
61 | ```
62 |
63 | ### Output
64 | Applying the AR **Extract Shared Kernel** removes the Shared Kernel relationship, creates a new Bounded Context for
65 | the shared domain model parts, and establishes two new upstream-downstream relationships between the new and the
66 | existing Bounded Contexts:
67 | ```
68 | ContextMap InsuranceContextMap {
69 | type = SYSTEM_LANDSCAPE
70 | state = TO_BE
71 |
72 | contains PolicyManagementContext
73 | contains DebtCollection
74 | contains PolicyManagementContext_DebtCollection_SharedKernel
75 |
76 | /* New relationships generated by the 'Extract Shared Kernel' AR: */
77 |
78 | PolicyManagementContext_DebtCollection_SharedKernel [ U ] -> [ D ] PolicyManagementContext
79 |
80 | PolicyManagementContext_DebtCollection_SharedKernel [ U ] -> [ D ] DebtCollection
81 |
82 | }
83 |
84 | BoundedContext PolicyManagementContext {
85 | /* ... */
86 | }
87 |
88 | BoundedContext DebtCollection {
89 | /* ... */
90 | }
91 |
92 | /* New Bounded Context generated by the 'Extract Shared Kernel' AR. After applying the AR, the Bounded Context can
93 | * be renamed with the 'Rename Element' refactoring. The user can further specify the comment parts here after applying
94 | * the AR (create new Aggregates and entities or move them from existing contexts to this one).
95 | */
96 | BoundedContext PolicyManagementContext_DebtCollection_SharedKernel
97 | ```
98 |
99 | ### Example Sources
100 | * Example input source: [example-input.cml](./example-input.cml)
101 | * Example output source: [example-output.cml](./example-output.cml)
102 |
103 | ## Further documentation
104 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
105 | * [AR-8 Extract Shared Kernel](https://contextmapper.org/docs/ar-extract-shared-kernel/)
106 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-08-Extract-Shared-Kernel/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Extract Shared Kernel' refactoring and shows a small part of the insurance example. */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 |
6 | contains PolicyManagementContext
7 | contains DebtCollection
8 |
9 | /* With a right-click on the Shared Kernel relationship ([SK]<->[SK]) you can execute the 'Extract Shared Kernel'
10 | * refactoring. It will create a new Bounded Context for the shared code (content of new Bounded Context has to
11 | * specified manually). Two new upstream-downstream relationships will be created to connect the existing Bounded
12 | * Contexts with the new one. After applying this AR, you can use the 'Rename Element' refactoring to change
13 | * the generated name of the new Bounded Context.
14 | */
15 | PolicyManagementContext [SK]<->[SK] DebtCollection {
16 | implementationTechnology = "Shared Java Library, Communication over RESTful HTTP"
17 | }
18 |
19 | }
20 |
21 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
22 | type = FEATURE
23 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
24 | responsibilities = "Offers, Contracts, Policies"
25 | implementationTechnology = "Java, Spring App"
26 |
27 | Aggregate Offers {
28 | Entity Offer {
29 | aggregateRoot
30 | int offerId
31 | Customer client
32 | - List products
33 | BigDecimal price
34 | }
35 | }
36 | Aggregate Products {
37 | Entity Product {
38 | aggregateRoot
39 | - ProductId identifier
40 | String productName
41 | }
42 | ValueObject ProductId {
43 | int productId key
44 | }
45 | }
46 | Aggregate Contract {
47 | Entity Contract {
48 | aggregateRoot
49 | - ContractId identifier
50 | Customer client
51 | - List products
52 | }
53 | ValueObject ContractId {
54 | int contractId key
55 | }
56 |
57 | Entity Policy {
58 | int policyNr
59 | - Contract contract
60 | BigDecimal price
61 | }
62 | }
63 | }
64 |
65 | BoundedContext DebtCollection implements DebtsDomain {
66 | type = FEATURE
67 | domainVisionStatement = "The debt collection context is responsible for the financial income of the insurance company (the debts) which depend on the corresponding contracts and policies."
68 | responsibilities = "Debts, Dunning"
69 | implementationTechnology = "JEE"
70 |
71 | Aggregate Debts {
72 | Entity Debt {
73 | aggregateRoot
74 | int debtNr
75 | - Policy policy
76 | Date creationDate
77 | Date paymentDate
78 | Date paymentDeadline
79 | BigDecimal price
80 | PaymentStatus status
81 | - List dunnigs
82 | }
83 | Entity Dunning {
84 | int dunningNr
85 | - Debt debt
86 | Date dunningDate
87 | Date paymentDeadline
88 | }
89 | }
90 | }
91 |
92 | /* Domain & Subdomain Definitions */
93 | Domain InsuranceDomain {
94 | Subdomain PolicyManagementDomain {
95 | type = CORE_DOMAIN
96 | domainVisionStatement = "Subdomain managing contracts and policies."
97 | }
98 | Subdomain DebtsDomain {
99 | type = GENERIC_SUBDOMAIN
100 | domainVisionStatement = "Subomain including everything related to the incoming money (debts, dunning, etc.)"
101 | }
102 | }
103 |
104 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-08-Extract-Shared-Kernel/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Extract Shared Kernel' refactoring and shows a small part of the insurance example. */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 |
6 | contains PolicyManagementContext
7 | contains DebtCollection
8 | contains PolicyManagementContext_DebtCollection_SharedKernel
9 |
10 | /* New relationships generated by the 'Extract Shared Kernel' AR: */
11 |
12 | PolicyManagementContext_DebtCollection_SharedKernel [ U ] -> [ D ] PolicyManagementContext
13 |
14 | PolicyManagementContext_DebtCollection_SharedKernel [ U ] -> [ D ] DebtCollection
15 |
16 | }
17 |
18 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
19 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
20 | responsibilities = "Offers, Contracts, Policies"
21 | implementationTechnology = "Java, Spring App"
22 |
23 | Aggregate Offers {
24 | Entity Offer {
25 | aggregateRoot
26 | int offerId
27 | Customer client
28 | - List products
29 | BigDecimal price
30 | }
31 | }
32 | Aggregate Products {
33 | Entity Product {
34 | aggregateRoot
35 | - ProductId identifier
36 | String productName
37 | }
38 | ValueObject ProductId {
39 | int productId key
40 | }
41 | }
42 | Aggregate Contract {
43 | Entity Contract {
44 | aggregateRoot
45 | - ContractId identifier
46 | Customer client
47 | - List products
48 | }
49 | ValueObject ContractId {
50 | int contractId key
51 | }
52 |
53 | Entity Policy {
54 | int policyNr
55 | - Contract contract
56 | BigDecimal price
57 | }
58 | }
59 | }
60 |
61 | BoundedContext DebtCollection implements DebtsDomain {
62 | domainVisionStatement = "The debt collection context is responsible for the financial income of the insurance company (the debts) which depend on the corresponding contracts and policies."
63 | responsibilities = "Debts, Dunning"
64 | implementationTechnology = "JEE"
65 |
66 | Aggregate Debts {
67 | Entity Debt {
68 | aggregateRoot
69 | int debtNr
70 | - Policy policy
71 | Date creationDate
72 | Date paymentDate
73 | Date paymentDeadline
74 | BigDecimal price
75 | PaymentStatus status
76 | - List dunnigs
77 | }
78 | Entity Dunning {
79 | int dunningNr
80 | - Debt debt
81 | Date dunningDate
82 | Date paymentDeadline
83 | }
84 | }
85 | }
86 |
87 | /* New Bounded Context generated by the 'Extract Shared Kernel' AR. After applying the AR, the Bounded Context can
88 | * be renamed with the 'Rename Element' refactoring. The user can further specify the comment parts here after applying
89 | * the AR (create new Aggregates and entities or move them from existing contexts to this one).
90 | */
91 | // Extracted Bounded Context for Shared Kernel. Please specify the kernel model here:
92 | BoundedContext PolicyManagementContext_DebtCollection_SharedKernel {
93 | Aggregate SharedKernelAggregate {
94 | Entity SharedKernelRoot {
95 | aggregateRoot
96 | }
97 | }
98 | }
99 |
100 | /* Domain & Subdomain Definitions */
101 | Domain InsuranceDomain {
102 | Subdomain PolicyManagementDomain {
103 | type = CORE_DOMAIN
104 | domainVisionStatement = "Subdomain managing contracts and policies."
105 | }
106 | Subdomain DebtsDomain {
107 | type = GENERIC_SUBDOMAIN
108 | domainVisionStatement = "Subomain including everything related to the incoming money (debts, dunning, etc.)"
109 | }
110 | }
111 |
112 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-09-Suspend-Partnership/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Suspend Partnership' refactoring and shows a small part of the insurance example. */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 |
6 | contains PolicyManagementContext
7 | contains RiskManagementContext
8 |
9 | /* With a right-click on the Partnership relationship ([P]<->[P]) you can execute the 'Suspend Partnership'
10 | * refactoring. On a dialog you can then choose between three modes how to suspend the partnership:
11 | * a) Merge the two Bounded Contexts (executes 'AR-7 Merge Bounded Contexts').
12 | * b) Extract a new Bounded Context for commonalities and establish upstream-downstream relationships between
13 | * the new and the existing two Bounded Contexts.
14 | * c) Simply replace the Partnership relationship with an upstream-downstream relationship (in this case
15 | * you have to choose which Bounded Context becomes upstream context).
16 | */
17 | RiskManagementContext [P]<->[P] PolicyManagementContext {
18 | implementationTechnology = "RabbitMQ"
19 | }
20 |
21 | }
22 |
23 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
24 | type = FEATURE
25 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
26 | responsibilities = "Offers, Contracts, Policies"
27 | implementationTechnology = "Java, Spring App"
28 |
29 | Aggregate Offers {
30 | Entity Offer {
31 | aggregateRoot
32 | int offerId
33 | Customer client
34 | - List products
35 | BigDecimal price
36 | }
37 | }
38 | Aggregate Products {
39 | Entity Product {
40 | aggregateRoot
41 | - ProductId identifier
42 | String productName
43 | }
44 | ValueObject ProductId {
45 | int productId key
46 | }
47 | }
48 | Aggregate Contract {
49 | Entity Contract {
50 | aggregateRoot
51 | - ContractId identifier
52 | Customer client
53 | - List products
54 | }
55 | ValueObject ContractId {
56 | int contractId key
57 | }
58 |
59 | Entity Policy {
60 | int policyNr
61 | - Contract contract
62 | BigDecimal price
63 | }
64 | }
65 | }
66 |
67 | BoundedContext RiskManagementContext implements RiskManagementDomain {
68 | type = FEATURE
69 | domainVisionStatement = "Uses data from PolicyManagement context to calculate risks."
70 | responsibilities = "Customer Risk Calculation"
71 | implementationTechnology = "Java, Spring App"
72 |
73 | Aggregate Risks {
74 | Entity CustomerRiskFactor {
75 | aggregateRoot
76 | int totalRiskFactor
77 | - List risks
78 | Customer client
79 | }
80 | ValueObject Risk {
81 | int likelihood
82 | String risk
83 | }
84 | }
85 | }
86 |
87 | /* Domain & Subdomain Definitions */
88 | Domain InsuranceDomain {
89 | Subdomain PolicyManagementDomain {
90 | type = CORE_DOMAIN
91 | domainVisionStatement = "Subdomain managing contracts and policies."
92 | }
93 | Subdomain RiskManagementDomain {
94 | type = GENERIC_SUBDOMAIN
95 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-09-Suspend-Partnership/example-output-a.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Suspend Partnership' refactoring and shows a small part of the insurance example.
2 | *
3 | * In this case we selected to MERGE the Bounded Contexts to suspend the partnership.
4 | */
5 | ContextMap InsuranceContextMap {
6 | type = SYSTEM_LANDSCAPE
7 | state = TO_BE
8 |
9 | contains RiskManagementContext
10 |
11 | /* Since the AR merged the two Bounded Context, the relationship has been removed. */
12 | }
13 |
14 | /* The merged Bounded Context contains all Aggregates of both contexts now. It further implements both Subdomains. */
15 | BoundedContext RiskManagementContext implements RiskManagementDomain , PolicyManagementDomain {
16 | domainVisionStatement "Uses data from PolicyManagement context to calculate risks."
17 | responsibilities = "Customer Risk Calculation", "Offers, Contracts, Policies"
18 | implementationTechnology "Java, Spring App"
19 |
20 | Aggregate Risks {
21 | Entity CustomerRiskFactor {
22 | aggregateRoot
23 | int totalRiskFactor
24 | - List risks
25 | Customer client
26 | }
27 | ValueObject Risk {
28 | int likelihood
29 | String risk
30 | }
31 | }
32 | Aggregate Offers {
33 | Entity Offer {
34 | aggregateRoot
35 | int offerId
36 | Customer client
37 | - List products
38 | BigDecimal price
39 | }
40 | }
41 | Aggregate Products {
42 | Entity Product {
43 | aggregateRoot
44 | - ProductId identifier
45 | String productName
46 | }
47 | ValueObject ProductId {
48 | int productId key
49 | }
50 | }
51 | Aggregate Contract {
52 | Entity Contract {
53 | aggregateRoot
54 | - ContractId identifier
55 | Customer client
56 | - List products
57 | }
58 | ValueObject ContractId {
59 | int contractId key
60 | }
61 |
62 | Entity Policy {
63 | int policyNr
64 | - Contract contract
65 | BigDecimal price
66 | }
67 | }
68 | }
69 |
70 | /* Domain & Subdomain Definitions */
71 | Domain InsuranceDomain {
72 | Subdomain PolicyManagementDomain {
73 | type = CORE_DOMAIN
74 | domainVisionStatement = "Subdomain managing contracts and policies."
75 | }
76 | Subdomain RiskManagementDomain {
77 | type = GENERIC_SUBDOMAIN
78 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-09-Suspend-Partnership/example-output-b.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Suspend Partnership' refactoring and shows a small part of the insurance example.
2 | *
3 | * In this case we selected to EXTRACT a new Bounded Contexts for commonalities to suspend the partnership.
4 | */
5 | ContextMap InsuranceContextMap {
6 | type = SYSTEM_LANDSCAPE
7 | state = TO_BE
8 |
9 | contains PolicyManagementContext
10 | contains RiskManagementContext
11 | contains RiskManagementContext_PolicyManagementContext_Partnership
12 |
13 | /* New upstream-downstream relationships between the new and the existing two Bounded Contexts: */
14 |
15 | RiskManagementContext_PolicyManagementContext_Partnership [ U ] -> [ D ] RiskManagementContext
16 |
17 | RiskManagementContext_PolicyManagementContext_Partnership [ U ] -> [ D ] PolicyManagementContext
18 |
19 | }
20 |
21 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
22 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
23 | responsibilities = "Offers, Contracts, Policies"
24 | implementationTechnology = "Java, Spring App"
25 |
26 | Aggregate Offers {
27 | Entity Offer {
28 | aggregateRoot
29 | int offerId
30 | Customer client
31 | - List products
32 | BigDecimal price
33 | }
34 | }
35 | Aggregate Products {
36 | Entity Product {
37 | aggregateRoot
38 | - ProductId identifier
39 | String productName
40 | }
41 | ValueObject ProductId {
42 | int productId key
43 | }
44 | }
45 | Aggregate Contract {
46 | Entity Contract {
47 | aggregateRoot
48 | - ContractId identifier
49 | Customer client
50 | - List products
51 | }
52 | ValueObject ContractId {
53 | int contractId key
54 | }
55 |
56 | Entity Policy {
57 | int policyNr
58 | - Contract contract
59 | BigDecimal price
60 | }
61 | }
62 | }
63 |
64 | BoundedContext RiskManagementContext implements RiskManagementDomain {
65 | domainVisionStatement = "Uses data from PolicyManagement context to calculate risks."
66 | responsibilities = "Customer Risk Calculation"
67 | implementationTechnology = "Java, Spring App"
68 |
69 | Aggregate Risks {
70 | Entity CustomerRiskFactor {
71 | aggregateRoot
72 | int totalRiskFactor
73 | - List risks
74 | Customer client
75 | }
76 | ValueObject Risk {
77 | int likelihood
78 | String risk
79 | }
80 | }
81 | }
82 |
83 | /* The new Bounded Context created by the 'Suspend Partnership' refactoring:
84 | * (can be renamed with the 'Rename Element' refactoring)
85 | */
86 | // Extracted Bounded Context for common model parts. Please specify the common model here:
87 | BoundedContext RiskManagementContext_PolicyManagementContext_Partnership {
88 | Aggregate CommonModelAggregate {
89 | Entity CommonModelPartRoot {
90 | aggregateRoot
91 | }
92 | }
93 | }
94 |
95 | /* Domain & Subdomain Definitions */
96 | Domain InsuranceDomain {
97 | Subdomain PolicyManagementDomain {
98 | type = CORE_DOMAIN
99 | domainVisionStatement = "Subdomain managing contracts and policies."
100 | }
101 | Subdomain RiskManagementDomain {
102 | type = GENERIC_SUBDOMAIN
103 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-09-Suspend-Partnership/example-output-c.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Suspend Partnership' refactoring and shows a small part of the insurance example.
2 | *
3 | * In this case we selected to REPLACE the partnership with an upstream-downstream relationship.
4 | */
5 | ContextMap InsuranceContextMap {
6 | type = SYSTEM_LANDSCAPE
7 | state = TO_BE
8 |
9 | contains PolicyManagementContext
10 | contains RiskManagementContext
11 |
12 | /* The new upstream-downstream relationship replacing the original Partnership relationship: */
13 |
14 | PolicyManagementContext [ U ] -> [ D ] RiskManagementContext
15 |
16 | }
17 |
18 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
19 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
20 | responsibilities = "Offers, Contracts, Policies"
21 | implementationTechnology = "Java, Spring App"
22 |
23 | Aggregate Offers {
24 | Entity Offer {
25 | aggregateRoot
26 | int offerId
27 | Customer client
28 | - List products
29 | BigDecimal price
30 | }
31 | }
32 | Aggregate Products {
33 | Entity Product {
34 | aggregateRoot
35 | - ProductId identifier
36 | String productName
37 | }
38 | ValueObject ProductId {
39 | int productId key
40 | }
41 | }
42 | Aggregate Contract {
43 | Entity Contract {
44 | aggregateRoot
45 | - ContractId identifier
46 | Customer client
47 | - List products
48 | }
49 | ValueObject ContractId {
50 | int contractId key
51 | }
52 |
53 | Entity Policy {
54 | int policyNr
55 | - Contract contract
56 | BigDecimal price
57 | }
58 | }
59 | }
60 |
61 | BoundedContext RiskManagementContext implements RiskManagementDomain {
62 | domainVisionStatement = "Uses data from PolicyManagement context to calculate risks."
63 | responsibilities = "Customer Risk Calculation"
64 | implementationTechnology = "Java, Spring App"
65 |
66 | Aggregate Risks {
67 | Entity CustomerRiskFactor {
68 | aggregateRoot
69 | int totalRiskFactor
70 | - List risks
71 | Customer client
72 | }
73 | ValueObject Risk {
74 | int likelihood
75 | String risk
76 | }
77 | }
78 | }
79 |
80 | /* Domain & Subdomain Definitions */
81 | Domain InsuranceDomain {
82 | Subdomain PolicyManagementDomain {
83 | type = CORE_DOMAIN
84 | domainVisionStatement = "Subdomain managing contracts and policies."
85 | }
86 | Subdomain RiskManagementDomain {
87 | type = GENERIC_SUBDOMAIN
88 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-10-Change-Shared-Kernel-To-Partnership/README.md:
--------------------------------------------------------------------------------
1 | # AR-10 Change Shared Kernel to Partnership
2 | This simple relationship refactoring changes a Shared Kernel relationship on a Context Map to a Partnership relationship.
3 |
4 | ## Summary
5 | Our relationship refactorings allow the user/modeller to change the type of a relationship on a Context Map easily without manual work.
6 | The symmetric relationships according to our [semantic model](/docs/language-model/), Shared Kernel and Partnership, are interchangeable without impacts
7 | to the structure of the decomposition. This refactoring changes a Shared Kernel relationship to a Partnership relationship.
8 |
9 | **Inverse AR:**
10 | * [AR-11: Change Partnership to Shared Kernel](./../AR-11-Change-Partnership-To-Shared-Kernel)
11 |
12 | ## Example
13 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
14 |
15 | ### Input
16 | The input Context Map:
17 | ```
18 | ContextMap InsuranceContextMap {
19 | type = SYSTEM_LANDSCAPE
20 | state = TO_BE
21 | contains PolicyManagementContext
22 | contains DebtCollection
23 |
24 | /* With a right-click on the Shared Kernel relationship ([SK]<->[SK]) you can execute the 'Change to Partnership'
25 | * refactoring. It will replace the Shared Kernel relationship below with a corresponding Partnership relationship
26 | * between the two Bounded Contexts.
27 | */
28 | PolicyManagementContext [SK]<->[SK] DebtCollection
29 |
30 | }
31 |
32 | BoundedContext PolicyManagementContext
33 |
34 | BoundedContext DebtCollection
35 | ```
36 |
37 | ### Output
38 | Applying the AR **Change Shared Kernel to Partnership** replaces the existing Shared Kernel relationship with a
39 | Partnership relationship:
40 | ```
41 | ContextMap InsuranceContextMap {
42 | type = SYSTEM_LANDSCAPE
43 | state = TO_BE
44 | contains PolicyManagementContext
45 | contains DebtCollection
46 |
47 | /* The new Partnership relationship after applying the 'Change Shared Kernel to Partnership' refactoring to the
48 | * Shared Kernel within the 'example-input.cml' file:
49 | */
50 | PolicyManagementContext [P] <-> [P] DebtCollection
51 |
52 | }
53 |
54 | BoundedContext PolicyManagementContext
55 |
56 | BoundedContext DebtCollection
57 | ```
58 |
59 | ### Example Sources
60 | * Example input source: [example-input.cml](./example-input.cml)
61 | * Example output source: [example-output.cml](./example-output.cml)
62 |
63 | ## Further documentation
64 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
65 | * [AR-10 Change Shared Kernel to Partnership](https://contextmapper.org/docs/ar-change-shared-kernel-to-partnership/)
66 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-10-Change-Shared-Kernel-To-Partnership/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Change Shared Kernel to Partnership' refactoring and shows a small part of the insurance example. */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 | contains PolicyManagementContext
6 | contains DebtCollection
7 |
8 | /* With a right-click on the Shared Kernel relationship ([SK]<->[SK]) you can execute the 'Change to Partnership'
9 | * refactoring. It will replace the Shared Kernel relationship below with a corresponding Partnership relationship
10 | * between the two Bounded Contexts.
11 | */
12 | PolicyManagementContext [SK]<->[SK] DebtCollection
13 |
14 | }
15 |
16 | BoundedContext PolicyManagementContext
17 |
18 | BoundedContext DebtCollection
19 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-10-Change-Shared-Kernel-To-Partnership/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Change Shared Kernel to Partnership' refactoring and shows a small part of the insurance example. */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 | contains PolicyManagementContext
6 | contains DebtCollection
7 |
8 | /* The new Partnership relationship after applying the 'Change Shared Kernel to Partnership' refactoring to the
9 | * Shared Kernel within the 'example-input.cml' file:
10 | */
11 | PolicyManagementContext [P] <-> [P] DebtCollection
12 |
13 | }
14 |
15 | BoundedContext PolicyManagementContext
16 |
17 | BoundedContext DebtCollection
18 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-11-Change-Partnership-To-Shared-Kernel/README.md:
--------------------------------------------------------------------------------
1 | # AR-11 Change Partnership to Shared Kernel
2 | This simple relationship refactoring changes a Partnership relationship on a Context Map to a Shared Kernel relationship.
3 |
4 | ## Summary
5 | Our relationship refactorings allow the user/modeller to change the type of a relationship on a Context Map easily without manual work.
6 | The symmetric relationships according to our [semantic model](/docs/language-model/), Shared Kernel and Partnership, are interchangeable without impacts
7 | to the structure of the decomposition. This refactoring changes a Partnership relationship to a Shared Kernel relationship.
8 |
9 | **Inverse AR:**
10 | * [AR-10: Change Shared Kernel to Partnership](./../AR-10-Change-Shared-Kernel-To-Partnership)
11 |
12 | ## Example
13 | The following two CML snippets show an example _input_ and _output_ illustrating how this AR works.
14 |
15 | ### Input
16 | The input Context Map:
17 | ```
18 | ContextMap InsuranceContextMap {
19 | type = SYSTEM_LANDSCAPE
20 | state = TO_BE
21 | contains PolicyManagementContext
22 | contains RiskManagementContext
23 |
24 | /* With a right-click on the Partnership relationship ([P]<->[P]) you can execute the 'Change to Shared Kernel'
25 | * refactoring. It will replace the Partnership relationship below with a corresponding Shared Kernel relationship
26 | * between the two Bounded Contexts.
27 | */
28 | RiskManagementContext [P]<->[P] PolicyManagementContext
29 |
30 | }
31 |
32 | BoundedContext PolicyManagementContext
33 |
34 | BoundedContext RiskManagementContext
35 | ```
36 |
37 | ### Output
38 | Applying the AR **Change Partnership to Shared Kernel** replaces the existing Partnership relationship with a
39 | Shared Kernel relationship:
40 | ```
41 | ContextMap InsuranceContextMap {
42 | type = SYSTEM_LANDSCAPE
43 | state = TO_BE
44 | contains PolicyManagementContext
45 | contains RiskManagementContext
46 |
47 | /* The new Shared Kernel relationship after applying the 'Change Partnership to Shared Kernel' refactoring to the
48 | * Partnership within the 'example-input.cml' file:
49 | */
50 | RiskManagementContext [SK] <-> [SK] PolicyManagementContext
51 |
52 | }
53 |
54 | BoundedContext PolicyManagementContext
55 |
56 | BoundedContext RiskManagementContext
57 | ```
58 |
59 | ### Example Sources
60 | * Example input source: [example-input.cml](./example-input.cml)
61 | * Example output source: [example-output.cml](./example-output.cml)
62 |
63 | ## Further documentation
64 | * Context Mapper [Architectural Refactorings (ARs)](https://contextmapper.org/docs/architectural-refactorings/)
65 | * [AR-11 Change Partnership to Shared Kernel](https://contextmapper.org/docs/ar-change-partnership-to-shared-kernel/)
66 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-11-Change-Partnership-To-Shared-Kernel/example-input.cml:
--------------------------------------------------------------------------------
1 | /* This is an example input file for the 'Change Partnership to Shared Kernel' refactoring and shows a small part of the insurance example. */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 | contains PolicyManagementContext
6 | contains RiskManagementContext
7 |
8 | /* With a right-click on the Partnership relationship ([P]<->[P]) you can execute the 'Change to Shared Kernel'
9 | * refactoring. It will replace the Partnership relationship below with a corresponding Shared Kernel relationship
10 | * between the two Bounded Contexts.
11 | */
12 | RiskManagementContext [P]<->[P] PolicyManagementContext
13 |
14 | }
15 |
16 | BoundedContext PolicyManagementContext
17 |
18 | BoundedContext RiskManagementContext
19 |
--------------------------------------------------------------------------------
/src/main/cml/architectural-refactorings/AR-11-Change-Partnership-To-Shared-Kernel/example-output.cml:
--------------------------------------------------------------------------------
1 | /* This is an example output file for the 'Change Partnership to Shared Kernel' refactoring and shows a small part of the insurance example. */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 | contains PolicyManagementContext
6 | contains RiskManagementContext
7 |
8 | /* The new Shared Kernel relationship after applying the 'Change Partnership to Shared Kernel' refactoring to the
9 | * Partnership within the 'example-input.cml' file:
10 | */
11 | RiskManagementContext [SK] <-> [SK] PolicyManagementContext
12 |
13 | }
14 |
15 | BoundedContext PolicyManagementContext
16 |
17 | BoundedContext RiskManagementContext
18 |
--------------------------------------------------------------------------------
/src/main/cml/bounded-context-canvas-example/Bounded-Context-Canvas-Example-Stage-1.cml:
--------------------------------------------------------------------------------
1 | /* Example Context Map written using a Bounded Context Canvas. */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 |
6 | /* Add bounded contexts to this context map: */
7 | contains CustomerManagementContext
8 | }
9 |
10 | /* Domain & Subdomain Definitions */
11 | Domain InsuranceDomain {
12 | Subdomain CustomerManagementDomain {
13 | type = CORE_DOMAIN
14 | domainVisionStatement = "Subdomain managing everything customer-related."
15 | }
16 | }
17 |
18 | /* Bounded Context Definitions */
19 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
20 | businessModel = "ENGAGEMENT"
21 | evolution = CUSTOM_BUILT
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/cml/bounded-context-canvas-example/README.md:
--------------------------------------------------------------------------------
1 | # Bounded Context Canvas Example
2 |
3 | This example illustrates the Context Mapper DSL capabilities to support Bounded Context canvases.
4 | Full support is a _work in progress_.
5 |
6 |
7 | Please see the [bounded context canvas example](Bounded-Context-Canvas-Example-Stage-1.cml).
8 |
--------------------------------------------------------------------------------
/src/main/cml/context-mapper-example/ContextMapper-Example-Stage-1.cml:
--------------------------------------------------------------------------------
1 | ContextMap ContextMapper {
2 | contains LanguageCore, ArchitecturalRefactorings, StructuredServiceDecomposition, DiscoveryLibrary, Generators
3 |
4 | LanguageCore -> DiscoveryLibrary
5 |
6 | LanguageCore <- StructuredServiceDecomposition
7 |
8 | LanguageCore -> Generators
9 |
10 | LanguageCore <-> ArchitecturalRefactorings
11 |
12 | }
13 |
14 | BoundedContext LanguageCore
15 |
16 | BoundedContext ArchitecturalRefactorings
17 |
18 | BoundedContext StructuredServiceDecomposition
19 |
20 | BoundedContext DiscoveryLibrary
21 |
22 | BoundedContext Generators
23 |
--------------------------------------------------------------------------------
/src/main/cml/context-mapper-example/ContextMapper-Example-Stage-2.cml:
--------------------------------------------------------------------------------
1 | ContextMap ContextMapper {
2 | contains LanguageCore, ArchitecturalRefactorings, StructuredServiceDecomposition, DiscoveryLibrary, Generators
3 |
4 | /**
5 | * Pattern selection:
6 | * ==================
7 | *
8 | * The language core (CML language) provides a Published Language (PL) allowing to describe software systems
9 | * in terms of DDD patterns. This PL is used by the other components. Since its not a public API (REST, Messaging,
10 | * or similar) we haven't added the Open Host Service (OHS) pattern.
11 | *
12 | *
13 | * The discovery library conforms to the model provided by the language core (we always generate CML models
14 | * according to the core). The generators and on the other hand may also influence the language sometimes.
15 | * The core further uses the API of our Service Cutter library to generate new decompositions.
16 | */
17 |
18 | LanguageCore [PL]->[CF] DiscoveryLibrary
19 |
20 | LanguageCore [ACL]<-[OHS,PL] StructuredServiceDecomposition
21 |
22 | LanguageCore [PL]-> Generators
23 |
24 | /* The refactorings are tightly coupled with the language. In this case the semantic model of the language
25 | * can be seen as a Shared Kernel:
26 | */
27 | LanguageCore [SK]<->[SK] ArchitecturalRefactorings
28 |
29 | }
30 |
31 | BoundedContext LanguageCore
32 |
33 | BoundedContext ArchitecturalRefactorings
34 |
35 | BoundedContext StructuredServiceDecomposition
36 |
37 | BoundedContext DiscoveryLibrary
38 |
39 | BoundedContext Generators
40 |
--------------------------------------------------------------------------------
/src/main/cml/context-mapper-example/ContextMapper-Example-Stage-3.cml:
--------------------------------------------------------------------------------
1 | ContextMap ContextMapper {
2 | contains LanguageCore, ArchitecturalRefactorings, StructuredServiceDecomposition, DiscoveryLibrary, Generators
3 |
4 | /**
5 | * Pattern selection:
6 | * ==================
7 | *
8 | * The language core (CML language) provides a Published Language (PL) allowing to describe software systems
9 | * in terms of DDD patterns. This PL is used by the other components. Since its not a public API (REST, Messaging,
10 | * or similar) we haven't added the Open Host Service (OHS) pattern.
11 | *
12 | *
13 | * The discovery library conforms to the model provided by the language core (we always generate CML models
14 | * according to the core). The generators and on the other hand may also influence the language sometimes.
15 | * The core further uses the API of our Service Cutter library to generate new decompositions.
16 | */
17 |
18 | LanguageCore [PL]->[CF] DiscoveryLibrary
19 |
20 | LanguageCore [ACL]<-[OHS,PL] StructuredServiceDecomposition
21 |
22 | LanguageCore [PL]-> Generators
23 |
24 | /* The refactorings are tightly coupled with the language. In this case the semantic model of the language
25 | * can be seen as a Shared Kernel:
26 | */
27 | LanguageCore [SK]<->[SK] ArchitecturalRefactorings
28 |
29 | }
30 |
31 | BoundedContext LanguageCore {
32 | domainVisionStatement "Provides the Context Mapper DSL (CML) modeling language to express architectures on the basis of Strategic Domain-driven Design (DDD) patterns."
33 |
34 | Aggregate StrategicDesign
35 |
36 | Aggregate TacticDesign
37 |
38 | }
39 |
40 | BoundedContext ArchitecturalRefactorings {
41 | domainVisionStatement "Architectural Refactorings (ARs) allow to improve the architecture model iteratively."
42 |
43 | Aggregate StructuralRefactorings
44 |
45 | Aggregate RelationshipRefactorings
46 | }
47 |
48 | BoundedContext StructuredServiceDecomposition {
49 | domainVisionStatement "The Service Cutter integration into Context Mapper allows to analyze the Context Map with respect to coupling criteria and supports to suggest improved Context Maps."
50 |
51 | Aggregate ERDModel // input
52 |
53 | Aggregate UserRepresentations // input
54 |
55 | Aggregate CouplingCriteria // service decomposition process
56 |
57 | Aggregate GraphClusteringAlgorithms // service decomposition process
58 |
59 | Aggregate ServiceDecompositions // output
60 |
61 | }
62 |
63 | BoundedContext DiscoveryLibrary {
64 | domainVisionStatement "The reverse engineering component can generate CML Context Maps from existing source code. This allows to reverse engineer the architecture model in projects with existing monoliths or microservices."
65 |
66 | Aggregate BoundedContextDiscoveryStrategies
67 |
68 | Aggregate RelationshipDiscoveryStrategies
69 | }
70 |
71 | BoundedContext Generators {
72 | domainVisionStatement "The generators allow to generate other representations of the architecture derived by a given CML Context Map."
73 |
74 | Aggregate GraphicalGenerators
75 |
76 | Aggregate ServiceContractsGenerators // generate (micro-)service generators
77 |
78 | Aggregate ServiceCutterGenerators // generate ServiceCutter input files
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/cml/context-mapper-example/README.md:
--------------------------------------------------------------------------------
1 | # Context Mapper Example
2 |
3 | This example is illustrates the Context Mapper DSL capabilities on the basis of the [Context Mapper framework](https://contextmapper.org/docs/home/) itself.
4 |
5 | Within this folder we modeled our own tool with the CML language as part of our validation activities. The following figure (generated with our [Context Map generator](https://contextmapper.org/docs/context-map-generator/)) illustrates the context map of our framework:
6 |
7 |
8 |
9 | Here you can find the corresponding context map in CML (Context Mapper Language) in different versions and levels of detail (stages):
10 |
11 | * [ContextMapper-Example-Stage-1](./ContextMapper-Example-Stage-1.cml): A simple context map without relationship patterns in upstream-downstream relationships and without details of the bounded contexts.
12 | * [ContextMapper-Example-Stage-2](./ContextMapper-Example-Stage-2.cml): This stage refines the relationships on the context map and adds the corresponding DDD relationship patterns.
13 | * [ContextMapper-Example-Stage-3](./ContextMapper-Example-Stage-3.cml): In stage three we added first details to the bounded contexts and specified the aggregates.
14 | * [ContextMapper-Example-Stage-4](./ContextMapper-Example-Stage-4.cml): A simple version including all domain objects but no attributes. This stage should still be understandable for users without technical knowledge.
15 |
--------------------------------------------------------------------------------
/src/main/cml/context-mapper-example/ServiceCutterLibraryContract.mdsl:
--------------------------------------------------------------------------------
1 | API description ServiceCutterLibraryAPI
2 | usage context PUBLIC_API for BACKEND_INTEGRATION
3 |
4 | // input model (Entity Relation Diagram & User Representations)
5 | data type EntityRelationshipDiagram { "name":D, "entities":{ "name":D, "nanoentities":D* }*, "relations":{ "origin":{ "name":D, "nanoentities":D* }, "destination":{ "name":D, "nanoentities":D* }, "relationType":RelationType }* }
6 | data type UserRepresentations { "useCases":{ "name":D, "nanoentitiesRead":D*, "nanoentitiesWritten":D*, "latencyCritical":D }*, "compatibilities":{ "contentVolatility":{ "characteristic":D, "nanoentities":D* }*, "structuralVolatility":{ "characteristic":D, "nanoentities":D* }*, "availabilityCriticality":{ "characteristic":D, "nanoentities":D* }*, "consistencyCriticality":{ "characteristic":D, "nanoentities":D* }*, "storageSimilarity":{ "characteristic":D, "nanoentities":D* }*, "securityCriticality":{ "characteristic":D, "nanoentities":D* }* }* }
7 | data type RelationType { "AGGREGATION" | "COMPOSITION" | "INHERITANCE" }
8 |
9 | // Service cutting context built by input and coupling criteria
10 | data type ServiceCutterContext { "systemName":D, "criteriaCatalog":CouplingCriteriaCatalog, "couplingInstances":CouplingInstance*, "nanoEntities":D*, "solverConfiguration":SolverConfiguration }
11 | data type CouplingCriteriaCatalog P // not specified in detail due to complexity
12 | data type CouplingInstance P // not specified in detail due to complexity
13 |
14 | // Solver configuration provided by user (algorithm and priorities)
15 | data type SolverConfiguration { "algorithm":D, "solverPriorities":{ "criterion":D, "priority":SolverPriority }* }
16 | data type SolverPriority { "IGNORE" | "XS" | "S" | "M" | "L" | "XL" | "XXL" }
17 |
18 | // Cutting result provided by Service Cutter
19 | data type SolverResult { "services":{ "nanoentities":D*, "id":Char }*, "relations":{ "serviceA":D, "serviceB":D, "sharedEntities":D*, "direction":Direction }* }
20 | data type Direction { "OUTGOING" | "INCOMING" | "BIDIRECTIONAL" }
21 | data type Char P // no char primitive type in MDSL
22 |
23 | endpoint type ServiceCutterContextBuilder // stateful type
24 | exposes
25 | operation ServiceCutterContextBuilder // constructor
26 | expecting
27 | payload EntityRelationshipDiagram
28 | operation withUserRepresentations // provide user representations (optionally)
29 | expecting
30 | payload UserRepresentations
31 | operation withCustomSolverConfiguration // change solver configuration (optionally)
32 | expecting
33 | payload SolverConfiguration
34 | operation build // build the context
35 | delivering
36 | payload ServiceCutterContext
37 |
38 | endpoint type SolverConfigurationFactory
39 | exposes
40 | operation createDefaultConfiguration // create initial/default solver configuration
41 | delivering
42 | payload SolverConfiguration
43 |
44 | endpoint type ServiceCutter
45 | exposes
46 | operation generateDecomposition // decompose the system with the provided context
47 | expecting
48 | payload ServiceCutterContext
49 | delivering
50 | payload SolverResult
51 |
52 |
53 | API provider ServiceCutterLibrary
54 | offers ServiceCutterContextBuilder
55 | offers SolverConfigurationFactory
56 | offers ServiceCutter
57 |
58 | API client LanguageCore
59 | consumes ServiceCutterContextBuilder
60 | consumes SolverConfigurationFactory
61 | consumes ServiceCutter
62 |
63 | IPA
--------------------------------------------------------------------------------
/src/main/cml/context-mapper-example/images/ContextMapper-Example-Simple_ComponentDiagram.puml:
--------------------------------------------------------------------------------
1 | @startuml
2 | skinparam componentStyle uml2
3 |
4 | component [LanguageCore]
5 | note top of [LanguageCore]
6 | Provides the Context Mapper DSL
7 | (CML) modeling language to express
8 | architectures on the basis of
9 | Strategic Domain-driven Design
10 | (DDD) patterns.
11 | end note
12 |
13 | component [ArchitecturalRefactorings]
14 | note bottom of [ArchitecturalRefactorings]
15 | Architectural Refactorings (ARs)
16 | allow to improve the architecture
17 | model iteratively.
18 | end note
19 |
20 | component [StructuredServiceDecomposition]
21 | note bottom of [StructuredServiceDecomposition]
22 | The Service Cutter integration into Context
23 | Mapper allows to analyze the Context Map
24 | with respect to coupling criteria and
25 | supports to suggest improved Context Maps.
26 | The Service Cutter library exposes an API
27 | (Open Host Service and Published Language)
28 | used by Context Mapper to generate the
29 | new decompositions.
30 | end note
31 |
32 | component [DiscoveryLibrary]
33 | note left of [DiscoveryLibrary]
34 | The reverse engineering and discovery
35 | component can generate CML Context Maps
36 | from existing source code. This allows
37 | to reverse engineer the architecture
38 | model in projects with existing monoliths
39 | or microservices.
40 | end note
41 |
42 | component [Generators]
43 | note right of [Generators]
44 | The generators allow to generate
45 | other representations of the architecture
46 | derived by a given CML Context
47 | Map.
48 | end note
49 |
50 | interface "Upstream-Downstream" as DiscoveryLibrary_to_LanguageCore
51 | [LanguageCore] -up-> DiscoveryLibrary_to_LanguageCore : "PUBLISHED_LANGUAGE (PL)"
52 | [DiscoveryLibrary] ..> DiscoveryLibrary_to_LanguageCore : " use as CONFORMIST (CF)"
53 |
54 | interface "Upstream-Downstream" as LanguageCore_to_StructuredServiceDecomposition
55 | [StructuredServiceDecomposition] -right-> LanguageCore_to_StructuredServiceDecomposition : "OHS, PL"
56 | LanguageCore_to_StructuredServiceDecomposition <. [LanguageCore] : "use via ACL"
57 |
58 | [LanguageCore] <-> [ArchitecturalRefactorings] : " Shared Kernel "
59 |
60 | interface "Upstream-Downstream" as Generators_to_LanguageCore
61 | [LanguageCore] -down-> Generators_to_LanguageCore : " PUBLISHED_LANGUAGE (PL)"
62 | Generators_to_LanguageCore <.. [Generators] : " use"
63 | @enduml
--------------------------------------------------------------------------------
/src/main/cml/context-mapper-example/images/ContextMapper-Example-Simple_ContextMap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/src/main/cml/context-mapper-example/images/ContextMapper-Example-Simple_ContextMap.png
--------------------------------------------------------------------------------
/src/main/cml/ddd-sample/DDD-Sample-Stage-1.cml:
--------------------------------------------------------------------------------
1 | /* The DDD Cargo sample application modeled in CML. Note that we split the application into multiple bounded contexts. */
2 | ContextMap DDDSampleMap {
3 | contains CargoBookingContext
4 | contains VoyagePlanningContext
5 | contains LocationContext
6 |
7 | /* As Evans mentions in his book (Bounded Context chapter): The voyage planning can be seen as
8 | * separated bounded context. However, it still shares code with the booking application (CargoBookingContext).
9 | * Thus, they are in a 'Shared-Kernel' relationship.
10 | */
11 | CargoBookingContext [SK]<->[SK] VoyagePlanningContext
12 |
13 | /* Note that the splitting of the LocationContext is not mentioned in the original DDD sample of Evans.
14 | * However, locations and the management around them, can somehow be seen as a separated concept which is used by other
15 | * bounded contexts. But this is just an example, since we want to demonstrate our DSL with multiple bounded contexts.
16 | */
17 | CargoBookingContext <- LocationContext
18 |
19 | VoyagePlanningContext <- LocationContext
20 |
21 | }
22 |
23 | /* The original booking application context */
24 | BoundedContext CargoBookingContext
25 |
26 | /* We split the Voyage Planning into a separate bounded context as Evans proposes it in his book. */
27 | BoundedContext VoyagePlanningContext
28 |
29 | /* Separate bounded context for managing the locations. */
30 | BoundedContext LocationContext
31 |
--------------------------------------------------------------------------------
/src/main/cml/ddd-sample/DDD-Sample-Stage-2.cml:
--------------------------------------------------------------------------------
1 | /* The DDD Cargo sample application modeled in CML. Note that we split the application into multiple bounded contexts. */
2 | ContextMap DDDSampleMap {
3 | contains CargoBookingContext
4 | contains VoyagePlanningContext
5 | contains LocationContext
6 |
7 | /* As Evans mentions in his book (Bounded Context chapter): The voyage planning can be seen as
8 | * separated bounded context. However, it still shares code with the booking application (CargoBookingContext).
9 | * Thus, they are in a 'Shared-Kernel' relationship.
10 | */
11 | CargoBookingContext [SK]<->[SK] VoyagePlanningContext
12 |
13 | /* Note that the splitting of the LocationContext is not mentioned in the original DDD sample of Evans.
14 | * However, locations and the management around them, can somehow be seen as a separated concept which is used by other
15 | * bounded contexts. But this is just an example, since we want to demonstrate our DSL with multiple bounded contexts.
16 | */
17 | CargoBookingContext [D]<-[U,OHS,PL] LocationContext
18 |
19 | VoyagePlanningContext [D]<-[U,OHS,PL] LocationContext
20 |
21 | }
22 |
23 | /* The original booking application context */
24 | BoundedContext CargoBookingContext
25 |
26 | /* We split the Voyage Planning into a separate bounded context as Evans proposes it in his book. */
27 | BoundedContext VoyagePlanningContext
28 |
29 | /* Separate bounded context for managing the locations. */
30 | BoundedContext LocationContext
31 |
--------------------------------------------------------------------------------
/src/main/cml/ddd-sample/DDD-Sample-Stage-3.cml:
--------------------------------------------------------------------------------
1 | /* The DDD Cargo sample application modeled in CML. Note that we split the application into multiple bounded contexts. */
2 | ContextMap DDDSampleMap {
3 | contains CargoBookingContext
4 | contains VoyagePlanningContext
5 | contains LocationContext
6 |
7 | /* As Evans mentions in his book (Bounded Context chapter): The voyage planning can be seen as
8 | * separated bounded context. However, it still shares code with the booking application (CargoBookingContext).
9 | * Thus, they are in a 'Shared-Kernel' relationship.
10 | */
11 | CargoBookingContext [SK]<->[SK] VoyagePlanningContext
12 |
13 | /* Note that the splitting of the LocationContext is not mentioned in the original DDD sample of Evans.
14 | * However, locations and the management around them, can somehow be seen as a separated concept which is used by other
15 | * bounded contexts. But this is just an example, since we want to demonstrate our DSL with multiple bounded contexts.
16 | */
17 | CargoBookingContext [D]<-[U,OHS,PL] LocationContext
18 |
19 | VoyagePlanningContext [D]<-[U,OHS,PL] LocationContext
20 |
21 | }
22 |
23 | /* The original booking application context */
24 | BoundedContext CargoBookingContext {
25 | Module cargo {
26 | basePackage = se.citerus.dddsample.domain.model
27 |
28 | Aggregate CargoItineraryLegDeliveryRouteSpecification
29 | }
30 | Module handling {
31 | basePackage = se.citerus.dddsample.domain.model
32 |
33 | Aggregate Handling
34 | }
35 | }
36 |
37 | /* We split the Voyage Planning into a separate bounded context as Evans proposes it in his book. */
38 | BoundedContext VoyagePlanningContext {
39 | Module voyage {
40 | basePackage = se.citerus.dddsample.domain.model
41 |
42 | Aggregate Voyage
43 | }
44 | }
45 |
46 | /* Separate bounded context for managing the locations. */
47 | BoundedContext LocationContext {
48 | Module location {
49 | basePackage = se.citerus.dddsample.domain.model
50 |
51 | Aggregate Location
52 | }
53 | }
--------------------------------------------------------------------------------
/src/main/cml/ddd-sample/DDD-Sample-Stage-4.cml:
--------------------------------------------------------------------------------
1 | /* The DDD Cargo sample application modeled in CML. Note that we split the application into multiple bounded contexts. */
2 | ContextMap DDDSampleMap {
3 | contains CargoBookingContext
4 | contains VoyagePlanningContext
5 | contains LocationContext
6 |
7 | /* As Evans mentions in his book (Bounded Context chapter): The voyage planning can be seen as
8 | * separated bounded context. However, it still shares code with the booking application (CargoBookingContext).
9 | * Thus, they are in a 'Shared-Kernel' relationship.
10 | */
11 | CargoBookingContext [SK]<->[SK] VoyagePlanningContext
12 |
13 | /* Note that the splitting of the LocationContext is not mentioned in the original DDD sample of Evans.
14 | * However, locations and the management around them, can somehow be seen as a separated concept which is used by other
15 | * bounded contexts. But this is just an example, since we want to demonstrate our DSL with multiple bounded contexts.
16 | */
17 | CargoBookingContext [D]<-[U,OHS,PL] LocationContext
18 |
19 | VoyagePlanningContext [D]<-[U,OHS,PL] LocationContext
20 |
21 | }
22 |
23 | /* The original booking application context */
24 | BoundedContext CargoBookingContext {
25 | Module cargo {
26 | basePackage = se.citerus.dddsample.domain.model
27 |
28 | Aggregate CargoItineraryLegDeliveryRouteSpecification {
29 | Entity Cargo
30 | ValueObject Delivery
31 | ValueObject HandlingActivity
32 | ValueObject Itinerary
33 | ValueObject Leg
34 | ValueObject RouteSpecification
35 | enum TransportStatus {
36 | NOT_RECEIVED, IN_PORT, ONBOARD_CARRIER, CLAIMED, UNKNOWN
37 | }
38 | enum RoutingStatus {
39 | NOT_ROUTED, ROUTED, MISROUTED
40 | }
41 | }
42 | }
43 |
44 | Module handling {
45 | basePackage = se.citerus.dddsample.domain.model
46 |
47 | Aggregate Handling {
48 | DomainEvent HandlingEvent
49 | ValueObject HandlingHistory
50 | }
51 | }
52 | }
53 |
54 | /* We split the Voyage Planning into a separate bounded context as Evans proposes it in his book. */
55 | BoundedContext VoyagePlanningContext {
56 | Module voyage {
57 | basePackage = se.citerus.dddsample.domain.model
58 |
59 | Aggregate Voyage {
60 | Entity Voyage
61 | ValueObject CarrierMovement
62 | ValueObject Schedule
63 | ValueObject VoyageNumber
64 | }
65 | }
66 | }
67 |
68 | /* Separate bounded context for managing the locations. */
69 | BoundedContext LocationContext {
70 | Module location {
71 | basePackage = se.citerus.dddsample.domain.model
72 |
73 | Aggregate Location {
74 | Entity Location
75 | ValueObject UnLocode
76 | ValueObject LocationShared
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/src/main/cml/ddd-sample/DDD-Sample-Stage-5.cml:
--------------------------------------------------------------------------------
1 | /* The DDD Cargo sample application modeled in CML. Note that we split the application into multiple bounded contexts. */
2 | ContextMap DDDSampleMap {
3 | contains CargoBookingContext
4 | contains VoyagePlanningContext
5 | contains LocationContext
6 |
7 | /* As Evans mentions in his book (Bounded Context chapter): The voyage planning can be seen as
8 | * separated bounded context. However, it still shares code with the booking application (CargoBookingContext).
9 | * Thus, they are in a 'Shared-Kernel' relationship.
10 | */
11 | CargoBookingContext [SK]<->[SK] VoyagePlanningContext
12 |
13 | /* Note that the splitting of the LocationContext is not mentioned in the original DDD sample of Evans.
14 | * However, locations and the management around them, can somehow be seen as a separated concept which is used by other
15 | * bounded contexts. But this is just an example, since we want to demonstrate our DSL with multiple bounded contexts.
16 | */
17 | CargoBookingContext [D]<-[U,OHS,PL] LocationContext
18 |
19 | VoyagePlanningContext [D]<-[U,OHS,PL] LocationContext
20 |
21 | }
22 |
23 | /* The original booking application context */
24 | BoundedContext CargoBookingContext {
25 | Module cargo {
26 | basePackage = se.citerus.dddsample.domain.model
27 |
28 | Aggregate CargoItineraryLegDeliveryRouteSpecification {
29 | Entity Cargo {
30 | aggregateRoot
31 |
32 | TrackingId trackingId
33 | - LocationShared origin
34 | - RouteSpecification routeSpecification
35 | - Itinerary itinerary
36 | - Delivery delivery
37 |
38 | Repository CargoRepository {
39 | @Cargo find(TrackingId trackingId) throws CargoNotFoundException;
40 | List<@Cargo> findAll;
41 | store(@Cargo cargo);
42 | TrackingId nextTrackingId();
43 | }
44 | }
45 |
46 | ValueObject Delivery {
47 | - TransportStatus transportStatus;
48 | - LocationShared lastKnownLocation;
49 | - Voyage currentVoyage;
50 | boolean misdirected;
51 | Date eta;
52 | - HandlingActivity nextExpectedActivity;
53 | boolean isUnloadedAtDestination;
54 | - RoutingStatus routingStatus;
55 | Date calculatedAt;
56 | - HandlingEvent lastEvent;
57 | }
58 |
59 | ValueObject HandlingActivity {
60 | HandlingEvent.Type handlingEventType
61 | - LocationShared location
62 | - Voyage voyage
63 | }
64 |
65 | ValueObject Itinerary {
66 | ItineraryNumber itineraryNumber
67 | - List legs
68 | }
69 |
70 | ValueObject Leg {
71 | - Voyage voyage
72 | - LocationShared loadLocation
73 | - LocationShared unloadLocation
74 | Date loadTime
75 | Date unloadTime
76 | }
77 |
78 | ValueObject RouteSpecification {
79 | - LocationShared origin
80 | - LocationShared destination
81 | Date arrivalDeadline
82 | }
83 |
84 | enum TransportStatus {
85 | NOT_RECEIVED, IN_PORT, ONBOARD_CARRIER, CLAIMED, UNKNOWN
86 | }
87 |
88 | enum RoutingStatus {
89 | NOT_ROUTED, ROUTED, MISROUTED
90 | }
91 |
92 | Service RoutingService {
93 | List<@Itinerary> fetchRoutesForSpecification(@RouteSpecification routeSpecification) throws LocationNotFoundException;
94 | }
95 |
96 | }
97 | }
98 |
99 | Module handling {
100 | basePackage = se.citerus.dddsample.domain.model
101 |
102 | Aggregate Handling {
103 | DomainEvent HandlingEvent {
104 | aggregateRoot
105 | persistent
106 |
107 | Type handlingType;
108 | - Voyage voyage;
109 | - LocationShared location;
110 | Date completionTime;
111 | Date registrationTime;
112 | - Cargo cargo;
113 |
114 | Repository HandlingEventRepository {
115 | @HandlingHistory lookupHandlingHistoryOfCargo(TrackingId trackingId);
116 | }
117 | }
118 |
119 | ValueObject HandlingHistory {
120 | - List handlingEvents
121 | }
122 | }
123 | }
124 | }
125 |
126 | /* We split the Voyage Planning into a separate bounded context as Evans proposes it in his book. */
127 | BoundedContext VoyagePlanningContext {
128 | Module voyage {
129 | basePackage = se.citerus.dddsample.domain.model
130 |
131 | Aggregate Voyage {
132 | Entity Voyage {
133 | aggregateRoot
134 |
135 | - VoyageNumber voyageNumber;
136 | - Schedule schedule;
137 |
138 | Repository VoyageRepository {
139 |
140 | }
141 | }
142 |
143 | ValueObject CarrierMovement {
144 | - LocationShared departureLocation;
145 | - LocationShared arrivalLocation;
146 | Date departureTime;
147 | Date arrivalTime;
148 | }
149 |
150 | ValueObject Schedule {
151 | - List carrierMovements
152 | }
153 |
154 | ValueObject VoyageNumber {
155 | String number
156 | }
157 | }
158 | }
159 | }
160 |
161 | /* Separate bounded context for managing the locations. */
162 | BoundedContext LocationContext {
163 | Module location {
164 | basePackage = se.citerus.dddsample.domain.model
165 |
166 | Aggregate Location {
167 | Entity Location {
168 | aggregateRoot
169 |
170 | PortCode portcode
171 | - UnLocode unLocode;
172 | String name;
173 |
174 | Repository LocationRepository {
175 | @Location find(@UnLocode unLocode);
176 | List<@Location> findAll();
177 | }
178 | }
179 |
180 | ValueObject UnLocode {
181 | String unLocode
182 | }
183 |
184 | ValueObject LocationShared {
185 | PortCode portCode
186 | - Location location
187 | }
188 | }
189 | }
190 | }
--------------------------------------------------------------------------------
/src/main/cml/ddd-sample/DDD-Sample_Alternative-Relationship-Syntax.cml:
--------------------------------------------------------------------------------
1 | /* The DDD Cargo sample application modeled in CML. Note that we split the application into multiple bounded contexts. */
2 | ContextMap {
3 | contains CargoBookingContext
4 | contains VoyagePlanningContext
5 | contains LocationContext
6 |
7 | /* As Evans mentions in his book (Bounded Context chapter): The voyage planning can be seen as
8 | * separated bounded context. However, it still shares code with the booking application (CargoBookingContext).
9 | * Thus, they are in a 'Shared-Kernel' relationship.
10 | */
11 | CargoBookingContext Shared-Kernel VoyagePlanningContext
12 |
13 | /* Note that the splitting of the LocationContext is not mentioned in the original DDD sample of Evans.
14 | * However, locations and the management around them, can somehow be seen as a separated concept which is used by other
15 | * bounded contexts. But this is just an example, since we want to demonstrate our DSL with multiple bounded contexts.
16 | */
17 | CargoBookingContext Downstream-Upstream [OHS,PL]LocationContext
18 |
19 | LocationContext[OHS,PL] Upstream-Downstream VoyagePlanningContext
20 |
21 | }
22 |
23 |
24 | /* The original booking application context */
25 | BoundedContext CargoBookingContext
26 |
27 | /* We split the Voyage Planning into a separate bounded context as Evans proposes it in his book. */
28 | BoundedContext VoyagePlanningContext
29 |
30 | /* Separate bounded context for managing the locations. */
31 | BoundedContext LocationContext
32 |
--------------------------------------------------------------------------------
/src/main/cml/ddd-sample/README.md:
--------------------------------------------------------------------------------
1 | # DDD "Cargo" Sample Application
2 |
3 | This example is illustrates the Context Mapper DSL capabilities on the basis the [DDD "Cargo" sample application](https://github.com/citerus/dddsample-core).
4 |
5 | Since CML is dealing with context maps, we divided the application into three bounded contexts. [Evans][1] already mentioned in his book, that the voyage scheduling part is a candidate for a possible bounded contexts. Thus, we made a separate bounded context for this part. Since they still share code, they are in shared kernel relationship. Further we proposed the idea of splitting the locations into a separate bounded context, inspired by the example of [Rademacher][2]. This context could provide everything related to locations as an OPEN HOST SERVICE. Note that this is just an example in order to have another bounded context and must not be a good solution necessarily.
6 |
7 | The following figure illustrates the example.
8 |
9 |
10 |
11 | Here you can find the corresponding context map in CML (Context Mapper Language) in different versions and levels of detail (stages). The first four stages do
12 | not contain detailed domain models and should be understandable for users without technical knowledge (business analysis only). The last stage contains details of
13 | the domain models including attributes for all domain objects and are designed for software engineers and architects.
14 |
15 | * [DDD-Sample-Stage-1](./DDD-Sample-Stage-1.cml): A simple context map without relationship patterns in upstream-downstream relationships and without details of the bounded contexts.
16 | * [DDD-Sample-Stage-2](./DDD-Sample-Stage-2.cml): This stage refines the relationships on the context map and adds the corresponding DDD relationship patterns.
17 | * [DDD-Sample-Stage-3](./DDD-Sample-Stage-3.cml): In stage three we added first details to the bounded contexts and specified the modules and aggregates.
18 | * [DDD-Sample-Stage-4](./DDD-Sample-Stage-4.cml): A simple version including all domain objects but no attributes. This stage should still be understandable for users without technical knowledge.
19 | * [DDD-Sample-Stage-5](./DDD-Sample-Stage-5.cml): Finally, a detailed context map on the architect and engineering level. All domain objects are specified in detail (including attributes). This example further contains the repositories and services of the DDD sample app.
20 | * [DDD-Sample_Alternative-Relationship-Syntax](./DDD-Sample_Alternative-Relationship-Syntax.cml): The simple context map example in stage two, but illustrating the alternative relationship syntax.
21 | * [DDD-Sample_User-Representations](./DDD-Sample_User-Representations.scl): Service Cutter user representations file (for Service Cutter integration) to generate new service cuts
22 |
23 | [1]: https://www.oreilly.com/library/view/domain-driven-design-tackling/0321125215/
24 | [2]: https://link.springer.com/chapter/10.1007/978-3-319-74781-1_17
25 |
--------------------------------------------------------------------------------
/src/main/cml/ddd-sample/images/DDD-Cargo-Tracking-ContextMap-Illustration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/src/main/cml/ddd-sample/images/DDD-Cargo-Tracking-ContextMap-Illustration.png
--------------------------------------------------------------------------------
/src/main/cml/ddd-service-cutting-sample/DDD-Sample.cml:
--------------------------------------------------------------------------------
1 | /**
2 | * The CargoTracking context contains the domain model of the DDD Sample application with all its Aggregates:
3 | */
4 | BoundedContext CargoTracking {
5 | Aggregate Cargo {
6 | owner CargoPlaner
7 |
8 | Entity Cargo {
9 | aggregateRoot
10 | - TrackingId trackingId
11 | - Location origin
12 | - RouteSpecification routeSpecification
13 | - Itinerary itinerary
14 | - Delivery delivery
15 | }
16 | ValueObject TrackingId {
17 | String id
18 | }
19 | ValueObject RouteSpecification {
20 | - Location origin
21 | - Location destination
22 | Date arrivalDeadline
23 | }
24 | ValueObject Delivery {
25 | - TransportStatus transportStatus
26 | - Location lastKnownLocation
27 | - Voyage currentVoyage
28 | boolean misdirected
29 | Date eta
30 | Date estimatedArrivalTime
31 | - HandlingActivity nextExpectedActivity
32 | boolean isUnloadedAtDestination
33 | - RoutingStatus routingStatus
34 | Date calculatedAt
35 | - HandlingEvent lastEvent
36 | }
37 | ValueObject HandlingActivity {
38 | Type handlingActivityType
39 | - Location location
40 | - Voyage voyage
41 | }
42 | ValueObject Itinerary {
43 | - List legs
44 | }
45 | ValueObject Leg {
46 | - Voyage voyage
47 | - Location loadLocation
48 | - Location unloadLocation
49 | Date loadTime
50 | Date unloadTime
51 | }
52 | enum RoutingStatus {
53 | NOT_ROUTED, ROUTED, MISROUTED;
54 | }
55 | enum TransportStatus {
56 | NOT_RECEIVED, IN_PORT, ONBOARD_CARRIER, CLAIMED, UNKNOWN;
57 | }
58 | }
59 | Aggregate Location {
60 | owner Administrators
61 |
62 | Entity Location {
63 | aggregateRoot
64 | - UnLocode unLocode
65 | String name
66 | }
67 | ValueObject UnLocode {
68 | String unlocode
69 | }
70 | }
71 | Aggregate Handling {
72 | owner CargoTracker
73 |
74 | DomainEvent HandlingEvent {
75 | - HandlingEventType handlingEventType
76 | - Voyage voyage
77 | - Location location
78 | Date completionTime
79 | Date registrationTime
80 | - Cargo cargo
81 | }
82 | enum HandlingEventType {
83 | LOAD, UNLOAD, RECEIVE, CLAIM, CUSTOMS
84 | }
85 | ValueObject HandlingHistory {
86 | - List handlingEvents
87 | }
88 | }
89 | Aggregate Voyage {
90 | owner VoyageManager
91 |
92 | Entity Voyage {
93 | aggregateRoot
94 | - VoyageNumber voyageNumber
95 | - Schedule schedule
96 | }
97 | ValueObject CarrierMovement {
98 | - Location departureLocation
99 | - Location arrivalLocation
100 | Date departureTime
101 | Date arrivalTime
102 | }
103 | ValueObject Schedule {
104 | - List carrierMovements
105 | }
106 | ValueObject VoyageNumber {
107 | String number
108 | }
109 | }
110 | }
111 |
112 | BoundedContext CargoPlaner { type TEAM }
113 | BoundedContext CargoTracker { type TEAM }
114 | BoundedContext VoyageManager { type TEAM }
115 | BoundedContext Administrators { type TEAM }
116 |
117 | /* Use Cases (taken from Service Cutter examples) */
118 | UseCase ViewTracking {
119 | interactions
120 | read "Cargo" with its "trackindId",
121 | read "HandlingEvent" with its "handlingEventType", "location", "completionTime",
122 | read "Delivery" with its "transportStatus", "estimatedArrivalTime", "misdirected",
123 | read "Voyage" with its "voyageNumber",
124 | read "RouteSpecification" with its "destination"
125 | }
126 |
127 | UseCase ViewCargos {
128 | interactions
129 | read "Cargo" with its "trackingId",
130 | read "RouteSpecification" with its "destination", "arrivalDeadline",
131 | read "Delivery" with its "routingStatus"
132 | }
133 |
134 | UseCase BookCargo {
135 | interactions
136 | read "Location" with its "unLocode",
137 | update "Cargo" with its "trackingId",
138 | update "RouteSpecification" with its "origin", "arrivalDeadline", "destination"
139 | }
140 |
141 | UseCase ChangeCargoDestination {
142 | interactions
143 | read "Cargo" with its "trackingId",
144 | read "RouteSpecification" with its "destination",
145 | update "RouteSpecification" with its "destination"
146 | }
147 |
148 | UseCase RouteCargo {
149 | interactions
150 | read "Cargo" with its "trackingId",
151 | read "RouteSpecification" with its "destination", "origin", "arrivalDeadline",
152 | read "Location" with its "unLocode",
153 | read "Voyage" with its "voyageNumber",
154 | read "CarrierMovement" with its "departureLocation", "arrivalLocation", "departureTime", "arrivalTime",
155 | update "Leg" with its "loadLocation", "unloadLocation", "loadTime", "unloadTime"
156 | }
157 |
158 | UseCase CreateLocation {
159 | interactions
160 | create "Location" with its "unLocode", "name"
161 | }
162 |
163 | UseCase CreateVoyage {
164 | interactions
165 | create "Voyage" with its "voyageNumber"
166 | }
167 |
168 | UseCase AddCarrierMovement {
169 | interactions
170 | read "Voyage" with its "voyageNumber",
171 | create "CarrierMovement" with its "departureLocation", "arrivalLocation", "departureTime", "arrivalTime"
172 | }
173 |
174 | UseCase HandleCargoEvent {
175 | interactions
176 | read "Voyage" with its "voyageNumber",
177 | read "Cargo" with its "trackingId",
178 | update "HandlingEvent" with its "handlingEventType", "completionTime", "registrationTime", "location",
179 | update "Delivery" with its "transportStatus", "misdirected", "estimatedArrivalTime", "isUnloadedAtDestination", "routingStatus"
180 | }
181 |
--------------------------------------------------------------------------------
/src/main/cml/ddd-service-cutting-sample/DDD-Sample.scl:
--------------------------------------------------------------------------------
1 |
2 | UseCase ViewTracking {
3 | reads "HandlingEvent.completionTime" "Delivery.estimatedArrivalTime" "Cargo.trackindId" "HandlingEvent.handlingEventType" "Delivery.misdirected" "Delivery.transportStatus" "Voyage.voyageNumber" "RouteSpecification.destination" "HandlingEvent.location"
4 | }
5 | UseCase ViewCargos {
6 | reads "Cargo.trackingId" "RouteSpecification.arrivalDeadline" "RouteSpecification.destination" "Delivery.routingStatus"
7 | }
8 | UseCase BookCargo {
9 | reads "Location.unLocode"
10 | writes "Cargo.trackingId" "RouteSpecification.arrivalDeadline" "RouteSpecification.destination" "RouteSpecification.origin"
11 | }
12 | UseCase ChangeCargoDestination {
13 | reads "Cargo.trackingId" "RouteSpecification.destination"
14 | writes "RouteSpecification.destination"
15 | }
16 | UseCase RouteCargo {
17 | reads "Location.unLocode" "CarrierMovement.arrivalTime" "Cargo.trackingId" "CarrierMovement.departureLocation" "RouteSpecification.arrivalDeadline" "Voyage.voyageNumber" "RouteSpecification.destination" "CarrierMovement.arrivalLocation" "CarrierMovement.departureTime" "RouteSpecification.origin"
18 | writes "Leg.loadLocation" "Leg.loadTime" "Leg.unloadTime" "Leg.unloadLocation"
19 | }
20 | UseCase CreateLocation {
21 | writes "Location.unLocode" "Location.name"
22 | }
23 | UseCase CreateVoyage {
24 | writes "Voyage.voyageNumber"
25 | }
26 | UseCase AddCarrierMovement {
27 | reads "Voyage.voyageNumber"
28 | writes "CarrierMovement.arrivalTime" "CarrierMovement.departureLocation" "CarrierMovement.arrivalLocation" "CarrierMovement.departureTime"
29 | }
30 | UseCase HandleCargoEvent {
31 | reads "Cargo.trackingId" "Voyage.voyageNumber"
32 | writes "HandlingEvent.completionTime" "Delivery.estimatedArrivalTime" "Delivery.isUnloadedAtDestination" "HandlingEvent.handlingEventType" "Delivery.misdirected" "Delivery.transportStatus" "HandlingEvent.registrationTime" "HandlingEvent.location" "Delivery.routingStatus"
33 | }
34 | Compatibilities {
35 | }
36 | /* These Aggregates are generated from the CML model. Note that they are overwritten each time you use the service cut generator! */
37 | Aggregate "Cargo" {
38 | "Leg.loadLocation" , "Delivery.currentVoyage" , "Leg.loadTime" , "HandlingActivity.location" , "Delivery.transportStatus" , "RouteSpecification.destination" , "Cargo.delivery" , "Cargo.trackingId" , "RouteSpecification.origin" , "Cargo.routeSpecification" , "Cargo.itinerary" , "Delivery.routingStatus" , "Delivery.estimatedArrivalTime" , "Delivery.lastKnownLocation" , "Delivery.calculatedAt" , "Delivery.isUnloadedAtDestination" , "Delivery.eta" , "RouteSpecification.arrivalDeadline" , "Leg.voyage" , "HandlingActivity.voyage" , "Delivery.nextExpectedActivity" , "TrackingId.id" , "Itinerary.legs" , "Delivery.lastEvent" , "Leg.unloadTime" , "Delivery.misdirected" , "Leg.unloadLocation" , "HandlingActivity.handlingActivityType" , "Cargo.origin"
39 | }
40 | Aggregate "Location" {
41 | "Location.unLocode" , "UnLocode.unlocode" , "Location.name"
42 | }
43 | Aggregate "Handling" {
44 | "HandlingHistory.handlingEvents" , "HandlingEvent.completionTime" , "HandlingEvent.handlingEventType" , "HandlingEvent.voyage" , "HandlingEvent.cargo" , "HandlingEvent.registrationTime" , "HandlingEvent.location"
45 | }
46 | Aggregate "Voyage" {
47 | "CarrierMovement.arrivalTime" , "VoyageNumber.number" , "CarrierMovement.departureLocation" , "Voyage.voyageNumber" , "Voyage.schedule" , "CarrierMovement.arrivalLocation" , "CarrierMovement.departureTime" , "Schedule.carrierMovements"
48 | }
49 | /* These Entities are generated from the CML model. Note that they are overwritten each time you use the service cut generator! */
50 | Entity "Cargo" {
51 | "Cargo.trackingId" , "Cargo.origin" , "Cargo.routeSpecification" , "Cargo.itinerary" , "Cargo.delivery"
52 | }
53 | Entity "Location" {
54 | "Location.unLocode" , "Location.name"
55 | }
56 | Entity "Voyage" {
57 | "Voyage.voyageNumber" , "Voyage.schedule"
58 | }
59 | /* These predefined services are generated from the CML model. Note that they are overwritten each time you use the service cut generator! */
60 | PredefinedService "CargoTracking" {
61 | "Location.unLocode" , "Leg.loadLocation" , "Delivery.currentVoyage" , "Leg.loadTime" , "HandlingActivity.location" , "HandlingEvent.cargo" , "Delivery.transportStatus" , "RouteSpecification.destination" , "HandlingEvent.registrationTime" , "CarrierMovement.departureTime" , "Cargo.delivery" , "Schedule.carrierMovements" , "HandlingEvent.completionTime" , "UnLocode.unlocode" , "Cargo.trackingId" , "HandlingEvent.handlingEventType" , "Location.name" , "CarrierMovement.arrivalLocation" , "RouteSpecification.origin" , "Cargo.routeSpecification" , "Cargo.itinerary" , "Delivery.routingStatus" , "HandlingHistory.handlingEvents" , "CarrierMovement.arrivalTime" , "Delivery.estimatedArrivalTime" , "Delivery.lastKnownLocation" , "VoyageNumber.number" , "Delivery.calculatedAt" , "Delivery.isUnloadedAtDestination" , "CarrierMovement.departureLocation" , "Delivery.eta" , "RouteSpecification.arrivalDeadline" , "Leg.voyage" , "Voyage.voyageNumber" , "Voyage.schedule" , "HandlingActivity.voyage" , "HandlingEvent.location" , "Delivery.nextExpectedActivity" , "TrackingId.id" , "HandlingEvent.voyage" , "Itinerary.legs" , "Delivery.lastEvent" , "Leg.unloadTime" , "Delivery.misdirected" , "Leg.unloadLocation" , "HandlingActivity.handlingActivityType" , "Cargo.origin"
62 | }
63 | /* These shared owner groups are generated from the CML model. Note that they are overwritten each time you use the service cut generator! */
64 | SharedOwnerGroup "CargoTracker" {
65 | "HandlingHistory.handlingEvents" , "HandlingEvent.completionTime" , "HandlingEvent.handlingEventType" , "HandlingEvent.voyage" , "HandlingEvent.cargo" , "HandlingEvent.registrationTime" , "HandlingEvent.location"
66 | }
67 | SharedOwnerGroup "VoyageManager" {
68 | "CarrierMovement.arrivalTime" , "VoyageNumber.number" , "CarrierMovement.departureLocation" , "Voyage.voyageNumber" , "Voyage.schedule" , "CarrierMovement.arrivalLocation" , "CarrierMovement.departureTime" , "Schedule.carrierMovements"
69 | }
70 | SharedOwnerGroup "Administrators" {
71 | "Location.unLocode" , "UnLocode.unlocode" , "Location.name"
72 | }
73 | SharedOwnerGroup "CargoPlaner" {
74 | "Leg.loadLocation" , "Delivery.currentVoyage" , "Leg.loadTime" , "HandlingActivity.location" , "Delivery.transportStatus" , "RouteSpecification.destination" , "Cargo.delivery" , "Cargo.trackingId" , "RouteSpecification.origin" , "Cargo.routeSpecification" , "Cargo.itinerary" , "Delivery.routingStatus" , "Delivery.estimatedArrivalTime" , "Delivery.lastKnownLocation" , "Delivery.calculatedAt" , "Delivery.isUnloadedAtDestination" , "Delivery.eta" , "RouteSpecification.arrivalDeadline" , "Leg.voyage" , "HandlingActivity.voyage" , "Delivery.nextExpectedActivity" , "TrackingId.id" , "Itinerary.legs" , "Delivery.lastEvent" , "Leg.unloadTime" , "Delivery.misdirected" , "Leg.unloadLocation" , "HandlingActivity.handlingActivityType" , "Cargo.origin"
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/Insurance-Example-Stage-1.cml:
--------------------------------------------------------------------------------
1 | /* Example Context Map written with 'ContextMapper DSL' */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 |
6 | /* Add bounded contexts to this context map: */
7 | contains CustomerManagementContext
8 | contains CustomerSelfServiceContext
9 | contains PrintingContext
10 | contains PolicyManagementContext
11 | contains RiskManagementContext
12 | contains DebtCollection
13 |
14 | /* Define the context relationships: */
15 |
16 | CustomerSelfServiceContext <- CustomerManagementContext
17 |
18 | CustomerManagementContext <- PrintingContext
19 |
20 | PrintingContext -> PolicyManagementContext
21 |
22 | RiskManagementContext <-> PolicyManagementContext
23 |
24 | PolicyManagementContext <- CustomerManagementContext
25 |
26 | DebtCollection <- PrintingContext
27 |
28 | PolicyManagementContext <-> DebtCollection
29 | }
30 |
31 | /* Bounded Context Definitions */
32 | BoundedContext CustomerManagementContext implements CustomerManagementDomain
33 |
34 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain
35 |
36 | BoundedContext PrintingContext implements PrintingDomain
37 |
38 | BoundedContext PolicyManagementContext implements PolicyManagementDomain
39 |
40 | BoundedContext RiskManagementContext implements RiskManagementDomain
41 |
42 | BoundedContext DebtCollection implements DebtsDomain
43 |
44 | /* Domain & Subdomain Definitions */
45 | Domain InsuranceDomain {
46 | Subdomain CustomerManagementDomain {
47 | type = CORE_DOMAIN
48 | domainVisionStatement = "Subdomain managing everything customer-related."
49 | }
50 | Subdomain PolicyManagementDomain {
51 | type = CORE_DOMAIN
52 | domainVisionStatement = "Subdomain managing contracts and policies."
53 | }
54 | Subdomain PrintingDomain {
55 | type = SUPPORTING_DOMAIN
56 | domainVisionStatement = "Service (external system) to solve printing for all kinds of documents (debts, policies, etc.)"
57 | }
58 | Subdomain RiskManagementDomain {
59 | type = GENERIC_SUBDOMAIN
60 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
61 | }
62 | Subdomain DebtsDomain {
63 | type = GENERIC_SUBDOMAIN
64 | domainVisionStatement = "Subomain including everything related to the incoming money (debts, dunning, etc.)"
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/Insurance-Example-Stage-2.cml:
--------------------------------------------------------------------------------
1 | /* Example Context Map written with 'ContextMapper DSL' */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 |
6 | /* Add bounded contexts to this context map: */
7 | contains CustomerManagementContext
8 | contains CustomerSelfServiceContext
9 | contains PrintingContext
10 | contains PolicyManagementContext
11 | contains RiskManagementContext
12 | contains DebtCollection
13 |
14 | /* Define the context relationships: */
15 |
16 | CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext
17 |
18 | CustomerManagementContext [D,ACL]<-[U,OHS,PL] PrintingContext
19 |
20 | PrintingContext [U,OHS,PL]->[D,ACL] PolicyManagementContext
21 |
22 | RiskManagementContext [P]<->[P] PolicyManagementContext
23 |
24 | PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext
25 |
26 | DebtCollection [D,ACL]<-[U,OHS,PL] PrintingContext
27 |
28 | PolicyManagementContext [SK]<->[SK] DebtCollection
29 | }
30 |
31 | /* Bounded Context Definitions */
32 | BoundedContext CustomerManagementContext implements CustomerManagementDomain
33 |
34 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain
35 |
36 | BoundedContext PrintingContext implements PrintingDomain
37 |
38 | BoundedContext PolicyManagementContext implements PolicyManagementDomain
39 |
40 | BoundedContext RiskManagementContext implements RiskManagementDomain
41 |
42 | BoundedContext DebtCollection implements DebtsDomain
43 |
44 | /* Domain & Subdomain Definitions */
45 | Domain InsuranceDomain {
46 | Subdomain CustomerManagementDomain {
47 | type = CORE_DOMAIN
48 | domainVisionStatement = "Subdomain managing everything customer-related."
49 | }
50 | Subdomain PolicyManagementDomain {
51 | type = CORE_DOMAIN
52 | domainVisionStatement = "Subdomain managing contracts and policies."
53 | }
54 | Subdomain PrintingDomain {
55 | type = SUPPORTING_DOMAIN
56 | domainVisionStatement = "Service (external system) to solve printing for all kinds of documents (debts, policies, etc.)"
57 | }
58 | Subdomain RiskManagementDomain {
59 | type = GENERIC_SUBDOMAIN
60 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
61 | }
62 | Subdomain DebtsDomain {
63 | type = GENERIC_SUBDOMAIN
64 | domainVisionStatement = "Subomain including everything related to the incoming money (debts, dunning, etc.)"
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/Insurance-Example-Stage-3.cml:
--------------------------------------------------------------------------------
1 | /* Example Context Map written with 'ContextMapper DSL' */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 |
6 | /* Add bounded contexts to this context map: */
7 | contains CustomerManagementContext
8 | contains CustomerSelfServiceContext
9 | contains PrintingContext
10 | contains PolicyManagementContext
11 | contains RiskManagementContext
12 | contains DebtCollection
13 |
14 | /* Define the context relationships: */
15 |
16 | CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext
17 |
18 | CustomerManagementContext [D,ACL]<-[U,OHS,PL] PrintingContext
19 |
20 | PrintingContext [U,OHS,PL]->[D,ACL] PolicyManagementContext
21 |
22 | RiskManagementContext [P]<->[P] PolicyManagementContext
23 |
24 | PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext
25 |
26 | DebtCollection [D,ACL]<-[U,OHS,PL] PrintingContext
27 |
28 | PolicyManagementContext [SK]<->[SK] DebtCollection
29 | }
30 |
31 | /* Bounded Context Definitions */
32 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
33 | type = FEATURE
34 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
35 | implementationTechnology = "Java, JEE Application"
36 | responsibilities = "Customers, Addresses"
37 |
38 | Aggregate Customers
39 |
40 | }
41 |
42 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
43 | type = APPLICATION
44 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
45 | responsibilities = "AddressChange"
46 | implementationTechnology = "PHP Web Application"
47 |
48 | Aggregate CustomerFrontend
49 |
50 | Aggregate Acounts
51 | }
52 |
53 | BoundedContext PrintingContext implements PrintingDomain {
54 | type = SYSTEM
55 | responsibilities = "Document Printing"
56 | domainVisionStatement = "An external system which provides printing services to the other Bounded Contexts."
57 |
58 | Aggregate Printing
59 |
60 | Aggregate Templating
61 | }
62 |
63 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
64 | type = FEATURE
65 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
66 | responsibilities = "Offers, Contracts, Policies"
67 | implementationTechnology = "Java, Spring App"
68 |
69 | Aggregate Offers
70 |
71 | Aggregate Products
72 |
73 | Aggregate Contract
74 | }
75 |
76 | BoundedContext RiskManagementContext implements RiskManagementDomain {
77 | type = FEATURE
78 | domainVisionStatement = "Uses data from PolicyManagement context to calculate risks."
79 | responsibilities = "Customer Risk Calculation"
80 | implementationTechnology = "Java, Spring App"
81 |
82 | Aggregate Risks
83 | }
84 |
85 | BoundedContext DebtCollection implements DebtsDomain {
86 | type = FEATURE
87 | domainVisionStatement = "The debt collection context is responsible for the financial income of the insurance company (the debts) which depend on the corresponding contracts and policies."
88 | responsibilities = "Debts, Dunning"
89 | implementationTechnology = "JEE"
90 |
91 | Aggregate Debts
92 | }
93 |
94 | /* Domain & Subdomain Definitions */
95 | Domain InsuranceDomain {
96 | Subdomain CustomerManagementDomain {
97 | type = CORE_DOMAIN
98 | domainVisionStatement = "Subdomain managing everything customer-related."
99 | }
100 | Subdomain PolicyManagementDomain {
101 | type = CORE_DOMAIN
102 | domainVisionStatement = "Subdomain managing contracts and policies."
103 | }
104 | Subdomain PrintingDomain {
105 | type = SUPPORTING_DOMAIN
106 | domainVisionStatement = "Service (external system) to solve printing for all kinds of documents (debts, policies, etc.)"
107 | }
108 | Subdomain RiskManagementDomain {
109 | type = GENERIC_SUBDOMAIN
110 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
111 | }
112 | Subdomain DebtsDomain {
113 | type = GENERIC_SUBDOMAIN
114 | domainVisionStatement = "Subomain including everything related to the incoming money (debts, dunning, etc.)"
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/Insurance-Example-Stage-4.cml:
--------------------------------------------------------------------------------
1 | /* Example Context Map written with 'ContextMapper DSL' */
2 | ContextMap InsuranceContextMap {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 |
6 | /* Add bounded contexts to this context map: */
7 | contains CustomerManagementContext
8 | contains CustomerSelfServiceContext
9 | contains PrintingContext
10 | contains PolicyManagementContext
11 | contains RiskManagementContext
12 | contains DebtCollection
13 |
14 | /* Define the context relationships: */
15 |
16 | CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext
17 |
18 | CustomerManagementContext [D,ACL]<-[U,OHS,PL] PrintingContext
19 |
20 | PrintingContext [U,OHS,PL]->[D,ACL] PolicyManagementContext
21 |
22 | RiskManagementContext [P]<->[P] PolicyManagementContext
23 |
24 | PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext
25 |
26 | DebtCollection [D,ACL]<-[U,OHS,PL] PrintingContext
27 |
28 | PolicyManagementContext [SK]<->[SK] DebtCollection
29 | }
30 |
31 | /* Bounded Context Definitions */
32 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
33 | type = FEATURE
34 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
35 | implementationTechnology = "Java, JEE Application"
36 | responsibilities = "Customers, Addresses"
37 |
38 | Aggregate Customers {
39 | Entity Customer
40 | Entity Address
41 | ValueObject SocialInsuranceNumber
42 | }
43 |
44 | }
45 |
46 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
47 | type = APPLICATION
48 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
49 | responsibilities = "AddressChange"
50 | implementationTechnology = "PHP Web Application"
51 |
52 | Aggregate CustomerFrontend {
53 | Entity CustomerAddressChange
54 | }
55 |
56 | Aggregate Acounts {
57 | Entity UserAccount
58 | }
59 | }
60 |
61 | BoundedContext PrintingContext implements PrintingDomain {
62 | type = SYSTEM
63 | responsibilities = "Document Printing"
64 | domainVisionStatement = "An external system which provides printing services to the other Bounded Contexts."
65 |
66 | Aggregate Printing {
67 | Entity PrintingJob
68 | Entity Document
69 | }
70 |
71 | Aggregate Templating {
72 | Entity Template
73 | }
74 | }
75 |
76 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
77 | type = FEATURE
78 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
79 | responsibilities = "Offers, Contracts, Policies"
80 | implementationTechnology = "Java, Spring App"
81 |
82 | Aggregate Offers {
83 | Entity Offer
84 | }
85 |
86 | Aggregate Products {
87 | Entity Product
88 | ValueObject ProductId
89 | }
90 |
91 | Aggregate Contract {
92 | Entity Contract
93 | ValueObject ContractId
94 | Entity Policy
95 | }
96 | }
97 |
98 | BoundedContext RiskManagementContext implements RiskManagementDomain {
99 | type = FEATURE
100 | domainVisionStatement = "Uses data from PolicyManagement context to calculate risks."
101 | responsibilities = "Customer Risk Calculation"
102 | implementationTechnology = "Java, Spring App"
103 |
104 | Aggregate Risks {
105 | Entity CustomerRiskFactor
106 | ValueObject Risk
107 | }
108 | }
109 |
110 | BoundedContext DebtCollection implements DebtsDomain {
111 | type = FEATURE
112 | domainVisionStatement = "The debt collection context is responsible for the financial income of the insurance company (the debts) which depend on the corresponding contracts and policies."
113 | responsibilities = "Debts, Dunning"
114 | implementationTechnology = "JEE"
115 |
116 | Aggregate Debts {
117 | Entity Debt
118 | Entity Dunning
119 | }
120 | }
121 |
122 | /* Domain & Subdomain Definitions */
123 | Domain InsuranceDomain {
124 | Subdomain CustomerManagementDomain {
125 | type = CORE_DOMAIN
126 | domainVisionStatement = "Subdomain managing everything customer-related."
127 | }
128 | Subdomain PolicyManagementDomain {
129 | type = CORE_DOMAIN
130 | domainVisionStatement = "Subdomain managing contracts and policies."
131 | }
132 | Subdomain PrintingDomain {
133 | type = SUPPORTING_DOMAIN
134 | domainVisionStatement = "Service (external system) to solve printing for all kinds of documents (debts, policies, etc.)"
135 | }
136 | Subdomain RiskManagementDomain {
137 | type = GENERIC_SUBDOMAIN
138 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
139 | }
140 | Subdomain DebtsDomain {
141 | type = GENERIC_SUBDOMAIN
142 | domainVisionStatement = "Subomain including everything related to the incoming money (debts, dunning, etc.)"
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/Insurance-Example_Alternative-Relationship-Syntax.cml:
--------------------------------------------------------------------------------
1 | /* Example Context Map written with 'ContextMapper DSL' */
2 | ContextMap InsuranceContextMapAlternative {
3 | type = SYSTEM_LANDSCAPE
4 | state = TO_BE
5 |
6 | /* Add bounded contexts to this context map: */
7 | contains CustomerManagementContext
8 | contains CustomerSelfServiceContext
9 | contains PrintingContext
10 | contains PolicyManagementContext
11 | contains RiskManagementContext
12 | contains DebtCollection
13 |
14 | /* Define the context relationships: */
15 |
16 | CustomerSelfServiceContext Customer-Supplier CustomerManagementContext
17 |
18 | PrintingContext[OHS,PL] Upstream-Downstream [ACL]CustomerManagementContext
19 |
20 | PolicyManagementContext[ACL] Downstream-Upstream [OHS,PL]PrintingContext
21 |
22 | RiskManagementContext Partnership PolicyManagementContext
23 |
24 | CustomerManagementContext[OHS,PL] Upstream-Downstream [CF]PolicyManagementContext
25 |
26 | DebtCollection[ACL] Downstream-Upstream [OHS,PL]PrintingContext
27 |
28 | PolicyManagementContext Shared-Kernel DebtCollection
29 | }
30 |
31 | /* Bounded Context Definitions */
32 | BoundedContext CustomerManagementContext implements CustomerManagementDomain
33 |
34 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain
35 |
36 | BoundedContext PrintingContext implements PrintingDomain
37 |
38 | BoundedContext PolicyManagementContext implements PolicyManagementDomain
39 |
40 | BoundedContext RiskManagementContext implements RiskManagementDomain
41 |
42 | BoundedContext DebtCollection implements DebtsDomain
43 |
44 | /* Domain & Subdomain Definitions */
45 | Domain InsuranceDomain {
46 | Subdomain CustomerManagementDomain {
47 | type = CORE_DOMAIN
48 | domainVisionStatement = "Subdomain managing everything customer-related."
49 | }
50 | Subdomain PolicyManagementDomain {
51 | type = CORE_DOMAIN
52 | domainVisionStatement = "Subdomain managing contracts and policies."
53 | }
54 | Subdomain PrintingDomain {
55 | type = SUPPORTING_DOMAIN
56 | domainVisionStatement = "Service (external system) to solve printing for all kinds of documents (debts, policies, etc.)"
57 | }
58 | Subdomain RiskManagementDomain {
59 | type = GENERIC_SUBDOMAIN
60 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
61 | }
62 | Subdomain DebtsDomain {
63 | type = GENERIC_SUBDOMAIN
64 | domainVisionStatement = "Subomain including everything related to the incoming money (debts, dunning, etc.)"
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/Insurance-Example_Team-Map.cml:
--------------------------------------------------------------------------------
1 | /* Example Context Map written with 'ContextMapper DSL' */
2 | ContextMap InsuranceTeamMap {
3 | type = ORGANIZATIONAL
4 | state = TO_BE
5 |
6 | /* Add contexts that represent subsystems/components to this organizational map: */
7 | contains CustomerManagementContext, CustomerSelfServiceContext, PolicyManagementContext, RiskManagementContext
8 |
9 | /* Add teams to this organizational map: */
10 | contains CustomersBackofficeTeam, CustomersFrontofficeTeam, ContractsTeam
11 |
12 | /* Define the subsystem/component relationships: */
13 |
14 | CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext
15 |
16 | PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext
17 |
18 | PolicyManagementContext [P]<->[P] RiskManagementContext
19 |
20 | /* Define the team relationships: */
21 |
22 | CustomersBackofficeTeam [U,S]->[D,C] CustomersFrontofficeTeam
23 |
24 | CustomersBackofficeTeam [U]->[D] ContractsTeam
25 |
26 | }
27 |
28 | /* Team Definitions */
29 | BoundedContext CustomersBackofficeTeam implements CustomerManagementDomain realizes CustomerManagementContext {
30 | type = TEAM
31 | domainVisionStatement = "This team is responsible for implementing the customers module in the back-office system."
32 | }
33 |
34 | BoundedContext CustomersFrontofficeTeam implements CustomerManagementDomain realizes CustomerSelfServiceContext {
35 | type = TEAM
36 | domainVisionStatement = "This team is responsible for implementing the front-office application for the insurance customers."
37 | }
38 |
39 | BoundedContext ContractsTeam implements PolicyManagementDomain, RiskManagementDomain realizes PolicyManagementContext, RiskManagementContext {
40 | type = TEAM
41 | domainVisionStatement = "This team is responsible for implementing the contract-, policy-, and risk-management modules in the back-office system."
42 | }
43 |
44 | /* Bounded Context Definitions */
45 | BoundedContext CustomerManagementContext implements CustomerManagementDomain {
46 | type = FEATURE
47 | domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
48 | implementationTechnology = "Java, JEE Application"
49 | responsibilities = "Customers, Addresses"
50 |
51 | Aggregate Customers {
52 | Entity Customer {
53 | aggregateRoot
54 |
55 | - SocialInsuranceNumber sin
56 | String firstname
57 | String lastname
58 | - List addresses
59 | }
60 |
61 | Entity Address {
62 | String street
63 | int postalCode
64 | String city
65 | }
66 |
67 | ValueObject SocialInsuranceNumber {
68 | String sin key
69 | }
70 | }
71 |
72 | }
73 |
74 | BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
75 | type = APPLICATION
76 | domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
77 | responsibilities = "Address Change"
78 | implementationTechnology = "PHP Web Application"
79 |
80 | Aggregate CustomerFrontend {
81 | Entity CustomerAddressChange {
82 | aggregateRoot
83 |
84 | - UserAccount issuer
85 | - Address changedAddress
86 | }
87 | }
88 |
89 | Aggregate Acounts {
90 | Entity UserAccount {
91 | aggregateRoot
92 |
93 | String username
94 | - Customer accountCustomer
95 | }
96 | }
97 | }
98 |
99 | BoundedContext PolicyManagementContext implements PolicyManagementDomain {
100 | type = FEATURE
101 | domainVisionStatement = "This bounded context manages the contracts and policies of the customers."
102 | responsibilities = "Offers, Contracts, Policies"
103 | implementationTechnology = "Java, Spring App"
104 |
105 | Aggregate Offers {
106 | Entity Offer {
107 | aggregateRoot
108 |
109 | int offerId
110 | - Customer client
111 | - List products
112 | BigDecimal price
113 | }
114 | }
115 |
116 | Aggregate Products {
117 | Entity Product {
118 | aggregateRoot
119 |
120 | - ProductId identifier
121 | String productName
122 | }
123 |
124 | ValueObject ProductId {
125 | int productId key
126 | }
127 | }
128 |
129 | Aggregate Contract {
130 | Entity Contract {
131 | aggregateRoot
132 |
133 | - ContractId identifier
134 | - Customer client
135 | - List products
136 | }
137 |
138 | ValueObject ContractId {
139 | int contractId key
140 | }
141 |
142 | Entity Policy {
143 | int policyNr
144 | - Contract contract
145 | BigDecimal price
146 | }
147 | }
148 | }
149 |
150 | BoundedContext RiskManagementContext implements RiskManagementDomain {
151 | type = FEATURE
152 | domainVisionStatement = "Uses data from PolicyManagement context to calculate risks."
153 | responsibilities = "Customer Risk Calculation"
154 | implementationTechnology = "Java, Spring App"
155 |
156 | Aggregate Risks {
157 | Entity CustomerRiskFactor {
158 | aggregateRoot
159 |
160 | int totalRiskFactor
161 | - List risks
162 | - Customer client
163 | }
164 |
165 | ValueObject Risk {
166 | int likelihood
167 | String risk
168 | }
169 | }
170 | }
171 |
172 | /* Domain & Subdomain Definitions */
173 | Domain InsuranceDomain {
174 | Subdomain CustomerManagementDomain {
175 | type = CORE_DOMAIN
176 | domainVisionStatement = "Subdomain managing everything customer-related."
177 | }
178 | Subdomain PolicyManagementDomain {
179 | type = CORE_DOMAIN
180 | domainVisionStatement = "Subdomain managing contracts and policies."
181 | }
182 | Subdomain RiskManagementDomain {
183 | type = GENERIC_SUBDOMAIN
184 | domainVisionStatement = "Subdomain supporting everything which relates to risk management."
185 | }
186 | Subdomain DebtsDomain {
187 | type = GENERIC_SUBDOMAIN
188 | domainVisionStatement = "Subomain including everything related to the incoming money (debts, dunning, etc.)"
189 | }
190 | }
191 |
192 |
193 |
194 |
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/README.md:
--------------------------------------------------------------------------------
1 | # Insurance Company Example
2 | This example illustrates the Context Mapper DSL capabilities on the basis of a fictitious insurance company scenario. The bounded contexts are partially inspired by the [Lakeside Mutual](https://github.com/Microservice-API-Patterns/LakesideMutual) project.
3 | Note that the goal of the example is to give a representative overview over the DSL's context mapping features. The contexts and their relationships may differ considerably in a real-world insurance company.
4 |
5 | ## Context Map
6 | The following figure illustrates the Context Map in a graphical representation inspired by [Vernon][1] and [Brandolini][2].
7 |
8 |
9 |
10 | You can find the corresponding context map in CML (Context Mapper Language) here in different versions and levels of detail (stages). The first four stages do
11 | not contain detailed domain models and should be understandable for users without technical knowledge (business analysis only). The last stage contains details of
12 | the domain models including attributes for all domain objects and are designed for software engineers and architects.
13 |
14 | * [Insurance-Example-Stage-1](./Insurance-Example-Stage-1.cml): A simple context map without relationship patterns in upstream-downstream relationships and without details of the bounded contexts.
15 | * [Insurance-Example-Stage-2](./Insurance-Example-Stage-2.cml): This stage refines the relationships on the context map and adds the corresponding DDD relationship patterns.
16 | * [Insurance-Example-Stage-3](./Insurance-Example-Stage-3.cml): In stage three we added first details to the bounded contexts and specified the aggregates.
17 | * [Insurance-Example-Stage-4](./Insurance-Example-Stage-4.cml): A simple version including all domain objects but no attributes. This stage should still be understandable for users without technical knowledge.
18 | * [Insurance-Example-Stage-5](./Insurance-Example-Stage-5.cml): Finally, a detailed context map on the architect and engineering level. All domain objects are specified in detail (including attributes). This example further contains methods in aggregate root entities.
19 | * [Insurance-Example_Alternative-Relationship-Syntax](./Insurance-Example_Alternative-Relationship-Syntax.cml): The simple context map example in stage two, but illustrating the alternative relationship syntax.
20 | * [Insurance-Example_User_Representations](./Insurance-Example_User_Representations.scl): Service Cutter user representations file (for Service Cutter integration) to generate new service cuts
21 |
22 | The following bounded contexts are involved in the system:
23 | * Customer Management
24 | * Customer Self-Service Management
25 | * Policy Management
26 | * Debt Collection
27 | * Risk Management
28 | * Printing Context
29 |
30 | ## Team Map
31 | Besides classic context maps with bounded contexts, CML supports modeling teams and their relationships as it is possible with bounded contexts. This is done by simply change the type of a bounded context from SYSTEM, FEATURE or APPLICATION to TEAM. Note that the type of the context map is ORGANIZATIONAL in this case.
32 |
33 | * [Insurance-Example_Team-Map](./Insurance-Example_Team-Map.cml): A team map example for the insurance scenario
34 |
35 | As you can see in the example linked above, you can further use the _realizes_ to define which teams work on which systems, applications, or features. By using the graphical Context Map generator, you can then generate team maps that illustrate the relations between development teams and system bounded contexts.
36 |
37 | Depending how you parameterize the generator, the produced illustrations will be unclustered...
38 |
39 |
40 |
41 | ... or clustered:
42 |
43 |
44 |
45 | ## Bounded Contexts
46 |
47 | ### Customer Management
48 | The customer management context is responsible for managing all the data of the insurance companies customers. Thus, it is typically a central bounded context which has relationships to many other contexts.
49 |
50 | ### Customer Self-Service Management
51 | This context represents a web application which allows the customer to login and change basic data records like the address.
52 |
53 | ### Policy Management
54 | This bounded context manages the contracts and policies of the customers. It works in a _partnership_ together with the risk management context, since it needs the customer risk data for calculating the customer rates. Further, it has a _shared kernel_ with the debt collection context.
55 |
56 | ### Debt Collection
57 | The debt collection context is responsible for the financial income of the insurance company (the debts) which depend on the corresponding contracts and policies.
58 |
59 | ### Risk Management
60 | The risk management context works in a close _relationship_ with the policy management context and calculates risks which influence contracts and policies.
61 |
62 | ### Printing Context
63 | This context represents an external system which is accessed by an API by many internal contexts. It handles documents which have to be printed, as for example debts, policies, etc.
64 |
65 | [1]: https://www.amazon.de/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577
66 | [2]: https://www.infoq.com/articles/ddd-contextmapping
67 |
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/images/ContextMap-Illustration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/src/main/cml/insurance-example/images/ContextMap-Illustration.png
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/images/TeamMap-Illustration-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/src/main/cml/insurance-example/images/TeamMap-Illustration-1.png
--------------------------------------------------------------------------------
/src/main/cml/insurance-example/images/TeamMap-Illustration-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/src/main/cml/insurance-example/images/TeamMap-Illustration-2.png
--------------------------------------------------------------------------------
/src/main/cml/lakeside-mutual/QuoteRequestFlow.cml:
--------------------------------------------------------------------------------
1 | /**
2 | * A RequestStatus is a value object that is used to represent
3 | * the current status of an insurance quote request.
4 | *
5 | * The following diagram shows the possible state transitions:
6 | *
7 | *
8 | *
9 | * │
10 | * ▼
11 | * ┌────────────┐
12 | * │ REQUEST_ │
13 | * │ SUBMITTED │
14 | * └────────────┘
15 | * │
16 | * ┌─────────────────┴────────────────┐
17 | * │ │
18 | * ▼ ▼
19 | * ┌────────────┐ ╔════════════╗
20 | * │ QUOTE_ │ ║ REQUEST_ ║
21 | * ┌───────────│ RECEIVED │─────────────┐ ║ REJECTED ║
22 | * │ └────────────┘ │ ╚════════════╝
23 | * │ │ │
24 | * │ │ │
25 | * ▼ ▼ ▼
26 | * ╔════════════╗ ┌────────────┐ ╔════════════╗
27 | * ║ QUOTE_ ║ │ QUOTE_ │ ║ QUOTE_ ║
28 | * ║ REJECTED ║ │ ACCEPTED │─────▶║ EXPIRED ║
29 | * ╚════════════╝ └────────────┘ ╚════════════╝
30 | * │
31 | * │
32 | * ▼
33 | * ╔════════════╗
34 | * ║ POLICY_ ║
35 | * ║ CREATED ║
36 | * ╚════════════╝
37 | *
38 | *
39 | */
40 |
41 | BoundedContext InsuranceQuotes {
42 | Application {
43 | Command SubmitRequest
44 | Flow QuoteRequestFlow {
45 | command SubmitRequest delegates to QuoteRequest[-> SUBMITTED] emits event RequestSubmitted
46 | event RequestSubmitted + RequestSubmitted triggers operation checkRequest
47 | operation checkRequest delegates to QuoteRequest[SUBMITTED -> RECEIVED X REJECTED] emits event QuoteReceived X RequestRejected
48 | event QuoteReceived triggers operation receiveAndCheckQuote
49 | operation receiveAndCheckQuote delegates to QuoteRequest[RECEIVED -> REJECTED X ACCEPTED X EXPIRED] emits event QuoteRejected X QuoteAccepted X QuoteExpired
50 | event QuoteAccepted triggers operation accept
51 | operation accept delegates to QuoteRequest[ACCEPTED -> POLICY_CREATED X EXPIRED] emits event PolicyCreated X QuoteExpired
52 | }
53 | }
54 | Aggregate QuoteRequest {
55 | Entity Request {
56 | aggregateRoot
57 | }
58 | DomainEvent RequestSubmitted
59 | DomainEvent QuoteReceived
60 | DomainEvent RequestRejected
61 | DomainEvent QuoteRejected
62 | DomainEvent QuoteAccepted
63 | DomainEvent QuoteExpired
64 | DomainEvent PolicyCreated
65 | Service QuoteRequestService {
66 | void checkRequest(@Request request);
67 | void receiveAndCheckQuote(@Request request);
68 | void reject(@Request request);
69 | void accept(@Request request);
70 | }
71 | enum RequestState {
72 | aggregateLifecycle
73 | SUBMITTED, RECEIVED, REJECTED, ACCEPTED, EXPIRED, POLICY_CREATED
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/cml/lakeside-mutual/README.md:
--------------------------------------------------------------------------------
1 | # Lakeside Mutual Example
2 | This example illustrates Context Mapper capabilities on the basis of a fictitious insurance project called [Lakeside Mutual](https://github.com/Microservice-API-Patterns/LakesideMutual) project. The CML model of this example has been reverse engineered with our [discovery library](https://github.com/ContextMapper/context-map-discovery). With an Event Storming we have enhanced the model for a future feature that could be realized in the project (claim processing).
3 |
4 | ## Context Map
5 | The following figure illustrates the Context Map in a graphical representation generated with our [Context Map generator](https://contextmapper.org/docs/context-map-generator/):
6 |
7 |
8 |
9 | The complete CML model of the system can be found in the following file: [LakesideMutual.cml](./LakesideMutual.cml)
10 |
11 | ## Event Storming
12 | We extended the reverse engineered CML model of the Lakeside Mutual to support claim processing as a future feature. We conducted an Event Storming to
13 | analyze the subdomain for the new feature. The example shall illustrate how Event Storming results can be modeled in Context Mapper.
14 |
15 | (a tutorial how Context Mapper can be used to model Event Storming results will be published on our website soon)
16 |
17 | The following graphic shows the [result of our Event Storming](https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/master/src/main/cml/lakeside-mutual/images/event-storming-result.jpg):
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/cml/lakeside-mutual/images/ContextMap-Illustration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/src/main/cml/lakeside-mutual/images/ContextMap-Illustration.png
--------------------------------------------------------------------------------
/src/main/cml/lakeside-mutual/images/event-storming-result.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/src/main/cml/lakeside-mutual/images/event-storming-result.jpg
--------------------------------------------------------------------------------
/src/main/cml/microservice-generation/JDL-example/generated-insurance-microservices.jdl:
--------------------------------------------------------------------------------
1 |
2 | /* Bounded Context CustomerManagement */
3 |
4 | entity Customer {
5 | firstname String
6 | lastname String
7 | }
8 |
9 |
10 | entity Address {
11 | street String
12 | postalCode Integer
13 | city String
14 | }
15 |
16 | microservice Customer, Address with CustomerManagement
17 |
18 | application {
19 | config {
20 | baseName CustomerManagement,
21 | packageName org.contextmapper.generated.customermanagement,
22 | applicationType microservice
23 | serverPort 8081
24 | }
25 | entities Customer, Address
26 | }
27 |
28 | /* Bounded Context CustomerSelfService */
29 |
30 | entity CustomerAddressChange {
31 | }
32 |
33 |
34 | entity UserAccount {
35 | username String
36 | }
37 |
38 | microservice CustomerAddressChange, UserAccount with CustomerSelfService
39 |
40 | application {
41 | config {
42 | baseName CustomerSelfService,
43 | packageName org.contextmapper.generated.customerselfservice,
44 | applicationType microservice
45 | serverPort 8082
46 | }
47 | entities CustomerAddressChange, UserAccount
48 | }
49 |
50 | /* Bounded Context Printing */
51 |
52 | entity PrintingJob {
53 | printingId Integer
54 | }
55 |
56 |
57 | entity Document {
58 | source Blob
59 | template String
60 | }
61 |
62 |
63 | entity Template {
64 | templateId Integer
65 | templateName String
66 | }
67 |
68 | microservice PrintingJob, Document, Template with Printing
69 |
70 | application {
71 | config {
72 | baseName Printing,
73 | packageName org.contextmapper.generated.printing,
74 | applicationType microservice
75 | serverPort 8083
76 | }
77 | entities PrintingJob, Document, Template
78 | }
79 |
80 | /* Bounded Context PolicyManagement */
81 |
82 | entity Offer {
83 | offerId Integer
84 | price BigDecimal
85 | }
86 |
87 |
88 | entity Product {
89 | productName String
90 | }
91 |
92 |
93 | entity Contract {
94 | }
95 |
96 |
97 | entity Policy {
98 | policyNr Integer
99 | price BigDecimal
100 | }
101 |
102 | microservice Offer, Product, Contract, Policy with PolicyManagement
103 |
104 | application {
105 | config {
106 | baseName PolicyManagement,
107 | packageName org.contextmapper.generated.policymanagement,
108 | applicationType microservice
109 | serverPort 8084
110 | }
111 | entities Offer, Product, Contract, Policy
112 | }
113 |
114 | /* Bounded Context RiskManagement */
115 |
116 | entity CustomerRiskFactor {
117 | totalRiskFactor Integer
118 | }
119 |
120 | microservice CustomerRiskFactor with RiskManagement
121 |
122 | application {
123 | config {
124 | baseName RiskManagement,
125 | packageName org.contextmapper.generated.riskmanagement,
126 | applicationType microservice
127 | serverPort 8085
128 | }
129 | entities CustomerRiskFactor
130 | }
131 |
132 | /* Bounded Context DebtCollection */
133 |
134 | entity Debt {
135 | debtNr Integer
136 | creationDate LocalDate
137 | paymentDate LocalDate
138 | paymentDeadline LocalDate
139 | price BigDecimal
140 | status Blob
141 | }
142 |
143 |
144 | entity Dunning {
145 | dunningNr Integer
146 | dunningDate LocalDate
147 | paymentDeadline LocalDate
148 | }
149 |
150 | microservice Debt, Dunning with DebtCollection
151 |
152 | application {
153 | config {
154 | baseName DebtCollection,
155 | packageName org.contextmapper.generated.debtcollection,
156 | applicationType microservice
157 | serverPort 8086
158 | }
159 | entities Debt, Dunning
160 | }
161 |
162 | /* relationships */
163 | relationship OneToMany {
164 | Customer{addresses} to Address
165 | Offer{products} to Product
166 | Contract{products} to Product
167 | Debt{dunnigs} to Dunning
168 | }
169 | relationship OneToOne {
170 | CustomerAddressChange{issuer} to UserAccount
171 | PrintingJob{document} to Document
172 | PrintingJob{template} to Template
173 | Policy{contract} to Contract
174 | }
175 |
176 | /* microservice gateyway app */
177 | application {
178 | config {
179 | baseName gateway,
180 | packageName org.contextmapper.generated.gateway,
181 | applicationType gateway
182 | serverPort 8080
183 | }
184 | entities Customer, Address, CustomerAddressChange, UserAccount, PrintingJob, Document, Template, Offer, Product, Contract, Policy, CustomerRiskFactor, Debt, Dunning
185 | }
186 |
187 | /* additional options */
188 | dto * with mapstruct
189 | service * with serviceImpl
190 |
191 |
--------------------------------------------------------------------------------
/src/main/cml/microservice-generation/JDL-example/generated-insurance-microservices.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/src/main/cml/microservice-generation/JDL-example/generated-insurance-microservices.png
--------------------------------------------------------------------------------
/src/main/cml/ooad-sample-claims/README.md:
--------------------------------------------------------------------------------
1 | # OOAD Transformations Applied
2 | On our [Rapid Object-oriented Analysis and Design](https://contextmapper.org/docs/rapid-ooad/) we explain how you can prototype an application with our OOAD
3 | transformations rapidly. This folder contains another example on which we applied this concept.
4 |
5 | ## Use Case: Get Paid for Car Accident
6 | The [example model](./claims-use-case.cml) contains a Use Case of Alistair Cockburn's book on [Writing Effective Use Cases](https://www.amazon.com/Writing-Effective-Cases-Alistair-Cockburn/dp/0201702258).
7 |
8 | ## Application Generation
9 | From the given Use Case we automatically derived the subdomain and the Bounded Context. Then, we generated the [JDL file](./claims-use-case-entities.jdl) from which we are able to generate
10 | a microservice application.
11 |
--------------------------------------------------------------------------------
/src/main/cml/ooad-sample-claims/claims-use-case-entities.jdl:
--------------------------------------------------------------------------------
1 |
2 | /* Bounded Context ClaimsManagement */
3 |
4 | entity Claim {
5 | date LocalDate
6 | amountClaimed Double
7 | description String
8 | claimId Blob
9 | }
10 |
11 |
12 | entity Policy {
13 | startDate LocalDate
14 | endDate LocalDate
15 | policyId Blob
16 | }
17 |
18 |
19 | entity Contract {
20 | contractId Blob
21 | }
22 |
23 |
24 | entity Agent {
25 | personalID Long
26 | firstName String
27 | lastName String
28 | agentId Blob
29 | }
30 |
31 |
32 | entity Claimant {
33 | firstName String
34 | lastName String
35 | claimantId Blob
36 | }
37 |
38 | microservice Claim, Policy, Contract, Agent, Claimant with ClaimsManagement
39 |
40 | application {
41 | config {
42 | baseName ClaimsManagement,
43 | packageName org.contextmapper.generated.claimsmanagement,
44 | applicationType microservice
45 | serverPort 8081
46 | }
47 | entities Claim, Policy, Contract, Agent, Claimant
48 | }
49 |
50 | /* relationships */
51 | relationship OneToMany {
52 | Policy{claims} to Claim
53 | Contract{policies} to Policy
54 | Claimant{claims} to Claim
55 | }
56 | relationship OneToOne {
57 | Claim{agent} to Agent
58 | }
59 |
60 | /* microservice gateway app */
61 | application {
62 | config {
63 | baseName gateway,
64 | packageName org.contextmapper.generated.gateway,
65 | applicationType gateway
66 | serverPort 8080
67 | }
68 | entities Claim, Policy, Contract, Agent, Claimant
69 | }
70 |
71 | /* additional options */
72 | dto * with mapstruct
73 | service * with serviceImpl
74 |
75 |
--------------------------------------------------------------------------------
/src/main/cml/ooad-sample-claims/claims-use-case-entities.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ContextMapper/context-mapper-examples/0854134a15fa70384c4e192cd5e32485ca0d22b5/src/main/cml/ooad-sample-claims/claims-use-case-entities.png
--------------------------------------------------------------------------------
/src/main/cml/ooad-sample-claims/claims-use-case.cml:
--------------------------------------------------------------------------------
1 | /**
2 | * Automatically derived with the OOAD step 3 transformation:
3 | * (adjusted data types in services manually)
4 | *
5 | * After having derived this BC, we generated the claims-use-case-entities.jdl file using our generic generator:
6 | * https://contextmapper.org/docs/generic-freemarker-generator/
7 | */
8 | BoundedContext ClaimsManagement implements ClaimsManagement {
9 | domainVisionStatement "This Bounded Context realizes the following subdomains: ClaimsManagement"
10 | type FEATURE
11 | /* This Aggregate contains the entities and services of the 'ClaimsManagement' subdomain.
12 | * TODO: You can now refactor the Aggregate, for example by using the 'Split Aggregate by Entities' architectural refactoring.
13 | * TODO: Add attributes and operations to the entities.
14 | * TODO: Add operations to the services.
15 | * Find examples and further instructions on our website: https://contextmapper.org/docs/rapid-ooad/ */
16 | Aggregate ClaimsManagementAggregate {
17 | Service AccidentService {
18 | void submitClaim (@Claim claim);
19 | PolicyExistanceVerification verifyExistanceOfPolicy (@Claim claim);
20 | void assignAgent (@Claim claim, @Agent agent);
21 | PolicyVerification verifyPolicy (@Claim claim);
22 | void payClaimant (@Claim claim);
23 | void closeClaim (@Claim claim);
24 | }
25 | Entity Claim {
26 | Date date
27 | Double amountClaimed
28 | String ^description
29 | ClaimID claimId
30 | - Agent agent
31 | }
32 | Entity Policy {
33 | Date startDate
34 | Date endDate
35 | PolicyID policyId
36 | - List claims
37 | }
38 | Entity Contract {
39 | ContractID contractId
40 | - List policies
41 | }
42 | Entity Agent {
43 | Long personalID
44 | String firstName
45 | String lastName
46 | AgentID agentId
47 | }
48 | Entity Claimant {
49 | String firstName
50 | String lastName
51 | ClaimantID claimantId
52 | - List claims
53 | }
54 | }
55 | }
56 |
57 | /**
58 | * Automatically derived with the OOAD step 2 transformation:
59 | * (manually concretized some datatypes)
60 | */
61 | Domain Insurance_Application {
62 | Subdomain ClaimsManagement {
63 | domainVisionStatement "Aims at promoting the following benefit for a Claimant: A claimant submits a claim and and gets paid from the insurance company."
64 | Entity Claim {
65 | Date date
66 | Double amountClaimed
67 | String ^description
68 | - Agent agent
69 | }
70 | Entity Policy {
71 | Date startDate
72 | Date endDate
73 | - List claims
74 | }
75 | Entity Contract {
76 | - List policies
77 | }
78 | Entity Agent {
79 | Long personalID
80 | String firstName
81 | String lastName
82 | }
83 | Entity Claimant {
84 | String firstName
85 | String lastName
86 | - List claims
87 | }
88 | Service AccidentService {
89 | submitClaim;
90 | verifyExistanceOfPolicy;
91 | assignAgent;
92 | verifyPolicy;
93 | payClaimant;
94 | closeClaim;
95 | }
96 | }
97 |
98 | }
99 |
100 | /**
101 | * The following Use Case "Get paid for car accident" has been taken out of Alistair Cockburn's book on "Writing Effective Use Cases".
102 | * Step 1: This is the part of this CML file which has been modeled manually: (all the parts above are generated by our OOAD transformations)
103 | */
104 | UseCase Get_paid_for_car_accident { // title
105 | actor "Claimant" // primary actor
106 | interactions
107 | "submit" a "Claim" with its "date", "amountClaimed", "description" for a "Policy", // step 1: claimant submits claim
108 | "verifyExistanceOf" "Policy" with its "startDate", "endDate" for a "Contract", // step 2: insurance company verifies that valid policy exists
109 | "assign" an "Agent" with its "personalID", "firstName", "lastName" for "Claim", // step 3: agent is assigned to claim
110 | "verify" "Policy" for a "Contract", // step 4: agent verifies all details are within policy guidelines
111 | "pay" "Claimant" with its "firstName", "lastName", // step 5 (1): claimant gets paid
112 | "close" "Claim" for "Claimant" // step 5 (2): file/claim gets closed
113 | benefit "A claimant submits a claim and and gets paid from the insurance company." // story (brief summary)
114 | scope "Insurance company" // scope
115 | level "Summary" // level
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/cml/same-day-delivery-shop/stakeholders-and-values.cml:
--------------------------------------------------------------------------------
1 |
2 |
3 | BoundedContext SameDayDelivery
4 |
5 |
6 | Stakeholders of SameDayDelivery {
7 | StakeholderGroup Online_Shopping_Company {
8 | Stakeholder Development_Team {
9 | influence MEDIUM
10 | interest HIGH
11 | }
12 | Stakeholder Product_Management {
13 | influence HIGH
14 | interest HIGH
15 | }
16 | Stakeholder Customer_Relationship_Manager {
17 | influence HIGH
18 | interest MEDIUM
19 | }
20 | }
21 | StakeholderGroup Product_Suppliers {
22 | Stakeholder Managers
23 | Stakeholder Logistics_Warehouse_Staff_of_Suppliers
24 | Stakeholder Delivery_Staff_of_Suppliers
25 | }
26 | StakeholderGroup Delivery_Partners {
27 | Stakeholder Route_Planners
28 | Stakeholder Drivers
29 | }
30 | StakeholderGroup Competing_Companies
31 |
32 | StakeholderGroup Logistics_Team {
33 | Stakeholder Logistics_Manager
34 | Stakeholder Warehouse_Staff
35 | }
36 | Stakeholder Government
37 |
38 | StakeholderGroup Customers_and_Shoppers {
39 | Stakeholder Shoppers_in_Emergency_Situations
40 | Stakeholder Others
41 | }
42 | }
43 | ValueRegister SD_Values for SameDayDelivery {
44 | ValueCluster Autonomy {
45 | core AUTONOMY
46 | demonstrator "customer values potentially increased freedom"
47 | demonstrator "delivery staff's freedom might suffer because of work-life-balance"
48 | Value Freedom {
49 | Stakeholder Customers_and_Shoppers {
50 | priority HIGH
51 | impact MEDIUM
52 | consequences
53 | good "increased freedom"
54 | }
55 | }
56 | Value Quality_of_Life {
57 | Stakeholder Customers_and_Shoppers {
58 | consequences
59 | good "less stress in emergendy situations"
60 | }
61 | }
62 | Value Sustainability {
63 | Stakeholder Customers_and_Shoppers {
64 | priority HIGH
65 | impact LOW
66 | consequences
67 | bad "fostering unsustainable behavior (always ordering last minute)"
68 | action "Limit Availability of Feature" ACT
69 | }
70 | }
71 | Value Ability_to_be_patient {
72 | Stakeholder Customers_and_Shoppers {
73 | priority MEDIUM
74 | impact HIGH
75 | consequences
76 | bad "patience of customer will further increase"
77 | action "Only allow feature for emergency (don't make it the default)" ACT
78 | }
79 | }
80 | }
81 | Value WorkLifeBalance {
82 | isCore
83 | demonstrator "Drivers value a healthy work-life-balance"
84 | Stakeholder Drivers {
85 | priority HIGH
86 | impact HIGH
87 | consequences
88 | bad "SDD will harm work-life-balance of drivers"
89 | action "hire more drivers, adjust availability to workload" ACT
90 | }
91 | }
92 | Value Revenue {
93 | demonstrator "Online shopping company needs revenue"
94 | Stakeholder Online_Shopping_Company {
95 | priority HIGH
96 | impact MEDIUM
97 | consequences
98 | good "increased number of customers"
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/cml/service-coordination-example/InsuranceClaimCoordination.cml:
--------------------------------------------------------------------------------
1 | /**
2 | * Example coordination of services between three Bounded Contexts.
3 | *
4 | */
5 | ContextMap {
6 | contains ClaimsManagement
7 | contains InsuranceManagement
8 | contains PaymentManagement
9 |
10 | ClaimsManagement <-> InsuranceManagement
11 |
12 | ClaimsManagement <-> PaymentManagement
13 | }
14 |
15 | BoundedContext ClaimsManagement {
16 | Application {
17 |
18 | Coordination SubmitValidClaimCoordination {
19 | ClaimsManagement::ClaimsApplicationService::submitClaim;
20 | InsuranceManagement::InsuranceApplicationService::checkInsurance;
21 | ClaimsManagement::ClaimsApplicationService::acceptClaim;
22 | PaymentManagement::PaymentApplicationService::performPayment;
23 | }
24 |
25 | Service ClaimsApplicationService {
26 | void submitClaim(@Claim claim);
27 | void acceptClaim(@Claim claim);
28 | }
29 | }
30 |
31 | Aggregate Claims {
32 | Entity Claim
33 | }
34 | }
35 |
36 | BoundedContext InsuranceManagement {
37 | Application {
38 | Service InsuranceApplicationService {
39 | void checkInsurance(@Claim claim);
40 | }
41 | }
42 | }
43 |
44 | BoundedContext PaymentManagement {
45 | Application {
46 | Service PaymentApplicationService {
47 | void performPayment(@Claim claim);
48 | }
49 | }
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/src/main/cml/workflow-samples/ClaimsManagement_with_Commands.cml:
--------------------------------------------------------------------------------
1 | BoundedContext ClaimsManagement {
2 | Application {
3 | Command SubmitClaim
4 | Command CheckClaimDocumentation
5 | Command CheckInsurance
6 | Command AcceptClaim
7 | Command RejectClaim
8 | Command SchedulePayment
9 | Command NofifyCustomer
10 |
11 | Flow ClaimsFlow {
12 | command SubmitClaim emits event ClaimSubmitted
13 | event ClaimSubmitted triggers command CheckClaimDocumentation
14 |
15 | command CheckClaimDocumentation emits event ClaimRegistered
16 | event ClaimRegistered triggers command CheckInsurance
17 | command CheckInsurance emits event AssessmentPerformed
18 | event AssessmentPerformed triggers command AcceptClaim X RejectClaim // X: alternative command invokation (exclusive; only one);
19 | // +: concurrent command invokation (all commands called);
20 | // O: alternative command invokation (inclusive; one or multiple)
21 |
22 | command AcceptClaim delegates to Claims [OPEN -> ACCEPTED] emits event ClaimAccepted // optional: define state transition that is done on command invokation
23 | command RejectClaim delegates to Claims [OPEN -> REJECTED] emits event ClaimRejected
24 |
25 | event ClaimAccepted triggers command SchedulePayment
26 | command SchedulePayment emits event PaymentPerformed
27 |
28 | event PaymentPerformed triggers command NofifyCustomer
29 | event ClaimRejected triggers command NofifyCustomer
30 |
31 | command NofifyCustomer delegates to Claims [ACCEPTED, REJECTED -> CUSTOMER_NOTIFIED] emits event CustomerNotified
32 | }
33 | }
34 |
35 | Aggregate Claims {
36 | Entity Claim {
37 | aggregateRoot
38 | long claimId
39 | CustomerId customer
40 | String ^description
41 | Blob requestDocument
42 | boolean isComplete
43 | boolean isAssessed
44 | - ClaimState claimState
45 | }
46 | enum ClaimState {
47 | aggregateLifecycle // enum marked as "state defining" for this aggregate
48 | OPEN, REJECTED, ACCEPTED, CUSTOMER_NOTIFIED
49 | }
50 |
51 | DomainEvent ClaimSubmitted
52 | DomainEvent ClaimRegistered
53 | DomainEvent AssessmentPerformed
54 | DomainEvent ClaimAccepted
55 | DomainEvent ClaimRejected
56 | DomainEvent PaymentPerformed
57 | DomainEvent CustomerNotified
58 | }
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/src/main/cml/workflow-samples/ClaimsManagement_with_ServiceOperations.cml:
--------------------------------------------------------------------------------
1 | BoundedContext ClaimsManagement {
2 | Application {
3 | Service ClaimsApplicationService {
4 | void submitClaim(@Claim claim);
5 | void checkClaimDocumentation(@Claim claim);
6 | void checkInsurance(@Claim claim);
7 | void acceptClaim(@Claim claim);
8 | void rejectClaim(@Claim claim);
9 | void schedulePayment(@Claim claim);
10 | void nofifyCustomer(@Claim claim);
11 | }
12 |
13 | Flow ClaimsFlow {
14 | operation submitClaim emits event ClaimSubmitted
15 | event ClaimSubmitted triggers operation checkClaimDocumentation
16 |
17 | operation checkClaimDocumentation emits event ClaimRegistered
18 | event ClaimRegistered triggers operation checkInsurance
19 | operation checkInsurance emits event AssessmentPerformed
20 | event AssessmentPerformed triggers operation acceptClaim X rejectClaim // X: alternative command invokation (exclusive; only one);
21 | // +: concurrent command invokation (all commands called);
22 | // O: alternative command invokation (inclusive; one or multiple)
23 |
24 | operation acceptClaim delegates to Claims [OPEN -> ACCEPTED] emits event ClaimAccepted // optional: define state transition that is done on command invokation
25 | operation rejectClaim delegates to Claims [OPEN -> REJECTED] emits event ClaimRejected
26 |
27 | event ClaimAccepted triggers operation schedulePayment
28 | operation schedulePayment emits event PaymentPerformed
29 |
30 | event PaymentPerformed triggers operation nofifyCustomer
31 | event ClaimRejected triggers operation nofifyCustomer
32 |
33 | operation nofifyCustomer delegates to Claims[ACCEPTED, REJECTED -> CUSTOMER_NOTIFIED] emits event CustomerNotified
34 | }
35 | }
36 |
37 | Aggregate Claims {
38 | Entity Claim {
39 | aggregateRoot
40 | long claimId
41 | CustomerId customer
42 | String ^description
43 | Blob requestDocument
44 | boolean isComplete
45 | boolean isAssessed
46 | - ClaimState claimState
47 | }
48 | enum ClaimState {
49 | aggregateLifecycle
50 | OPEN, REJECTED, ACCEPTED, CUSTOMER_NOTIFIED
51 | }
52 |
53 | DomainEvent ClaimSubmitted
54 | DomainEvent ClaimRegistered
55 | DomainEvent AssessmentPerformed
56 | DomainEvent ClaimAccepted
57 | DomainEvent ClaimRejected
58 | DomainEvent PaymentPerformed
59 | DomainEvent CustomerNotified
60 | }
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/src/main/cml/workflow-samples/InsuranceQuoteRequest.cml:
--------------------------------------------------------------------------------
1 | /**
2 | * A RequestStatus is a value object that is used to represent
3 | * the current status of an insurance quote request.
4 | *
5 | * The following diagram shows the possible state transitions:
6 | *
7 | *
8 | *
9 | * │
10 | * ▼
11 | * ┌────────────┐
12 | * │ REQUEST_ │
13 | * │ SUBMITTED │
14 | * └────────────┘
15 | * │
16 | * ┌─────────────────┴────────────────┐
17 | * │ │
18 | * ▼ ▼
19 | * ┌────────────┐ ╔════════════╗
20 | * │ QUOTE_ │ ║ REQUEST_ ║
21 | * ┌───────────│ RECEIVED │─────────────┐ ║ REJECTED ║
22 | * │ └────────────┘ │ ╚════════════╝
23 | * │ │ │
24 | * │ │ │
25 | * ▼ ▼ ▼
26 | * ╔════════════╗ ┌────────────┐ ╔════════════╗
27 | * ║ QUOTE_ ║ │ QUOTE_ │ ║ QUOTE_ ║
28 | * ║ REJECTED ║ │ ACCEPTED │─────▶║ EXPIRED ║
29 | * ╚════════════╝ └────────────┘ ╚════════════╝
30 | * │
31 | * │
32 | * ▼
33 | * ╔════════════╗
34 | * ║ POLICY_ ║
35 | * ║ CREATED ║
36 | * ╚════════════╝
37 | *
38 | *
39 | */
40 | BoundedContext InsuranceQuotes {
41 |
42 | Aggregate QuoteRequest {
43 | Entity Request {
44 | aggregateRoot
45 | }
46 |
47 | DomainEvent RequestSubmitted
48 | DomainEvent QuoteReceived
49 | DomainEvent RequestRejected
50 | DomainEvent QuoteRejected
51 | DomainEvent QuoteAccepted
52 | DomainEvent QuoteExpired
53 | DomainEvent PolicyCreated
54 |
55 | Service QuoteRequestService {
56 | void checkRequest(@Request request);
57 | void receiveAndCheckQuote(@Request request);
58 | void reject(@Request request);
59 | void accept(@Request request);
60 | }
61 |
62 | enum RequestState {
63 | aggregateLifecycle
64 | SUBMITTED, RECEIVED, REJECTED, ACCEPTED, EXPIRED, POLICY_CREATED
65 | }
66 | }
67 |
68 | Application {
69 | Command SubmitRequest // command triggered by user
70 |
71 | Flow QuoteFlow {
72 | command SubmitRequest delegates to QuoteRequest[-> SUBMITTED] emits event RequestSubmitted
73 | event RequestSubmitted triggers operation checkRequest
74 | operation checkRequest delegates to QuoteRequest[SUBMITTED -> RECEIVED X REJECTED] emits event QuoteReceived X RequestRejected
75 | event QuoteReceived triggers operation receiveAndCheckQuote
76 | operation receiveAndCheckQuote delegates to QuoteRequest[RECEIVED -> REJECTED X ACCEPTED X EXPIRED] emits event QuoteRejected X QuoteAccepted X QuoteExpired
77 | event QuoteAccepted triggers operation accept
78 | operation accept delegates to QuoteRequest[ACCEPTED -> POLICY_CREATED X EXPIRED] emits event PolicyCreated X QuoteExpired
79 | }
80 | }
81 |
82 | }
--------------------------------------------------------------------------------
/src/main/cml/workflow-samples/InsuranceQuoteRequest_StateMachineWithoutEventsAndCommands.cml:
--------------------------------------------------------------------------------
1 | /**
2 | * A RequestStatus is a value object that is used to represent
3 | * the current status of an insurance quote request.
4 | *
5 | * The following diagram shows the possible state transitions:
6 | *
7 | *
8 | *
9 | * │
10 | * ▼
11 | * ┌────────────┐
12 | * │ REQUEST_ │
13 | * │ SUBMITTED │
14 | * └────────────┘
15 | * │
16 | * ┌─────────────────┴────────────────┐
17 | * │ │
18 | * ▼ ▼
19 | * ┌────────────┐ ╔════════════╗
20 | * │ QUOTE_ │ ║ REQUEST_ ║
21 | * ┌───────────│ RECEIVED │─────────────┐ ║ REJECTED ║
22 | * │ └────────────┘ │ ╚════════════╝
23 | * │ │ │
24 | * │ │ │
25 | * ▼ ▼ ▼
26 | * ╔════════════╗ ┌────────────┐ ╔════════════╗
27 | * ║ QUOTE_ ║ │ QUOTE_ │ ║ QUOTE_ ║
28 | * ║ REJECTED ║ │ ACCEPTED │─────▶║ EXPIRED ║
29 | * ╚════════════╝ └────────────┘ ╚════════════╝
30 | * │
31 | * │
32 | * ▼
33 | * ╔════════════╗
34 | * ║ POLICY_ ║
35 | * ║ CREATED ║
36 | * ╚════════════╝
37 | *
38 | *
39 | */
40 | BoundedContext InsuranceQuotes {
41 |
42 | Aggregate QuoteRequest {
43 | Entity QuoteRequest {
44 | aggregateRoot
45 | }
46 |
47 | Service QuoteRequestService {
48 | // just grammar examples:
49 | // @Object readOperation() : read-only;
50 | // void writeOperation(@Object param) : write;
51 | // void writeOperation(@Object param) : write [STATE1 -> STATE2];
52 | // void writeOperation(@Object param) : write [STATE1 -> STATE2 X STATE3];
53 |
54 | void submitRequest(@QuoteRequest request) : write [-> REQUEST_SUBMITTED];
55 | void rejectRequest(@QuoteRequest request): write [REQUEST_SUBMITTED -> REQUEST_REJECTED];
56 | void receiveQuote(@QuoteRequest request) : write [REQUEST_SUBMITTED -> QUOTE_RECEIVED];
57 | void checkQuote(@QuoteRequest request) : write [QUOTE_RECEIVED -> QUOTE_REJECTED X QUOTE_ACCEPTED X QUOTE_EXPIRED];
58 | void createPolicy(@QuoteRequest request) : write [QUOTE_ACCEPTED -> POLICY_CREATED X QUOTE_EXPIRED];
59 |
60 | // void getRequest(RequestId requestId) : read-only;
61 |
62 | // + : parallel gateway (AND)
63 | // X : exclusive gateway (XOR)
64 | // O : inclusive gateway (OR)
65 | }
66 |
67 | enum RequestState {
68 | aggregateLifecycle
69 | REQUEST_SUBMITTED, QUOTE_RECEIVED, REQUEST_REJECTED, QUOTE_ACCEPTED, QUOTE_REJECTED, QUOTE_EXPIRED, POLICY_CREATED
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/cml/workflow-samples/InsuranceQuoteRequest_StateMachineWithoutEventsAndCommands_Entity.cml:
--------------------------------------------------------------------------------
1 | /**
2 | * A RequestStatus is a value object that is used to represent
3 | * the current status of an insurance quote request.
4 | *
5 | * The following diagram shows the possible state transitions:
6 | *
7 | *
8 | *
9 | * │
10 | * ▼
11 | * ┌────────────┐
12 | * │ REQUEST_ │
13 | * │ SUBMITTED │
14 | * └────────────┘
15 | * │
16 | * ┌─────────────────┴────────────────┐
17 | * │ │
18 | * ▼ ▼
19 | * ┌────────────┐ ╔════════════╗
20 | * │ QUOTE_ │ ║ REQUEST_ ║
21 | * ┌───────────│ RECEIVED │─────────────┐ ║ REJECTED ║
22 | * │ └────────────┘ │ ╚════════════╝
23 | * │ │ │
24 | * │ │ │
25 | * ▼ ▼ ▼
26 | * ╔════════════╗ ┌────────────┐ ╔════════════╗
27 | * ║ QUOTE_ ║ │ QUOTE_ │ ║ QUOTE_ ║
28 | * ║ REJECTED ║ │ ACCEPTED │─────▶║ EXPIRED ║
29 | * ╚════════════╝ └────────────┘ ╚════════════╝
30 | * │
31 | * │
32 | * ▼
33 | * ╔════════════╗
34 | * ║ POLICY_ ║
35 | * ║ CREATED ║
36 | * ╚════════════╝
37 | *
38 | *
39 | */
40 | BoundedContext InsuranceQuotes {
41 |
42 | Aggregate QuoteRequest {
43 |
44 | // also possible on Entity operations:
45 | Entity QuoteRequest {
46 | aggregateRoot
47 |
48 | // just grammar examples:
49 | // def @Object readOperation() : read-only;
50 | // def void writeOperation(@Object param) : write;
51 | // def void writeOperation(@Object param) : write [STATE1 -> STATE2];
52 | // def void writeOperation(@Object param) : write [STATE1 -> STATE2 X STATE3];
53 |
54 | def void submit() : write [-> REQUEST_SUBMITTED];
55 | def void reject(): write [REQUEST_SUBMITTED -> REQUEST_REJECTED];
56 | def void receiveQuote() : write [REQUEST_SUBMITTED -> QUOTE_RECEIVED];
57 | def void checkQuote() : write [QUOTE_RECEIVED -> QUOTE_REJECTED X QUOTE_ACCEPTED X QUOTE_EXPIRED];
58 | def void createPolicy() : write [QUOTE_ACCEPTED -> POLICY_CREATED X QUOTE_EXPIRED];
59 | }
60 |
61 | enum RequestState {
62 | aggregateLifecycle
63 | REQUEST_SUBMITTED, QUOTE_RECEIVED, REQUEST_REJECTED, QUOTE_ACCEPTED, QUOTE_REJECTED, QUOTE_EXPIRED, POLICY_CREATED
64 | }
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------