diff --git a/404.html b/404.html index 2c68768..feaa3b2 100644 --- a/404.html +++ b/404.html @@ -1,8 +1,11 @@ --- layout: default +title: Page not found +permalink: /404.html --- -
-

The page you are looking for cannot be found.

-

404

+
+

404

+

Page not found

+

The page you are looking for does not exist (anymore). Try the search above, or start from the documentation.

diff --git a/LICENSE b/LICENSE index 4926de5..261eeb9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,201 @@ -MIT License - -Copyright (c) 2017 Can Güney Aksakalli - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 21a7787..b5407ff 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Context Mapper](https://raw.githubusercontent.com/wiki/ContextMapper/context-mapper-dsl/logo/cm-logo-github-small.png) # contextmapper.org -[![Build & Deploy Website](https://github.com/ContextMapper/contextmapper.github.io/actions/workflows/deploy.yml/badge.svg)](https://github.com/ContextMapper/contextmapper.github.io/actions/workflows/deploy.yml) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) +[![Build & Deploy Website](https://github.com/ContextMapper/contextmapper.github.io/actions/workflows/deploy.yml/badge.svg)](https://github.com/ContextMapper/contextmapper.github.io/actions/workflows/deploy.yml) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) This is the repository of Context Mapper's website [https://contextmapper.org/](https://contextmapper.org/). @@ -25,9 +25,27 @@ To preview the website locally, follow these steps: bundle exec jekyll serve ``` +## Writing Documentation +CML code blocks are highlighted by our own Rouge lexer ([`_plugins/cml_lexer.rb`](_plugins/cml_lexer.rb)); use `cml` as language: + +````markdown +```cml +BoundedContext CustomerManagementContext implements CustomerManagementDomain { + type = FEATURE +} +``` +```` + +When the CML grammar gets new keywords, add them to the lexer as well. + +For [MDSL](https://microservice-api-patterns.github.io/MDSL-Specification/) examples (for example, generated service contracts), use `mdsl` ([`_plugins/mdsl_lexer.rb`](_plugins/mdsl_lexer.rb), keywords from the MDSL grammar). + ## Deployment and Previews * **Production:** every push to `master` is built with Jekyll and deployed to [https://contextmapper.org/](https://contextmapper.org/) (GitHub Pages) by the [Build & Deploy Website](.github/workflows/deploy.yml) workflow. Pull requests are built (but not deployed) by the same workflow. * **Previews:** to review changes in the browser before merging them, run the [Deploy Preview (manual)](.github/workflows/preview.yml) workflow on your branch (_Actions_ > _Deploy Preview (manual)_ > _Run workflow_ > select the branch). The branch is deployed to Cloudflare Pages and the URL is shown in the workflow run summary (`https://.contextmapper-preview.pages.dev`). The previews are protected by Cloudflare Access; ask a maintainer to get access. ## Contribution If you think something is missing on our documentation website and you still have unanswered questions, we are happy if you create an issue [here](https://github.com/ContextMapper/contextmapper.github.io/issues) allowing us to improve the docs. PRs are always welcome as well! + +## License +This website is released under the [Apache License, Version 2.0](LICENSE). The fonts in `assets/fonts` ([Inter](https://github.com/rsms/inter) and [JetBrains Mono](https://github.com/JetBrains/JetBrainsMono)) are licensed under the [SIL Open Font License 1.1](assets/fonts). diff --git a/_config.yml b/_config.yml index f1cdd82..fc27bcf 100644 --- a/_config.yml +++ b/_config.yml @@ -15,10 +15,6 @@ git_edit_address: https://github.com/ContextMapper/contextmapper.github.io/blob/ twitter: card: "summary_large_image" -# theme options from https://bootswatch.com/ -# comment out this to use default Bootstrap -bootwatch: paper - # Build settings markdown: kramdown highlighter: rouge diff --git a/_docs/examples.md b/_docs/examples.md index 1860e31..69f4f39 100644 --- a/_docs/examples.md +++ b/_docs/examples.md @@ -12,12 +12,12 @@ The following graphical illustrations of our sample Context Maps are inspired by ## Insurance Example Link: [https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/insurance-example](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/insurance-example) -Insurance Company Example Context Map +Insurance Company Example Context Map ## DDD Sample Link: [https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/ddd-sample](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/ddd-sample) -DDD Sample Context Map +DDD Sample Context Map ## Architectural Refactoring (AR) Examples The following folder contains a number of small CML snippets from the insurance example; they illustrate how you can apply refactorings to your models: diff --git a/_docs/generators/bpmn-sketch-miner.md b/_docs/generators/bpmn-sketch-miner.md index bd235d3..0f49fb0 100644 --- a/_docs/generators/bpmn-sketch-miner.md +++ b/_docs/generators/bpmn-sketch-miner.md @@ -9,48 +9,49 @@ We use the [BPMN Sketch Miner](https://www.bpmn-sketch-miner.ai/) tool to visual ## Example Flow The following CML code illustrates how you can model flows. A complete documentation on the syntax can be found in the [language reference](/docs/application-and-process-layer/#processes-and-eventcommand-flows). -
/**
- * A flow inspired by the Lakeside Mutual project (https://github.com/Microservice-API-Patterns/LakesideMutual).
- * Find the original process visualization here:
- * https://github.com/Microservice-API-Patterns/LakesideMutual/blob/master/policy-management-backend/src/main/java/com/lakesidemutual/policymanagement/domain/insurancequoterequest/RequestStatus.java
- **/
-BoundedContext InsuranceQuotes {
-  Application {
-    Flow QuoteRequestFlow {
-      operation submitRequest delegates to QuoteRequest[-> SUBMITTED] emits event RequestSubmitted
-      event RequestSubmitted + RequestSubmitted triggers operation checkRequest
-      operation checkRequest delegates to QuoteRequest[SUBMITTED -> RECEIVED X REJECTED] emits event QuoteReceived X RequestRejected
-      event QuoteReceived triggers operation receiveAndCheckQuote
-      operation receiveAndCheckQuote delegates to QuoteRequest[RECEIVED -> REJECTED X ACCEPTED X EXPIRED] emits event QuoteRejected X QuoteAccepted X QuoteExpired
-      event QuoteAccepted triggers operation accept
-      operation accept delegates to QuoteRequest[ACCEPTED -> POLICY_CREATED X EXPIRED] emits event PolicyCreated X QuoteExpired
+```cml
+/**
+ * A flow inspired by the Lakeside Mutual project (https://github.com/Microservice-API-Patterns/LakesideMutual).
+ * Find the original process visualization here:
+ * https://github.com/Microservice-API-Patterns/LakesideMutual/blob/master/policy-management-backend/src/main/java/com/lakesidemutual/policymanagement/domain/insurancequoterequest/RequestStatus.java
+ **/
+BoundedContext InsuranceQuotes {
+  Application {
+    Flow QuoteRequestFlow {
+      operation submitRequest delegates to QuoteRequest[-> SUBMITTED] emits event RequestSubmitted
+      event RequestSubmitted + RequestSubmitted triggers operation checkRequest
+      operation checkRequest delegates to QuoteRequest[SUBMITTED -> RECEIVED X REJECTED] emits event QuoteReceived X RequestRejected
+      event QuoteReceived triggers operation receiveAndCheckQuote
+      operation receiveAndCheckQuote delegates to QuoteRequest[RECEIVED -> REJECTED X ACCEPTED X EXPIRED] emits event QuoteRejected X QuoteAccepted X QuoteExpired
+      event QuoteAccepted triggers operation accept
+      operation accept delegates to QuoteRequest[ACCEPTED -> POLICY_CREATED X EXPIRED] emits event PolicyCreated X QuoteExpired
     }
   }
-  Aggregate QuoteRequest {
-    Entity Request {
-      aggregateRoot
+  Aggregate QuoteRequest {
+    Entity Request {
+      aggregateRoot
     }
-    DomainEvent RequestSubmitted
-    DomainEvent QuoteReceived
-    DomainEvent RequestRejected
-    DomainEvent QuoteRejected
-    DomainEvent QuoteAccepted
-    DomainEvent QuoteExpired
-    DomainEvent PolicyCreated
-    Service QuoteRequestService {
-      void submitRequest(@Request request);
-      void checkRequest(@Request request);
-      void receiveAndCheckQuote(@Request request);
-      void reject(@Request request);
-      void accept(@Request request);
+    DomainEvent RequestSubmitted
+    DomainEvent QuoteReceived
+    DomainEvent RequestRejected
+    DomainEvent QuoteRejected
+    DomainEvent QuoteAccepted
+    DomainEvent QuoteExpired
+    DomainEvent PolicyCreated
+    Service QuoteRequestService {
+      void submitRequest(@Request request);
+      void checkRequest(@Request request);
+      void receiveAndCheckQuote(@Request request);
+      void reject(@Request request);
+      void accept(@Request request);
     }
-    enum RequestState {
-      aggregateLifecycle
+    enum RequestState {
+      aggregateLifecycle
        SUBMITTED, RECEIVED, REJECTED, ACCEPTED, EXPIRED, POLICY_CREATED
     }
   }
 }
-
+``` ## Open Flow in BPMN Sketch Miner The Context Mapper IDEs ([VS Code extension](/docs/vs-code/) as well as [Eclipse plugin](/docs/eclipse/)) allow you to open a flow in [BPMN Sketch Miner](https://www.bpmn-sketch-miner.ai/) with two (or max. three) clicks. The following example illustrates this in VS Code (Eclipse works the same way). diff --git a/_docs/generators/context-map-generator.md b/_docs/generators/context-map-generator.md index c0bf70c..cf7fae0 100644 --- a/_docs/generators/context-map-generator.md +++ b/_docs/generators/context-map-generator.md @@ -12,18 +12,19 @@ and [Brandolini](https://www.infoq.com/articles/ddd-contextmapping/). ## Examples The following CML Context Map represents the DDD cargo sample application (find the complete CML file [here](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/ddd-sample)): -
ContextMap DDDSampleMap {
-  contains CargoBookingContext
-  contains VoyagePlanningContext
-  contains LocationContext
+```cml
+ContextMap DDDSampleMap {
+  contains CargoBookingContext
+  contains VoyagePlanningContext
+  contains LocationContext
 
-  CargoBookingContext [SK]<->[SK] VoyagePlanningContext
+  CargoBookingContext [SK]<->[SK] VoyagePlanningContext
 
-  CargoBookingContext [D]<-[U,OHS,PL] LocationContext
+  CargoBookingContext [D]<-[U,OHS,PL] LocationContext
 
-  VoyagePlanningContext [D]<-[U,OHS,PL] LocationContext
+  VoyagePlanningContext [D]<-[U,OHS,PL] LocationContext
 }
-
+``` Using our generator produces the following graphical Context Map for you: @@ -32,50 +33,51 @@ Using our generator produces the following graphical Context Map for you: As a second example, the following Context Map represents our [insurance company example](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/insurance-example) (find the complete CML file [here](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/insurance-example)): -
ContextMap InsuranceContextMap {
-  type = SYSTEM_LANDSCAPE
-  state = TO_BE
+```cml
+ContextMap InsuranceContextMap {
+  type = SYSTEM_LANDSCAPE
+  state = TO_BE
 
-  /* Add bounded contexts to this context map: */
-  contains CustomerManagementContext, CustomerSelfServiceContext, PrintingContext
-  contains PolicyManagementContext, RiskManagementContext, DebtCollection
+  /* Add bounded contexts to this context map: */
+  contains CustomerManagementContext, CustomerSelfServiceContext, PrintingContext
+  contains PolicyManagementContext, RiskManagementContext, DebtCollection
 
-  /* Define the context relationships: */
+  /* Define the context relationships: */
 
-  CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext {
-    exposedAggregates = Customers
+  CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext {
+    exposedAggregates = Customers
   }
 
-  CustomerManagementContext [D,ACL]<-[U,OHS,PL] PrintingContext {
-    implementationTechnology = "SOAP"
-    downstreamRights = INFLUENCER
-    exposedAggregates = Printing
+  CustomerManagementContext [D,ACL]<-[U,OHS,PL] PrintingContext {
+    implementationTechnology = "SOAP"
+    downstreamRights = INFLUENCER
+    exposedAggregates = Printing
   }
 
-  PrintingContext [U,OHS,PL]->[D,ACL] PolicyManagementContext {
-    implementationTechnology = "SOAP"
-    exposedAggregates = Printing
+  PrintingContext [U,OHS,PL]->[D,ACL] PolicyManagementContext {
+    implementationTechnology = "SOAP"
+    exposedAggregates = Printing
   }
 
-  RiskManagementContext [P]<->[P] PolicyManagementContext {
-    implementationTechnology = "RabbitMQ"
+  RiskManagementContext [P]<->[P] PolicyManagementContext {
+    implementationTechnology = "RabbitMQ"
   }
 
-  PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
-    implementationTechnology = "RESTfulHTTP"
-    exposedAggregates = Customers
+  PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
+    implementationTechnology = "RESTfulHTTP"
+    exposedAggregates = Customers
   }
 
-  DebtCollection [D,ACL]<-[U,OHS,PL] PrintingContext {
-    implementationTechnology = "SOAP"
-    exposedAggregates = Printing
+  DebtCollection [D,ACL]<-[U,OHS,PL] PrintingContext {
+    implementationTechnology = "SOAP"
+    exposedAggregates = Printing
   }
 
-  PolicyManagementContext [SK]<->[SK] DebtCollection {
-    implementationTechnology = "Shared Java Library, Communication over RESTful HTTP"
+  PolicyManagementContext [SK]<->[SK] DebtCollection {
+    implementationTechnology = "Shared Java Library, Communication over RESTful HTTP"
   }
 }
-
+``` Our generator produces the following graphical result for the above Context Map: @@ -83,54 +85,55 @@ Our generator produces the following graphical result for the above Context Map: Besides Context Maps of the type _SYSTEM\_LANDSCAPE_, CML allows you to create maps that illustrate which development teams work on which subsystems or components (Context Map type _ORGANZATIONAL_). The following CML example illustrates how this can be done: -
ContextMap InsuranceTeamMap {
-  type = ORGANIZATIONAL
-  state = TO_BE
-  
-  /* Add contexts that represent subsystems/components to this organizational map: */
-  contains CustomerManagementContext, CustomerSelfServiceContext, PolicyManagementContext, RiskManagementContext
-
-  /* Add teams to this organizational map: */
-  contains CustomersBackofficeTeam, CustomersFrontofficeTeam, ContractsTeam
-  
-  /* Define the subsystem/component relationships: */
-
-  CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext
-
-  PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext
-    
-  PolicyManagementContext [P]<->[P] RiskManagementContext
-
-  /* Define the team relationships: */
-   
-  CustomersBackofficeTeam [U,S]->[D,C] CustomersFrontofficeTeam
-  
-  CustomersBackofficeTeam [U]->[D] ContractsTeam
-  
+```cml
+ContextMap InsuranceTeamMap {
+  type = ORGANIZATIONAL
+  state = TO_BE
+
+  /* Add contexts that represent subsystems/components to this organizational map: */
+  contains CustomerManagementContext, CustomerSelfServiceContext, PolicyManagementContext, RiskManagementContext
+
+  /* Add teams to this organizational map: */
+  contains CustomersBackofficeTeam, CustomersFrontofficeTeam, ContractsTeam
+
+  /* Define the subsystem/component relationships: */
+
+  CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext
+
+  PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext
+
+  PolicyManagementContext [P]<->[P] RiskManagementContext
+
+  /* Define the team relationships: */
+
+  CustomersBackofficeTeam [U,S]->[D,C] CustomersFrontofficeTeam
+
+  CustomersBackofficeTeam [U]->[D] ContractsTeam
+
 }
 
-/* Team Definitions */
-BoundedContext CustomersBackofficeTeam realizes CustomerManagementContext {
-  type = TEAM
-  domainVisionStatement = "This team is responsible for implementing the customers module in the back-office system."
+/* Team Definitions */
+BoundedContext CustomersBackofficeTeam realizes CustomerManagementContext {
+  type = TEAM
+  domainVisionStatement = "This team is responsible for implementing the customers module in the back-office system."
 }
 
-BoundedContext CustomersFrontofficeTeam realizes CustomerSelfServiceContext {
-  type = TEAM
-  domainVisionStatement = "This team is responsible for implementing the front-office application for the insurance customers."
+BoundedContext CustomersFrontofficeTeam realizes CustomerSelfServiceContext {
+  type = TEAM
+  domainVisionStatement = "This team is responsible for implementing the front-office application for the insurance customers."
 }
 
-BoundedContext ContractsTeam realizes PolicyManagementContext, RiskManagementContext {
-  type = TEAM
-  domainVisionStatement = "This team is responsible for implementing the contract-, policy-, and risk-management modules in the back-office system."
+BoundedContext ContractsTeam realizes PolicyManagementContext, RiskManagementContext {
+  type = TEAM
+  domainVisionStatement = "This team is responsible for implementing the contract-, policy-, and risk-management modules in the back-office system."
 }
 
-/* Subsystem/component definitions */
-BoundedContext CustomerManagementContext
-BoundedContext CustomerSelfServiceContext
-BoundedContext PolicyManagementContext
-BoundedContext RiskManagementContext
-
+/* Subsystem/component definitions */ +BoundedContext CustomerManagementContext +BoundedContext CustomerSelfServiceContext +BoundedContext PolicyManagementContext +BoundedContext RiskManagementContext +``` Depending on how you configure the the generator (clustering parameter), it will generate one of the following visualizations for you. Not clustered: diff --git a/_docs/generators/generators.md b/_docs/generators/generators.md index 276442a..36bce41 100644 --- a/_docs/generators/generators.md +++ b/_docs/generators/generators.md @@ -57,47 +57,48 @@ assistance regarding how to implement your system as a (micro-)service-oriented This is an examplary [MDSL](https://microservice-api-patterns.github.io/MDSL-Specification/) service contract for our [insurance example](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/insurance-example): -
// Generated from DDD Context Map 'Insurance-Example_Context-Map.cml' at 21.10.2019 17:48:52 CEST.
-API description CustomerManagementContextAPI
-usage context PUBLIC_API for BACKEND_INTEGRATION
-
-data type Address { "street":V<string>, "postalCode":V<int>, "city":V<string> }
-data type AddressId P
-data type changeCustomerParameter { "firstname":V<string>, "lastname":V<string> }
-
-endpoint type CustomersAggregate
-  serves as INFORMATION_HOLDER_RESOURCE
-  exposes
-    operation createAddress
-      with responsibility "Creates new address for customer"
-      expecting
-        payload Address
-      delivering
-        payload AddressId
-    operation changeCustomer
-      with responsibility "Changes existing customer address"
-      expecting
-        payload changeCustomerParameter
-      delivering
-        payload V<bool>
-
-// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL).
-API provider CustomerManagementContextProvider
-  // The customer management context is responsible for managing all the data of the insurance companies customers.
-  offers CustomersAggregate
-  at endpoint location "http://localhost:8001"
-    via protocol "RESTfulHTTP"
-
-// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL).
-API client PolicyManagementContextClient
-  // This bounded context manages the contracts and policies of the customers.
-  consumes CustomersAggregate
-API client CustomerSelfServiceContextClient
-  // This context represents a web application which allows the customer to login and change basic data records like the address.
-  consumes CustomersAggregate
-
-IPA
-
+```mdsl +// Generated from DDD Context Map 'Insurance-Example_Context-Map.cml' at 21.10.2019 17:48:52 CEST. +API description CustomerManagementContextAPI +usage context PUBLIC_API for BACKEND_INTEGRATION + +data type Address { "street":V, "postalCode":V, "city":V } +data type AddressId P +data type changeCustomerParameter { "firstname":V, "lastname":V } + +endpoint type CustomersAggregate + serves as INFORMATION_HOLDER_RESOURCE + exposes + operation createAddress + with responsibility "Creates new address for customer" + expecting + payload Address + delivering + payload AddressId + operation changeCustomer + with responsibility "Changes existing customer address" + expecting + payload changeCustomerParameter + delivering + payload V + +// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL). +API provider CustomerManagementContextProvider + // The customer management context is responsible for managing all the data of the insurance companies customers. + offers CustomersAggregate + at endpoint location "http://localhost:8001" + via protocol "RESTfulHTTP" + +// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL). +API client PolicyManagementContextClient + // This bounded context manages the contracts and policies of the customers. + consumes CustomersAggregate +API client CustomerSelfServiceContextClient + // This context represents a web application which allows the customer to login and change basic data records like the address. + consumes CustomersAggregate + +IPA +``` Learn more about the [MDSL](https://microservice-api-patterns.github.io/MDSL-Specification/) generator [here](/docs/mdsl/). diff --git a/_docs/generators/generic-freemarker-generator.md b/_docs/generators/generic-freemarker-generator.md index 6c6a4bc..8c044b7 100644 --- a/_docs/generators/generic-freemarker-generator.md +++ b/_docs/generators/generic-freemarker-generator.md @@ -481,7 +481,7 @@ The Context Mapper Eclipse plugin comes with sample Freemarker templates. Use th ![Create Sample Project with Freemarker Templates (2)](/img/screenshot-new-freemarker-example-project-2.png) ### Visual Studio Code -In VS Code we do not deliver the example templates with the extension itself. However, you can just download the *.ftl files from [here](https://github.com/ContextMapper/context-mapper-dsl/tree/master/org.contextmapper.dsl.ui/samples/freemarker) and use it with our generator in VS Code. +In VS Code we do not deliver the example templates with the extension itself. However, you can just download the *.ftl files from [here](https://github.com/ContextMapper/context-mapper-dsl/tree/master/samples/freemarker) and use it with our generator in VS Code. ### Provided Examples The project currently contains the following example templates: diff --git a/_docs/generators/mdsl.md b/_docs/generators/mdsl.md index 60ecdb6..c13a3e3 100644 --- a/_docs/generators/mdsl.md +++ b/_docs/generators/mdsl.md @@ -41,7 +41,7 @@ The base/primitive types are mapped to [Atomic Parameters](https://microservice- If you declare a method with multiple parameters or refer to an object (such as Entity or Value Object) in CML, we generate a corresponding [Parameter Tree](https://microservice-api-patterns.org/patterns/structure/representationElements/ParameterTree). For example the following entity would be mapped to the (rather flat) parameter tree below: CML input: -``` +```cml Entity Address { String street String lockbox nullable @@ -50,59 +50,62 @@ Entity Address { } ``` MDSL data type result: -
data type Address { "street":D<string>, "lockbox":D<string>?, "postalCode":D<int>, "city":D<string> }
-
+```mdsl +data type Address { "street":D, "lockbox":D?, "postalCode":D, "city":D } +``` All abstract data types that are not base types and not specified in CML (no references to objects) will produce an abstract, unspecified placeholder element `P` in [MDSL](https://microservice-api-patterns.github.io/MDSL-Specification/), as the following example illustrates: -
data type JustAnUnspecifiedParameterType P
-
+```mdsl +data type JustAnUnspecifiedParameterType P +``` **Hint**: Find more information in our SummerSoC 2020 paper on [Domain-driven Service Design - Context Modeling, Model Refactoring and Contract Generation](/media/SummerSoC-2020_Domain-driven-Service-Design_Authors-Copy.pdf) (authors copy). ## Example An exemplary API description in [MDSL](https://microservice-api-patterns.github.io/MDSL-Specification/), generated by Context Mapper, is: -
// Generated from DDD Context Map 'Insurance-Example_Context-Map.cml' at 21.10.2019 17:48:52 CEST.
-API description CustomerManagementContextAPI
-usage context PUBLIC_API for BACKEND_INTEGRATION
-
-data type Address { "street":D<string>, "postalCode":D<int>, "city":D<string> }
-data type AddressId P
-data type changeCustomerParameter { "firstname":D<string>, "lastname":D<string> }
-
-endpoint type CustomersAggregate
-  serves as INFORMATION_HOLDER_RESOURCE
-  exposes
-    operation createAddress
-      with responsibility "Creates new address for customer"
-      expecting
-        payload Address
-      delivering
-        payload AddressId
-    operation changeCustomer
-      with responsibility "Changes existing customer address"
-      expecting
-        payload changeCustomerParameter
-      delivering
-        payload D<bool>
-
-// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL).
-API provider CustomerManagementContextProvider
-  // The customer management context is responsible for managing all the data of the insurance companies customers.
-  offers CustomersAggregate
-  at endpoint location "http://localhost:8001"
-    via protocol "RESTfulHTTP"
-
-// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL).
-API client PolicyManagementContextClient
-  // This bounded context manages the contracts and policies of the customers.
-  consumes CustomersAggregate
-API client CustomerSelfServiceContextClient
-  // This context represents a web application which allows the customer to login and change basic data records like the address.
-  consumes CustomersAggregate
-
-IPA
-
+```mdsl +// Generated from DDD Context Map 'Insurance-Example_Context-Map.cml' at 21.10.2019 17:48:52 CEST. +API description CustomerManagementContextAPI +usage context PUBLIC_API for BACKEND_INTEGRATION + +data type Address { "street":D, "postalCode":D, "city":D } +data type AddressId P +data type changeCustomerParameter { "firstname":D, "lastname":D } + +endpoint type CustomersAggregate + serves as INFORMATION_HOLDER_RESOURCE + exposes + operation createAddress + with responsibility "Creates new address for customer" + expecting + payload Address + delivering + payload AddressId + operation changeCustomer + with responsibility "Changes existing customer address" + expecting + payload changeCustomerParameter + delivering + payload D + +// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL). +API provider CustomerManagementContextProvider + // The customer management context is responsible for managing all the data of the insurance companies customers. + offers CustomersAggregate + at endpoint location "http://localhost:8001" + via protocol "RESTfulHTTP" + +// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL). +API client PolicyManagementContextClient + // This bounded context manages the contracts and policies of the customers. + consumes CustomersAggregate +API client CustomerSelfServiceContextClient + // This context represents a web application which allows the customer to login and change basic data records like the address. + consumes CustomersAggregate + +IPA +``` *Note:* This example has been generated from our [insurance example](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/insurance-example), which you can find in our [examples repository](https://github.com/ContextMapper/context-mapper-examples). @@ -112,43 +115,45 @@ The MDSL language allows modelers to specify the roles of endpoints and operatio the MAP patterns can be added in CML. In this case we use the _Information Holder Resource_ pattern on the Aggregate level and the _Retrieval Operation_ pattern on the method level: -
BoundedContext CustomerManagementContext {
+```cml
+BoundedContext CustomerManagementContext {
 
-  "INFORMATION_HOLDER_RESOURCE"
-  Aggregate Customers {
+  "INFORMATION_HOLDER_RESOURCE"
+  Aggregate Customers {
 
-    Entity Customer {
-      aggregateRoot
+    Entity Customer {
+      aggregateRoot
 
-      - SocialInsuranceNumber sin
-      String firstname
-      String lastname
-      - List<Address> addresses
+      - SocialInsuranceNumber sin
+      String firstname
+      String lastname
+      - List
addresses - "RETRIEVAL_OPERATION" - def @Address getAddress(AddressId addressId); + "RETRIEVAL_OPERATION" + def @Address getAddress(AddressId addressId); } - Entity Address + Entity Address } } -
+``` The patterns are detected by our generator and mapped to the corresponding language features of MDSL. The following MDSL code illustrates the resulting resource for the Aggregate specified above: -
data type Address { "street":D<string>, "postalCode":D<int>, "city":D<string> }
-data type AddressId P
-
-endpoint type CustomersAggregate
-  serves as INFORMATION_HOLDER_RESOURCE
-  exposes
-    operation getAddress
-      with responsibility RETRIEVAL_OPERATION
-      expecting
-        payload AddressId
-      delivering
-        payload Address
-
+```mdsl +data type Address { "street":D, "postalCode":D, "city":D } +data type AddressId P + +endpoint type CustomersAggregate + serves as INFORMATION_HOLDER_RESOURCE + exposes + operation getAddress + with responsibility RETRIEVAL_OPERATION + expecting + payload AddressId + delivering + payload Address +``` As illustrated above, the patterns on the endpoint/resource level are added with the _serves as_ keyword and on the operation level with the _with responsibility_ keyword. In the following we list the supported patterns: @@ -177,85 +182,87 @@ The generators can be called from the context menus of the CML editors in VS Cod ## Protected Regions After you have generated an MDSL contract, you can add protected regions for **data types**, **endpoint types**, **API providers**, and **API clients** if you want to modify parts of the contract and protect them from being overwritten. The following example shows the corresponding comments that are required to begin and end the four different protected regions: -
// Generated from DDD Context Map 'Insurance-Example_Context-Map.cml' at 21.10.2019 17:48:52 CEST.
-API description CustomerManagementContextAPI
-usage context PUBLIC_API for BACKEND_INTEGRATION
+```mdsl
+// Generated from DDD Context Map 'Insurance-Example_Context-Map.cml' at 21.10.2019 17:48:52 CEST.
+API description CustomerManagementContextAPI
+usage context PUBLIC_API for BACKEND_INTEGRATION
 
-// ** BEGIN PROTECTED REGION for data types
+// ** BEGIN PROTECTED REGION for data types
 
-// ** END PROTECTED REGION for data types
+// ** END PROTECTED REGION for data types
 
-data type Address { "street":D<string>, "postalCode":D<int>, "city":D<string> }
-data type AddressId P
-data type changeCustomerParameter { "firstname":D<string>, "lastname":D<string> }
+data type Address { "street":D, "postalCode":D, "city":D }
+data type AddressId P
+data type changeCustomerParameter { "firstname":D, "lastname":D }
 
-// ** BEGIN PROTECTED REGION for endpoint types
+// ** BEGIN PROTECTED REGION for endpoint types
 
-// ** END PROTECTED REGION for endpoint types
+// ** END PROTECTED REGION for endpoint types
 
-endpoint type CustomersAggregate
-  serves as INFORMATION_HOLDER_RESOURCE
-  exposes
-    operation createAddress
-      with responsibility "Creates new address for customer"
-      expecting
-        payload Address
-      delivering
-        payload AddressId
-    operation changeCustomer
-      with responsibility "Changes existing customer address"
-      expecting
-        payload changeCustomerParameter
-      delivering
-        payload D<bool>
+endpoint type CustomersAggregate
+  serves as INFORMATION_HOLDER_RESOURCE
+  exposes
+    operation createAddress
+      with responsibility "Creates new address for customer"
+      expecting
+        payload Address
+      delivering
+        payload AddressId
+    operation changeCustomer
+      with responsibility "Changes existing customer address"
+      expecting
+        payload changeCustomerParameter
+      delivering
+        payload D
 
-// ** BEGIN PROTECTED REGION for API providers
+// ** BEGIN PROTECTED REGION for API providers
 
-// ** END PROTECTED REGION for API providers
+// ** END PROTECTED REGION for API providers
 
-// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL).
-API provider CustomerManagementContextProvider
-  // The customer management context is responsible for managing all the data of the insurance companies customers.
-  offers CustomersAggregate
-  at endpoint location "http://localhost:8001"
-    via protocol "RESTfulHTTP"
+// Generated from DDD upstream Bounded Context 'CustomerManagementContext' implementing OPEN_HOST_SERVICE (OHS) and PUBLISHED_LANGUAGE (PL).
+API provider CustomerManagementContextProvider
+  // The customer management context is responsible for managing all the data of the insurance companies customers.
+  offers CustomersAggregate
+  at endpoint location "http://localhost:8001"
+    via protocol "RESTfulHTTP"
 
-// ** BEGIN PROTECTED REGION for API clients
+// ** BEGIN PROTECTED REGION for API clients
 
-// ** END PROTECTED REGION for API clients
+// ** END PROTECTED REGION for API clients
 
-// Generated from DDD downstream Bounded Context 'PolicyManagementContext' implementing CONFORMIST (CF).
-API client PolicyManagementContextClient
-  // This bounded context manages the contracts and policies of the customers.
-  consumes CustomersAggregate
-API client CustomerSelfServiceContextClient
-  // This context represents a web application which allows the customer to login and change basic data records like the address.
-  consumes CustomersAggregate
+// Generated from DDD downstream Bounded Context 'PolicyManagementContext' implementing CONFORMIST (CF).
+API client PolicyManagementContextClient
+  // This bounded context manages the contracts and policies of the customers.
+  consumes CustomersAggregate
+API client CustomerSelfServiceContextClient
+  // This context represents a web application which allows the customer to login and change basic data records like the address.
+  consumes CustomersAggregate
 
-IPA
-
+IPA +``` The protected regions allow you to guard _data types_, _endpoints_, _API providers_, and _API clients_ into so that they are not overwritten at re-generation. Thus, you can call the MDSL generator on the same file again and all objects within a protected region will still be there and remain unchanged. For example, you can move a set of _data types_ into the corresponding protected region if you changed the data types manually after generation and want to protect them: -
// Generated from DDD Context Map 'Insurance-Example_Context-Map.cml' at 21.10.2019 17:48:52 CEST.
-API description CustomerManagementContextAPI
-usage context PUBLIC_API for BACKEND_INTEGRATION
+```mdsl
+// Generated from DDD Context Map 'Insurance-Example_Context-Map.cml' at 21.10.2019 17:48:52 CEST.
+API description CustomerManagementContextAPI
+usage context PUBLIC_API for BACKEND_INTEGRATION
 
-// ** BEGIN PROTECTED REGION for data types
+// ** BEGIN PROTECTED REGION for data types
 
-data type Address { "street":D<string>, "postalCode":D<int>, "city":D<string>, "manuallyChangedThisDataType":D<string> }
+data type Address { "street":D, "postalCode":D, "city":D, "manuallyChangedThisDataType":D }
 
-// ** END PROTECTED REGION for data types
+// ** END PROTECTED REGION for data types
 
-data type AddressId P
-data type changeCustomerParameter { "firstname":D<string>, "lastname":D<string> }
+data type AddressId P
+data type changeCustomerParameter { "firstname":D, "lastname":D }
 
-// removed the rest here to save space ...
+// removed the rest here to save space ...
 
-IPA
-
+IPA +``` ## MDSL Support The current version of our MDSL generator is compatible with the MDSL Version 5. For further questions regarding [MDSL](https://microservice-api-patterns.github.io/MDSL-Specification/), please visit its website [https://microservice-api-patterns.github.io/MDSL-Specification/](https://microservice-api-patterns.github.io/MDSL-Specification/). This is the [update site](https://microservice-api-patterns.github.io/MDSL-Specification/updates/) to install the MDSL tools plugin. diff --git a/_docs/getting-started.md b/_docs/getting-started.md index 59c8a7b..6c65364 100644 --- a/_docs/getting-started.md +++ b/_docs/getting-started.md @@ -46,50 +46,52 @@ Release notes for all our latest releases can be found [here](https://github.com ## Example The following example gives you a first impression how CML context maps look like: ([DDD Sample Application](https://github.com/citerus/dddsample-core)) -
/** 
- * The DDD Cargo sample application modeled in CML. Note that we split the application into 
- * multiple bounded contexts.
- *
- */
-ContextMap {
-  contains CargoBookingContext
-  contains VoyagePlanningContext
-  contains LocationContext
-  
-  CargoBookingContext [SK]<->[SK] VoyagePlanningContext
-  
-  CargoBookingContext [D]<-[U,OHS,PL] LocationContext
-
-  VoyagePlanningContext [D]<-[U,OHS,PL] LocationContext
+```cml
+/**
+ * The DDD Cargo sample application modeled in CML. Note that we split the application into
+ * multiple bounded contexts.
+ *
+ */
+ContextMap {
+  contains CargoBookingContext
+  contains VoyagePlanningContext
+  contains LocationContext
+
+  CargoBookingContext [SK]<->[SK] VoyagePlanningContext
+
+  CargoBookingContext [D]<-[U,OHS,PL] LocationContext
+
+  VoyagePlanningContext [D]<-[U,OHS,PL] LocationContext
 }
-
+``` The bounded contexts have to be specified before you can use them within a context map. A simple example of a bounded context definition is: -
BoundedContext LocationContext {
-  Module location {
-    Aggregate Location {
-      Entity Location {
-        aggregateRoot
+```cml
+BoundedContext LocationContext {
+  Module location {
+    Aggregate Location {
+      Entity Location {
+        aggregateRoot
 
-        PortCode portcode
-        - UnLocode unLocode
-          String name
+        PortCode portcode
+        - UnLocode unLocode
+          String name
       }
 
-      ValueObject UnLocode {
-        String unLocode
+      ValueObject UnLocode {
+        String unLocode
       }
 
-      ValueObject LocationShared {
-        PortCode portCode
-        - Location location
+      ValueObject LocationShared {
+        PortCode portCode
+        - Location location
       }
     }
   }
 }
-
+``` ## Next steps... diff --git a/_docs/language-reference/aggregate.md b/_docs/language-reference/aggregate.md index 1c29912..38a7f44 100644 --- a/_docs/language-reference/aggregate.md +++ b/_docs/language-reference/aggregate.md @@ -15,41 +15,42 @@ The respective rules are defined by the [Sculptor DSL](https://sculptor.github.i The following CML snippet illustrates an example of an aggregate to provide an impression how the rule can be used: -
Aggregate Contract {
-  responsibilities = "Contracts", "Policies"
-  knowledgeLevel = CONCRETE
+```cml
+Aggregate Contract {
+  responsibilities = "Contracts", "Policies"
+  knowledgeLevel = CONCRETE
 
-  Entity Contract {
-    aggregateRoot
+  Entity Contract {
+    aggregateRoot
 
-    - ContractId identifier
-    - Customer client
-    - List<Product> products
+    - ContractId identifier
+    - Customer client
+    - List products
   }
 
-  enum States {
-    aggregateLifecycle
+  enum States {
+    aggregateLifecycle
     CREATED, POLICE_CREATED, RECALLED
   }
 
-  ValueObject ContractId {
-    int contractId key
+  ValueObject ContractId {
+    int contractId key
   }
 
-  Entity Policy {
-    int policyNr
-    - Contract contract
-    BigDecimal price
+  Entity Policy {
+    int policyNr
+    - Contract contract
+    BigDecimal price
   }
 
-  Service ContractService {
-    @ContractId createContract(@Contract contrace) : write [ -> CREATED];
-    @Contract getContract(@ContractId contractId) : read-only;
-    boolean createPolicy(@ContractId contractId) : write [ CREATED -> POLICE_CREATED ];
-    boolean recall(@ContractId contractId) : write [ CREATED, POLICE_CREATED -> RECALLED ];
+  Service ContractService {
+    @ContractId createContract(@Contract contrace) : write [ -> CREATED];
+    @Contract getContract(@ContractId contractId) : read-only;
+    boolean createPolicy(@ContractId contractId) : write [ CREATED -> POLICE_CREATED ];
+    boolean recall(@ContractId contractId) : write [ CREATED, POLICE_CREATED -> RECALLED ];
   }
 }
-
+``` The equal sign (=) to assign an attribute value is always optional and therefore can be omitted. @@ -62,31 +63,34 @@ Further examples can be found within our GitHub example repository [context-mapp ## Aggregate Lifecycle and State Transitions As already illustrated in the example above, you can declare an Aggregate's states with an _enum_. The _aggregateLifecycle_ keyword marks the enum that defines the states: -
enum States {
-  aggregateLifecycle
+```cml
+enum States {
+  aggregateLifecycle
   CREATED, POLICE_CREATED, RECALLED
 }
-
+``` In addition, every operation (no matter whether it is specified in a _Service_ or an _Entity_) can declare whether it is a "read only" or "write" operation with the keywords _read-only_ and _write_: -
Service ContractService {
-  @ContractId createContract(@Contract contrace) : write;
-  @Contract getContract(@ContractId contractId) : read-only;
-  boolean createPolicy(@ContractId contractId) : write;
-  boolean recall(@ContractId contractId) : write;
+```cml
+Service ContractService {
+  @ContractId createContract(@Contract contrace) : write;
+  @Contract getContract(@ContractId contractId) : read-only;
+  boolean createPolicy(@ContractId contractId) : write;
+  boolean recall(@ContractId contractId) : write;
 }
-
+``` A _write_ operation may changes the state of the Aggregate. Such state transitions can be specified in square brackets: -
Service ContractService {
-  @ContractId createContract(@Contract contrace) : write [ -> CREATED];
-  @Contract getContract(@ContractId contractId) : read-only;
-  boolean createPolicy(@ContractId contractId) : write [ CREATED -> POLICE_CREATED ];
-  boolean recall(@ContractId contractId) : write [ CREATED, POLICE_CREATED -> RECALLED ];
+```cml
+Service ContractService {
+  @ContractId createContract(@Contract contrace) : write [ -> CREATED];
+  @Contract getContract(@ContractId contractId) : read-only;
+  boolean createPolicy(@ContractId contractId) : write [ CREATED -> POLICE_CREATED ];
+  boolean recall(@ContractId contractId) : write [ CREATED, POLICE_CREATED -> RECALLED ];
 }
-
+``` With our [PlantUML generator](/docs/plant-uml/) you can visualize the lifecycle of your Aggregates with state diagrams. For example, the model at the top of this page generates the following state diagram: @@ -98,26 +102,27 @@ With our [PlantUML generator](/docs/plant-uml/) you can visualize the lifecycle These language features allow you to define the lifecycle of an Aggregate. The following example show all possible variants of state transitions (note that the following example is not in line with the example above; it just shows all variants of possible state transitions): -
// an initial state:
--> CREATED
+```cml
+// an initial state:
+-> CREATED
 
-// simple state transition from one state into the other
-CREATED -> CHECK_REQUESTED
+// simple state transition from one state into the other
+CREATED -> CHECK_REQUESTED
 
-// the left side can contain multiple states:
-// (this means that the state on the right can be reached by any of those on the left side)
-CREATED, CHECK_REQUESTED -> CHECK_IN_PROGRESS
+// the left side can contain multiple states:
+// (this means that the state on the right can be reached by any of those on the left side)
+CREATED, CHECK_REQUESTED -> CHECK_IN_PROGRESS
 
-// multiple target states possible
-// X stands for XOR and means one OR the other will be reached but not both at the same time (exclusive OR)
-CHECK_IN_PROGRESS -> ACCEPTED X REJECTED
+// multiple target states possible
+// X stands for XOR and means one OR the other will be reached but not both at the same time (exclusive OR)
+CHECK_IN_PROGRESS -> ACCEPTED X REJECTED
 
-// target states can be marked as end states with a star:
-CHECK_IN_PROGRESS -> ACCEPTED* X REJECTED*
+// target states can be marked as end states with a star:
+CHECK_IN_PROGRESS -> ACCEPTED* X REJECTED*
 
-// a combination of multiple on the left and multiple on the right
-CREATED, CHECK_REQUESTED -> ACCEPTED X REJECTED
-
+// a combination of multiple on the left and multiple on the right +CREATED, CHECK_REQUESTED -> ACCEPTED X REJECTED +``` _Hint:_ You can also model the state transition inside your [event flows in the application layer](/docs/application-and-process-layer/#processes-and-eventcommand-flows). @@ -125,107 +130,110 @@ _Hint:_ You can also model the state transition inside your [event flows in the CML allows specifying an owner on the aggregate level. If aggregates are maintained by different teams, you can specify this as in the following example: -
BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
-  type = APPLICATION
-  domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
-  responsibilities = "AddressChange"
-  implementationTechnology = "PHP Web Application"
+```cml
+BoundedContext CustomerSelfServiceContext implements CustomerManagementDomain {
+  type = APPLICATION
+  domainVisionStatement = "This context represents a web application which allows the customer to login and change basic data records like the address."
+  responsibilities = "AddressChange"
+  implementationTechnology = "PHP Web Application"
 
-  Aggregate CustomerFrontend {
-    owner = CustomerFrontendTeam
+  Aggregate CustomerFrontend {
+    owner = CustomerFrontendTeam
 
-    DomainEvent CustomerAddressChange {
-      aggregateRoot
+    DomainEvent CustomerAddressChange {
+      aggregateRoot
 
-      - UserAccount issuer
-      - Address changedAddress
+      - UserAccount issuer
+      - Address changedAddress
     }
   }
-  Aggregate Acounts {
-    owner = CustomerBackendTeam
+  Aggregate Acounts {
+    owner = CustomerBackendTeam
 
-    Entity UserAccount {
-      aggregateRoot
+    Entity UserAccount {
+      aggregateRoot
 
-      String username
-      - Customer accountCustomer
+      String username
+      - Customer accountCustomer
     }
   }
 }
-
+``` The _owner_ attribute may be used for service decomposition by using the [Split Bounded Context by Owners](/docs/ar-split-bounded-context-by-owners) architectural refactoring. Note that the _owner_ attribute refers to a team, which must be a bounded context of the type _TEAM_: (see [Bounded Context](/docs/bounded-context) for more details): -
/* Team Definitions */
-BoundedContext CustomerBackendTeam {
-  type = TEAM
+```cml
+/* Team Definitions */
+BoundedContext CustomerBackendTeam {
+  type = TEAM
 }
 
-BoundedContext CustomerFrontendTeam {
-  type = TEAM
+BoundedContext CustomerFrontendTeam {
+  type = TEAM
 }
-
+``` ## Aggregate Features With CML you can further specify which [features or user requirements (use cases and/or user stories)](/docs/user-requirements/) an Aggregate supports. This information may be used for service decomposition when applying the [Split Bounded Context by Features](/docs/ar-split-bounded-context-by-features) architectural refactoring. Use Cases can be assigned with the _useCases_ keyword and User Stories with the _userStories_ keyword. You can also use the _features_ keyword and assign both, Use Cases and User Stories, at the same time: -
BoundedContext PolicyManagementContext implements PolicyManagementDomain {
-  Aggregate Offers {
-    useCases = CreateOfferForCustomer
-    
-    Entity Offer {
-      aggregateRoot
-      
-      int offerId
-      - Customer client
-      - List<Product> products
-      BigDecimal price
+```cml
+BoundedContext PolicyManagementContext implements PolicyManagementDomain {
+  Aggregate Offers {
+    useCases = CreateOfferForCustomer
+
+    Entity Offer {
+      aggregateRoot
+
+      int offerId
+      - Customer client
+      - List products
+      BigDecimal price
     }
   }
-  Aggregate Products {
-    userStories = AddProductToOffer
-    
-    Entity Product {
-      aggregateRoot
-      
-      - ProductId identifier
-      String productName
+  Aggregate Products {
+    userStories = AddProductToOffer
+
+    Entity Product {
+      aggregateRoot
+
+      - ProductId identifier
+      String productName
     }
-    ValueObject ProductId {
-      int productId key
+    ValueObject ProductId {
+      int productId key
     }
   }
-  Aggregate Contract {
-    features = CreateOfferForCustomer, UpdateContract
-    
-    Entity Contract {
-      aggregateRoot
-      
-      - ContractId identifier
-      - Customer client
-      - List<Product> products
+  Aggregate Contract {
+    features = CreateOfferForCustomer, UpdateContract
+
+    Entity Contract {
+      aggregateRoot
+
+      - ContractId identifier
+      - Customer client
+      - List products
     }
-    ValueObject ContractId {
-      int contractId key
+    ValueObject ContractId {
+      int contractId key
     }
-    
-    Entity Policy {
-      int policyNr
-      - Contract contract
-      BigDecimal price
+
+    Entity Policy {
+      int policyNr
+      - Contract contract
+      BigDecimal price
     }
   }
 }
 
-UseCase CreateOfferForCustomer
-UserStory UpdateContract
-UserStory AddProductToOffer
-
+UseCase CreateOfferForCustomer +UserStory UpdateContract +UserStory AddProductToOffer +``` Multiple User Stories and/or Use Cases can be assigned as a comma-separated list, as shown in the last Aggregate example above. @@ -239,27 +247,28 @@ This can be very helpful to model security-related requirements which can later A simple example: -
BoundedContext MyMonolith {
-  Aggregate CustomerManagement {
-    securityZone "Internal"
-    Entity Customer {
-      String firstName
-      String lastName
+```cml
+BoundedContext MyMonolith {
+  Aggregate CustomerManagement {
+    securityZone "Internal"
+    Entity Customer {
+      String firstName
+      String lastName
     }
-    Entity Address {
-      - Customer customer
-      String street
-      String city
+    Entity Address {
+      - Customer customer
+      String street
+      String city
     }
   }
-  Aggregate CustomerFrontend {
-    securityZone "Public"
-    DomainEvent AddressChanged {
-      - Address address
+  Aggregate CustomerFrontend {
+    securityZone "Public"
+    DomainEvent AddressChanged {
+      - Address address
     }
   }
 }
-
+``` ## Security Access Groups The attribute _securityAccessGroup_ allows you to assign different Aggregates to different _security access groups_. This feature is primarily used to generate the [user representations for Service Cutter](/docs/service-cutter-context-map-suggestions/#input-and-preconditions), i.e. the [security access groups](https://github.com/ServiceCutter/ServiceCutter/wiki/Security-access-groups). @@ -268,27 +277,28 @@ This can be very helpful to declare that your Aggregates have different access r An example: -
BoundedContext MyMonolith {
-  Aggregate CustomerManagement {
-    securityAccessGroup "InsuranceEmployees"
-    Entity Customer {
-      String firstName
-      String lastName
+```cml
+BoundedContext MyMonolith {
+  Aggregate CustomerManagement {
+    securityAccessGroup "InsuranceEmployees"
+    Entity Customer {
+      String firstName
+      String lastName
     }
-    Entity Address {
-      - Customer customer
-      String street
-      String city
+    Entity Address {
+      - Customer customer
+      String street
+      String city
     }
   }
-  Aggregate CustomerFrontend {
-    securityAccessGroup "Customers"
-    DomainEvent AddressChanged {
-      - Address address
+  Aggregate CustomerFrontend {
+    securityAccessGroup "Customers"
+    DomainEvent AddressChanged {
+      - Address address
     }
   }
 }
-
+``` ## Characteristics Classification On the Aggregate level it is possible to classify parts of your domain model [according to Service Cutter's characteristics (compatibilities)](https://github.com/ServiceCutter/ServiceCutter/wiki/Compatibilities). This is primarily used to generate the [user representations for Service Cutter](/docs/service-cutter-context-map-suggestions/#input-and-preconditions), in case you generate service decomposition suggestions with Context Mapper. @@ -314,18 +324,19 @@ The attribute _contentVolatility_ takes the following values: An example: -
Aggregate AggregateDemo1 {
-  contentVolatility = OFTEN // content changes more often in this Aggregate
-  
-  Entity DemoEntityOne
+```cml
+Aggregate AggregateDemo1 {
+  contentVolatility = OFTEN // content changes more often in this Aggregate
+
+  Entity DemoEntityOne
 }
 
-Aggregate AggregateDemo2 {
-  contentVolatility = NORMAL
-  
-  Entity DemoEntityTwo
+Aggregate AggregateDemo2 {
+  contentVolatility = NORMAL
+
+  Entity DemoEntityTwo
 }
-
+``` ### Likelihood for Change @@ -341,31 +352,33 @@ components (see [Parnas](https://dl.acm.org/citation.cfm?doid=361598.361623)). B The likelihood on an aggregate is declared as follows: -
Aggregate CustomerFrontend {
-  likelihoodForChange = OFTEN
-  
-  DomainEvent CustomerAddressChange {
-    aggregateRoot
-    
-    - UserAccount issuer
-    - Address changedAddress
+```cml
+Aggregate CustomerFrontend {
+  likelihoodForChange = OFTEN
+
+  DomainEvent CustomerAddressChange {
+    aggregateRoot
+
+    - UserAccount issuer
+    - Address changedAddress
   }
 }
-
+``` You can also use the _structuralVolatility_ keyword: -
Aggregate CustomerFrontend {
-  structuralVolatility = OFTEN
-  
-  DomainEvent CustomerAddressChange {
-    aggregateRoot
-    
-    - UserAccount issuer
-    - Address changedAddress
+```cml
+Aggregate CustomerFrontend {
+  structuralVolatility = OFTEN
+
+  DomainEvent CustomerAddressChange {
+    aggregateRoot
+
+    - UserAccount issuer
+    - Address changedAddress
   }
 }
-
+``` ### Availability Criticality This characteristic corresponds to the [Availability Criticality](https://github.com/ServiceCutter/ServiceCutter/wiki/CC-7-Availability-Criticality) criterion of [Service Cutter](https://github.com/ServiceCutter/ServiceCutter/wiki/Coupling-Criteria). @@ -377,18 +390,19 @@ The attribute _availabilityCriticality_ takes the following values: An example: -
Aggregate AggregateDemo1 {
-  availabilityCriticality = HIGH // higher availability requirements then other aggregate
-  
-  Entity DemoEntityOne
+```cml
+Aggregate AggregateDemo1 {
+  availabilityCriticality = HIGH // higher availability requirements then other aggregate
+
+  Entity DemoEntityOne
 }
 
-Aggregate AggregateDemo2 {
-  availabilityCriticality = NORMAL
-  
-  Entity DemoEntityTwo
+Aggregate AggregateDemo2 {
+  availabilityCriticality = NORMAL
+
+  Entity DemoEntityTwo
 }
-
+``` ### Consistency Criticality This characteristic corresponds to the [Consistency Criticality](https://github.com/ServiceCutter/ServiceCutter/wiki/CC-6-Consistency-Criticality) criterion of [Service Cutter](https://github.com/ServiceCutter/ServiceCutter/wiki/Coupling-Criteria). @@ -400,18 +414,19 @@ The attribute _consistencyCriticality_ takes the following values: An example: -
Aggregate AggregateDemo1 {
-  consistencyCriticality = HIGH // higher consistency requirements then other aggregate
-  
-  Entity DemoEntityOne
+```cml
+Aggregate AggregateDemo1 {
+  consistencyCriticality = HIGH // higher consistency requirements then other aggregate
+
+  Entity DemoEntityOne
 }
 
-Aggregate AggregateDemo2 {
-  consistencyCriticality = NORMAL
-  
-  Entity DemoEntityTwo
+Aggregate AggregateDemo2 {
+  consistencyCriticality = NORMAL
+
+  Entity DemoEntityTwo
 }
-
+``` ### Storage Similarity This characteristic corresponds to the [Storage Similarity](https://github.com/ServiceCutter/ServiceCutter/wiki/CC-11-Storage-Similarity) criterion of [Service Cutter](https://github.com/ServiceCutter/ServiceCutter/wiki/Coupling-Criteria). @@ -423,24 +438,25 @@ The attribute _storageSimilarity_ takes the following values: An example: -
Aggregate AggregateDemo1 {
-  storageSimilarity = HUGE // similar storage requirements as AggregateDemo3
-  
-  Entity DemoEntityOne
+```cml
+Aggregate AggregateDemo1 {
+  storageSimilarity = HUGE // similar storage requirements as AggregateDemo3
+
+  Entity DemoEntityOne
 }
 
-Aggregate AggregateDemo2 {
-  storageSimilarity = NORMAL
-  
-  Entity DemoEntityTwo
+Aggregate AggregateDemo2 {
+  storageSimilarity = NORMAL
+
+  Entity DemoEntityTwo
 }
 
-Aggregate AggregateDemo3 {
-  storageSimilarity = HUGE // similar storage requirements as AggregateDemo1
-  
-  Entity DemoEntityThree
+Aggregate AggregateDemo3 {
+  storageSimilarity = HUGE // similar storage requirements as AggregateDemo1
+
+  Entity DemoEntityThree
 }
-
+``` ### Security Criticality This characteristic corresponds to the [Security Criticality](https://github.com/ServiceCutter/ServiceCutter/wiki/CC-15-Security-Criticality) criterion of [Service Cutter](https://github.com/ServiceCutter/ServiceCutter/wiki/Coupling-Criteria). @@ -452,16 +468,17 @@ The attribute _securityCriticality_ takes the following values: An example: -
Aggregate AggregateDemo1 {
-  securityCriticality = HIGH // high security requirements
-  
-  Entity DemoEntityOne
+```cml
+Aggregate AggregateDemo1 {
+  securityCriticality = HIGH // high security requirements
+
+  Entity DemoEntityOne
 }
 
-Aggregate AggregateDemo2 {
-  securityCriticality = NORMAL
-  
-  Entity DemoEntityTwo
+Aggregate AggregateDemo2 {
+  securityCriticality = NORMAL
+
+  Entity DemoEntityTwo
 }
-
+``` diff --git a/_docs/language-reference/anticorruption-layer.md b/_docs/language-reference/anticorruption-layer.md index 02934e2..afb2fd1 100644 --- a/_docs/language-reference/anticorruption-layer.md +++ b/_docs/language-reference/anticorruption-layer.md @@ -9,10 +9,11 @@ The Anticorruption Layer pattern describes a relationship between two bounded co The Anticorruption Layer pattern can be used as a role for the downstream context in a Upstream/Downstream relationship by using the **ACL** abbreviation. The following example illustrates the syntax: -
DebtCollection [D,ACL]<-[U,OHS,PL] PrintingContext {
-  implementationTechnology = "SOAP"
+```cml
+DebtCollection [D,ACL]<-[U,OHS,PL] PrintingContext {
+  implementationTechnology = "SOAP"
 }
-
+``` ## Semantic Rules Note that semantic rules (validators) exist for Anticorruption Layer within CML. This means that not every combination of patterns and concepts is allowed, even if it would be syntactically correct. diff --git a/_docs/language-reference/application-and-process-layer.md b/_docs/language-reference/application-and-process-layer.md index 96bddf0..5aa6b23 100644 --- a/_docs/language-reference/application-and-process-layer.md +++ b/_docs/language-reference/application-and-process-layer.md @@ -14,66 +14,69 @@ DDD practitioners and experts typically distinguish between domain services and The following example illustrates how to model an application layer in a Bounded Context and add application services: -
BoundedContext ClaimsManagement {
-  Application {
-    Service ClaimsApplicationService {
-      void submitClaim(@Claim claim);
-      void checkInsurance(@Claim claim);
-      void acceptClaim(@Claim claim);
-      void rejectClaim(@Claim claim);
+```cml
+BoundedContext ClaimsManagement {
+  Application {
+    Service ClaimsApplicationService {
+      void submitClaim(@Claim claim);
+      void checkInsurance(@Claim claim);
+      void acceptClaim(@Claim claim);
+      void rejectClaim(@Claim claim);
     }
   }
-  
-  Aggregate Claims {
-    Entity Claim {
-      aggregateRoot
-      long claimId
-      CustomerId customer
-      String description
-      Blob requestDocument
-      boolean isComplete
-      boolean isAssessed
-      - ClaimState claimState
+
+  Aggregate Claims {
+    Entity Claim {
+      aggregateRoot
+      long claimId
+      CustomerId customer
+      String description
+      Blob requestDocument
+      boolean isComplete
+      boolean isAssessed
+      - ClaimState claimState
     }
-    enum ClaimState {
-      aggregateLifecycle
+    enum ClaimState {
+      aggregateLifecycle
       OPEN, REJECTED, ACCEPTED
     }
-    
-    abstract DomainEvent ClaimEvent {
-      long claimId
-      Date timestamp
+
+    abstract DomainEvent ClaimEvent {
+      long claimId
+      Date timestamp
     }
-    DomainEvent ClaimSubmitted extends ClaimEvent
-    DomainEvent ClaimAccepted extends ClaimEvent
-    DomainEvent ClaimRejected extends ClaimEvent
+    DomainEvent ClaimSubmitted extends ClaimEvent
+    DomainEvent ClaimAccepted extends ClaimEvent
+    DomainEvent ClaimRejected extends ClaimEvent
   }
 }
-
+``` Optionally, it is possible to name the application layer: -
Application ClaimsApplicationLayer {
-  Service ClaimsApplicationService {
-    void submitClaim(@Claim claim);
-    void checkInsurance(@Claim claim);
-    void acceptClaim(@Claim claim);
-    void rejectClaim(@Claim claim);
+```cml
+Application ClaimsApplicationLayer {
+  Service ClaimsApplicationService {
+    void submitClaim(@Claim claim);
+    void checkInsurance(@Claim claim);
+    void acceptClaim(@Claim claim);
+    void rejectClaim(@Claim claim);
   }
 }
-
+``` As documented on the [Aggregate page](/docs/aggregate/#aggregate-lifecycle-and-state-transitions), it is also possible to specify state transitions made by operations. Please consult the Aggregate documentation for the syntax of state transitions. The same syntax is available for the operations of application services: -
Application {
-  Service ClaimsApplicationService {
-    void submitClaim(@Claim claim) : write [ -> OPEN];
-    void checkInsurance(@Claim claim);
-    void acceptClaim(@Claim claim) : write [ OPEN -> ACCEPTED ];
-    void rejectClaim(@Claim claim) : write [ OPEN -> REJECTED ];
+```cml
+Application {
+  Service ClaimsApplicationService {
+    void submitClaim(@Claim claim) : write [ -> OPEN];
+    void checkInsurance(@Claim claim);
+    void acceptClaim(@Claim claim) : write [ OPEN -> ACCEPTED ];
+    void rejectClaim(@Claim claim) : write [ OPEN -> REJECTED ];
   }
 }
-
+``` _Hint:_ If you model processes/flows (see documentation of syntax below) you may want to declare the state transitions in the flow steps instead of service operations. @@ -81,20 +84,21 @@ As an alternative to "service operations" you can also create semantically equiv The syntax for domain events and commands is documented on the [tactic DDD reference page](/docs/tactic-ddd/#domain-events). The following example illustrates how you can use those concepts in the application layer as well: -
Application {
-  Command SubmitClaim {
-    // attributes/body optional
+```cml
+Application {
+  Command SubmitClaim {
+    // attributes/body optional
   }
-  Command AcceptClaim
-  Command RejectClaim
-  
-  Event ClaimSubmitted {
-    // attributes/body optional
+  Command AcceptClaim
+  Command RejectClaim
+
+  Event ClaimSubmitted {
+    // attributes/body optional
   }
-  Event ClaimAccepted
-  Event ClaimRejected
+  Event ClaimAccepted
+  Event ClaimRejected
 }
-
+``` _Hint:_ Modeling commands that are triggered by users or external systems in the application layer may feel natural. Events, however, may be part of your [domain model](https://github.com/socadk/design-practice-repository/blob/master/artifact-templates/DPR-DomainModel.md). Therefore you should decide consciously whether you want to model these events on the application layer or inside the corresponding domain layer Aggregate. @@ -105,62 +109,64 @@ In addition to application services and commands, the application layer offers l Our flow grammar supports Context Mapper users in modeling such event/command flows in CML. The following example models the event storming result illustrated above: -
Application {
+```cml
+Application {
 
-  /* we removed commands and events here to keep the sample shorter */
+  /* we removed commands and events here to keep the sample shorter */
 
-  Flow ClaimsFlow {
-    command SubmitClaim emits event ClaimSubmitted
-    event ClaimSubmitted triggers command CheckClaimDocumentation
-    command CheckClaimDocumentation emits event ClaimRegistered
-    event ClaimRegistered triggers command CheckInsurance
-    command CheckInsurance emits event AssessmentPerformed
+  Flow ClaimsFlow {
+    command SubmitClaim emits event ClaimSubmitted
+    event ClaimSubmitted triggers command CheckClaimDocumentation
+    command CheckClaimDocumentation emits event ClaimRegistered
+    event ClaimRegistered triggers command CheckInsurance
+    command CheckInsurance emits event AssessmentPerformed
 
-    event AssessmentPerformed triggers command AcceptClaim X RejectClaim 
-    command AcceptClaim delegates to Claims [OPEN -> ACCEPTED] emits event ClaimAccepted
-    command RejectClaim delegates to Claims [OPEN -> REJECTED] emits event ClaimRejected
+    event AssessmentPerformed triggers command AcceptClaim X RejectClaim
+    command AcceptClaim delegates to Claims [OPEN -> ACCEPTED] emits event ClaimAccepted
+    command RejectClaim delegates to Claims [OPEN -> REJECTED] emits event ClaimRejected
 
-    event ClaimAccepted triggers command SchedulePayment
-    command SchedulePayment emits event PaymentPerformed
-    event PaymentPerformed triggers command NofifyCustomer
-    event ClaimRejected triggers command NofifyCustomer
-    command NofifyCustomer delegates to Claims [ACCEPTED, REJECTED -> CUSTOMER_NOTIFIED] emits event CustomerNotified
+    event ClaimAccepted triggers command SchedulePayment
+    command SchedulePayment emits event PaymentPerformed
+    event PaymentPerformed triggers command NofifyCustomer
+    event ClaimRejected triggers command NofifyCustomer
+    command NofifyCustomer delegates to Claims [ACCEPTED, REJECTED -> CUSTOMER_NOTIFIED] emits event CustomerNotified
   }
 }
-
+``` The example above works with commands. It is however possible to model the same flow with service operations: -
Application {
-  Service ClaimsApplicationService {
-    void submitClaim(@Claim claim);
-    void checkClaimDocumentation(@Claim claim);
-    void checkInsurance(@Claim claim);
-    void acceptClaim(@Claim claim);
-    void rejectClaim(@Claim claim);
-    void schedulePayment(@Claim claim);
-    void nofifyCustomer(@Claim claim);
+```cml
+Application {
+  Service ClaimsApplicationService {
+    void submitClaim(@Claim claim);
+    void checkClaimDocumentation(@Claim claim);
+    void checkInsurance(@Claim claim);
+    void acceptClaim(@Claim claim);
+    void rejectClaim(@Claim claim);
+    void schedulePayment(@Claim claim);
+    void nofifyCustomer(@Claim claim);
   }
-  
-  Flow ClaimsFlow {
-    operation submitClaim emits event ClaimSubmitted
-    event ClaimSubmitted triggers operation checkClaimDocumentation
-    operation checkClaimDocumentation emits event ClaimRegistered
-    event ClaimRegistered triggers operation checkInsurance
-    operation checkInsurance emits event AssessmentPerformed
-    
-    event AssessmentPerformed triggers operation acceptClaim X rejectClaim 
-    operation acceptClaim delegates to Claims [OPEN -> ACCEPTED] emits event ClaimAccepted
-    operation rejectClaim delegates to Claims [OPEN -> REJECTED] emits event ClaimRejected
-    
-    event ClaimAccepted triggers operation schedulePayment
-    operation schedulePayment emits event PaymentPerformed
-    event PaymentPerformed triggers operation nofifyCustomer
-    event ClaimRejected triggers operation nofifyCustomer
-    operation nofifyCustomer delegates to Claims[ACCEPTED, REJECTED -> CUSTOMER_NOTIFIED] emits event CustomerNotified
+
+  Flow ClaimsFlow {
+    operation submitClaim emits event ClaimSubmitted
+    event ClaimSubmitted triggers operation checkClaimDocumentation
+    operation checkClaimDocumentation emits event ClaimRegistered
+    event ClaimRegistered triggers operation checkInsurance
+    operation checkInsurance emits event AssessmentPerformed
+
+    event AssessmentPerformed triggers operation acceptClaim X rejectClaim
+    operation acceptClaim delegates to Claims [OPEN -> ACCEPTED] emits event ClaimAccepted
+    operation rejectClaim delegates to Claims [OPEN -> REJECTED] emits event ClaimRejected
+
+    event ClaimAccepted triggers operation schedulePayment
+    operation schedulePayment emits event PaymentPerformed
+    event PaymentPerformed triggers operation nofifyCustomer
+    event ClaimRejected triggers operation nofifyCustomer
+    operation nofifyCustomer delegates to Claims[ACCEPTED, REJECTED -> CUSTOMER_NOTIFIED] emits event CustomerNotified
   }
 }
-
+``` In the following we explain the grammar in detail and step by step... @@ -172,7 +178,9 @@ There are basically two types of flow steps that are supported by CML: These types of steps are inspired by the [Event Storming Cheat sheet of the DDD crew](https://github.com/ddd-crew/eventstorming-glossary-cheat-sheet), the following illustration in particular: -![Event Storming Picture](https://raw.githubusercontent.com/ddd-crew/eventstorming-glossary-cheat-sheet/master/resources/software-picture.jpg) +![Event Storming Picture](/img/ddd-crew-eventstorming-software-picture.jpg) + +_Illustration: [EventStorming Glossary & Cheat sheet](https://github.com/ddd-crew/eventstorming-glossary-cheat-sheet) by the DDD Crew, licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)._ _Note:_ We do not support all of the concepts illustrated above! Especially policies and the "query model / information" sticky are not supported explicitly. @@ -185,34 +193,36 @@ In the following we will see that we also support the Aggregate in _Type 2_; the The following example illustrates the basic syntax of the two step types: -
Application {
+```cml
+Application {
 
-  /* we removed commands and events here to keep the sample shorter */
+  /* we removed commands and events here to keep the sample shorter */
 
-  Flow ClaimsFlow {
-    /* type 2: (event production) */
-    command SubmitClaim emits event ClaimSubmitted
+  Flow ClaimsFlow {
+    /* type 2: (event production) */
+    command SubmitClaim emits event ClaimSubmitted
 
-    /* type 2 alternative: (event production) */
-    operation submitClaim emits event ClaimSubmitted
+    /* type 2 alternative: (event production) */
+    operation submitClaim emits event ClaimSubmitted
 
-    /* type 1: (command invokation) */
-    event ClaimSubmitted triggers command CheckClaimDocumentation
+    /* type 1: (command invokation) */
+    event ClaimSubmitted triggers command CheckClaimDocumentation
 
-    /* type 1 alternative: (operation invokation) */
-    event ClaimSubmitted triggers operation checkClaimDocumentation
+    /* type 1 alternative: (operation invokation) */
+    event ClaimSubmitted triggers operation checkClaimDocumentation
   }
 }
-
+``` #### Emitting Events A command or operation can emit multiple events. This is expressed with the _+_ sign as follows: -
command SubmitClaim emits event Event1 + Event2 + Event3 // and so on... (emit as many events as you want)
+```cml
+command SubmitClaim emits event Event1 + Event2 + Event3 // and so on... (emit as many events as you want)
 
-// alternative
-operation submitClaim emits event Event1 + Event2
-
+// alternative +operation submitClaim emits event Event1 + Event2 +``` The example above illustrates that an operation emits **multiple** events events, which means, **all events are emitted**! @@ -220,19 +230,21 @@ There are situations in which you want to express that **one OR an other** event **Exclusive variant:** -
command SubmitClaim emits event Event1 X Event2 X Event3
+```cml
+command SubmitClaim emits event Event1 X Event2 X Event3
 
-// alternative
-operation submitClaim emits event Event1 X Event2
-
+// alternative +operation submitClaim emits event Event1 X Event2 +``` **Inclusive variant:** -
command SubmitClaim emits event Event1 O Event2 O Event3
+```cml
+command SubmitClaim emits event Event1 O Event2 O Event3
 
-// alternative
-operation submitClaim emits event Event1 O Event2
-
+// alternative +operation submitClaim emits event Event1 O Event2 +``` **Symbol Summary:** @@ -249,11 +261,12 @@ _Note:_ It is not possible to mix the symbols inside a single flow step (we do n #### Command/Operation triggered by multiple Events On the other hand a command or operation may only be triggered if multiple events happen. This is modelled as follows: -
event ClaimSubmitted + ContractChecked triggers command AssessClaim
+```cml
+event ClaimSubmitted + ContractChecked triggers command AssessClaim
 
-// alternative
-event ClaimSubmitted + ContractChecked triggers operation assessClaim
-
+// alternative +event ClaimSubmitted + ContractChecked triggers operation assessClaim +``` This example expresses that both events (_ClaimSubmitted_ as well as _ContractChecked_) _must_ have been emitted so that _AssessClaim_ is triggered. @@ -264,31 +277,34 @@ Similar to the _event productions_ explained above, it is possible that events t **Parallel variant:** -
event ClaimSubmitted triggers command CheckClaim + CheckPolicy
+```cml
+event ClaimSubmitted triggers command CheckClaim + CheckPolicy
 
-// operation alternative:
-event ClaimSubmitted triggers operation checkClaim + checkPolicy
-
+// operation alternative: +event ClaimSubmitted triggers operation checkClaim + checkPolicy +``` This example expresses that all listed operations/commands are triggered (parallel). **Exclusive variant:** -
event ClaimSubmitted triggers command CheckClaim X CheckPolicy
+```cml
+event ClaimSubmitted triggers command CheckClaim X CheckPolicy
 
-// operation alternative:
-event ClaimSubmitted triggers operation checkClaim X checkPolicy
-
+// operation alternative: +event ClaimSubmitted triggers operation checkClaim X checkPolicy +``` This example means that only one of the commands/operations is triggered. **Inclusive variant:** -
event ClaimSubmitted triggers command CheckClaim O CheckPolicy
+```cml
+event ClaimSubmitted triggers command CheckClaim O CheckPolicy
 
-// operation alternative:
-event ClaimSubmitted triggers operation checkClaim O checkPolicy
-
+// operation alternative: +event ClaimSubmitted triggers operation checkClaim O checkPolicy +``` This example expresses that one or multiple but not necessarily all commands/operations are triggered. @@ -307,11 +323,12 @@ Commands and operations are typically delegated to an Aggregate. This also corre In CML this means that you can optionally add the following reference to _event production_ steps (_Type 2_ above): -
command SubmitClaim delegates to Claims emits event Event1 X Event2 X Event3
+```cml
+command SubmitClaim delegates to Claims emits event Event1 X Event2 X Event3
 
-// alternative
-operation submitClaim delegates to Claims emits event Event1 X Event2
-
+// alternative +operation submitClaim delegates to Claims emits event Event1 X Event2 +``` Note that this is a reference to an Aggregate that must actually exist in your Bounded Context. In the example above there must be an Aggregate called _Claims_ in the same Bounded Context. @@ -322,22 +339,24 @@ _Note:_ State transition can be modelled on service and domain object operations If you use flows you can add the state transitions to the flow steps instead of modeling them inside the Aggregate (operations). The state transitions can be added to the _event production_ steps (_type 2_ above) as follows (optionally): -
command SubmitClaim delegates to Claims [ -> SUBMITTED ] emits event Event1 X Event2 X Event3
+```cml
+command SubmitClaim delegates to Claims [ -> SUBMITTED ] emits event Event1 X Event2 X Event3
 
-// alternative
-operation submitClaim delegates to Claims [ -> SUBMITTED ] emits event Event1 X Event2
-
+// alternative +operation submitClaim delegates to Claims [ -> SUBMITTED ] emits event Event1 X Event2 +``` For a complete documentation and examples for the state transition grammar we refer to the [Aggregate page](/docs/aggregate/#aggregate-lifecycle-and-state-transitions). #### Actors Commands or operations can be triggered by actors/users. In CML you can specify this (optionally) as follows: -
command SubmitClaim [ initiated by "Customer" ] delegates to Claims [ -> SUBMITTED ] emits event Event1
+```cml
+command SubmitClaim [ initiated by "Customer" ] delegates to Claims [ -> SUBMITTED ] emits event Event1
 
-// alternative
-operation submitClaim [ initiated by "Customer" ] delegates to Claims [ -> SUBMITTED ] emits event Event1
-
+// alternative +operation submitClaim [ initiated by "Customer" ] delegates to Claims [ -> SUBMITTED ] emits event Event1 +``` ### Visualization with BPMN Sketch Miner Once you modelled an application flow you can visualize it in the [BPMN Sketch Miner](https://www.bpmn-sketch-miner.ai/). Use Context Mapper's [BPMN Sketch Miner generator](/docs/bpmn-sketch-miner/) to generate the Sketch Miner DSL output or directly open the visualization in the browser. @@ -353,48 +372,48 @@ In case you want to model processes/workflows that span multiple Bounded Context To model these workflows in Context Mapper, you use the _coordination_ construct inside the _application_ layer of a Bounded Context. The following example illustrates this using an adaptation of the same claims processing concept from before: -
ContextMap {
-  contains ClaimsManagement
-  contains InsuranceManagement
-  contains PaymentManagement
+```cml
+ContextMap {
+  contains ClaimsManagement
+  contains InsuranceManagement
+  contains PaymentManagement
 
-  ClaimsManagement <-> InsuranceManagement
-  ClaimsManagement <-> PaymentManagement
+  ClaimsManagement <-> InsuranceManagement
+  ClaimsManagement <-> PaymentManagement
 }
 
-BoundedContext ClaimsManagement {
-  Application {
-    Coordination SubmitValidClaimCoordination {
+BoundedContext ClaimsManagement {
+  Application {
+    Coordination SubmitValidClaimCoordination {
       ClaimsManagement::ClaimsApplicationService::submitClaim;
       InsuranceManagement::InsuranceApplicationService::checkInsurance;
       ClaimsManagement::ClaimsApplicationService::acceptClaim;
       PaymentManagement::PaymentApplicationService::performPayment;
     }
 
-    Service ClaimsApplicationService {
-      void submitClaim(@Claim claim);
-      void acceptClaim(@Claim claim);
+    Service ClaimsApplicationService {
+      void submitClaim(@Claim claim);
+      void acceptClaim(@Claim claim);
     }
   }
 }
 
-BoundedContext InsuranceManagement {
-  Application {
-    Service InsuranceApplicationService {
-      void checkInsurance(@Claim claim);
+BoundedContext InsuranceManagement {
+  Application {
+    Service InsuranceApplicationService {
+      void checkInsurance(@Claim claim);
     }
   }
 }
 
-BoundedContext PaymentManagement {
-  Application {
-    Service PaymentApplicationService {
-      void performPayment(@Claim claim);
+BoundedContext PaymentManagement {
+  Application {
+    Service PaymentApplicationService {
+      void performPayment(@Claim claim);
     }
   }
 }
-
-
+``` _Note:_ The type of workflow coordination (orchestration or choreography) is not explicitly supported in the syntax, but can still be modeled by assuming that the Bounded Context where the coordination is defined serves as either the orchestrator, or the start of the choreography. @@ -409,10 +428,10 @@ To correctly reference an application service operation, a coordination step is The following is an example of a coordination step: -
// Bounded context name :: application service name :: service operation name
+```cml
+// Bounded context name :: application service name :: service operation name
 ClaimsManagement::ClaimsApplicationService::submitClaim;
-
-
+``` Each of the three segments of a coordination step is also subject to certain syntax rules to maintain the integrity of the model. Respectively, these are: diff --git a/_docs/language-reference/bounded-context.md b/_docs/language-reference/bounded-context.md index 8776bfa..f6de54c 100644 --- a/_docs/language-reference/bounded-context.md +++ b/_docs/language-reference/bounded-context.md @@ -10,32 +10,33 @@ Bounded Contexts are defined on the root level of a CML (*.cml) file and then re ## Syntax The following example illustrates how a bounded context is defined in CML (syntactical features). The **Customer Management** context is a context within our fictitious insurance company example. The whole example with the context map and all bounded contexts can be found [here](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/insurance-example). -
BoundedContext CustomerManagementContext implements CustomerManagementDomain {
-  type = FEATURE
-  domainVisionStatement = "The customer management context is responsible for ..."
-  implementationTechnology = "Java, JEE Application"
-  responsibilities = "Customers", "Addresses"
-  knowledgeLevel = CONCRETE
-
-  Module addresses {
-    Aggregate Addresses {
-      Entity Address {
-        String city
+```cml
+BoundedContext CustomerManagementContext implements CustomerManagementDomain {
+  type = FEATURE
+  domainVisionStatement = "The customer management context is responsible for ..."
+  implementationTechnology = "Java, JEE Application"
+  responsibilities = "Customers", "Addresses"
+  knowledgeLevel = CONCRETE
+
+  Module addresses {
+    Aggregate Addresses {
+      Entity Address {
+        String city
       }
     }
   }
-  Aggregate Customers {
-    Entity Customer {
-      aggregateRoot
-
-      - SocialInsuranceNumber sin
-      String firstname
-      String lastname
-      - List<Address> addresses
+  Aggregate Customers {
+    Entity Customer {
+      aggregateRoot
+
+      - SocialInsuranceNumber sin
+      String firstname
+      String lastname
+      - List
addresses } } } -
+```
Note: Bounded Context names must be unique within your CML model. @@ -45,12 +46,13 @@ The **implements** keyword specifies which domain or subdomains are implemented keyword you can either reference a list of subdomains (comma-separated) or one top-level domain. Consult [Subdomain](/docs/subdomain/) to learn how subdomains are specified. Attribute values are assigned as follows: -
BoundedContext ContextMapperTool refines StrategicDomainDrivenDesignContext {
-  type FEATURE
-  domainVisionStatement "Context Mapper provides a formal way to model strategic DDD Context Maps."
-  implementationTechnology "Java, Eclipse"
+```cml
+BoundedContext ContextMapperTool refines StrategicDomainDrivenDesignContext {
+  type FEATURE
+  domainVisionStatement "Context Mapper provides a formal way to model strategic DDD Context Maps."
+  implementationTechnology "Java, Eclipse"
 }
-
+``` An equal sign (=) to assign attribute values may be present but can be omitted. The example above also shows how you can let one bounded context refine another one (with the **refines** keyword). This feature allows you to create some kind of an inheritance hierarchy in case one bounded context can be seen as a refinement of another bounded context. However, note that this is only a modeling information and generators do not recursively resolve the domain model (Aggregates, etc.) of refined bounded contexts. @@ -128,11 +130,12 @@ Further reading on bounded context canvases: ### Team _realizes_ Bounded Context If your bounded context is of the type TEAM, you can specify which bounded context the team implements by using the _realizes_ keyword. The following example illustrates this: -
BoundedContext CustomersBackofficeTeam implements CustomerManagementDomain realizes CustomerManagementContext {
-  type = TEAM
-  domainVisionStatement = "This team is responsible for implementing ..."
+```cml
+BoundedContext CustomersBackofficeTeam implements CustomerManagementDomain realizes CustomerManagementContext {
+  type = TEAM
+  domainVisionStatement = "This team is responsible for implementing ..."
 }
-
+``` ## The Bounded Context Building Blocks diff --git a/_docs/language-reference/conformist.md b/_docs/language-reference/conformist.md index b5ba890..d9c8546 100644 --- a/_docs/language-reference/conformist.md +++ b/_docs/language-reference/conformist.md @@ -9,10 +9,11 @@ The Conformist pattern describes a relationship between two bounded contexts and The Conformist pattern can be used as a role for the downstream context in a Upstream/Downstream relationship by using the **CF** abbreviation. The following example illustrates the syntax: -
PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
-  implementationTechnology = "RESTful HTTP"
+```cml
+PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
+  implementationTechnology = "RESTful HTTP"
 }
-
+``` ## Semantic Rules Note that semantic rules (validators) exist for Conformist within CML. This means that not every combination of patterns and concepts is allowed, even if it would be syntactically correct. diff --git a/_docs/language-reference/context-map.md b/_docs/language-reference/context-map.md index b8e9c6f..08b0fe3 100644 --- a/_docs/language-reference/context-map.md +++ b/_docs/language-reference/context-map.md @@ -11,29 +11,31 @@ A context map contains bounded contexts and defines their relationships. The int The following CML code snippet illustrates an example for a context map, according to our customized [DDD Sample](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/ddd-sample). With the _contains_ keyword you add a bounded context to the map. -
ContextMap {
-  type = SYSTEM_LANDSCAPE
-  state = AS_IS
-
-  contains CargoBookingContext
-  contains VoyagePlanningContext
-  contains LocationContext
-	
-  CargoBookingContext [SK]<->[SK] VoyagePlanningContext
+```cml
+ContextMap {
+  type = SYSTEM_LANDSCAPE
+  state = AS_IS
+
+  contains CargoBookingContext
+  contains VoyagePlanningContext
+  contains LocationContext
+
+  CargoBookingContext [SK]<->[SK] VoyagePlanningContext
 }
-
+``` Alternatively, you can use only one _contains_ keyword and list all bounded contexts comma-separated: -
ContextMap DDDSampleContextMap {
-  type SYSTEM_LANDSCAPE
-  state AS_IS
+```cml
+ContextMap DDDSampleContextMap {
+  type SYSTEM_LANDSCAPE
+  state AS_IS
 
-  contains CargoBookingContext, VoyagePlanningContext, LocationContext
+  contains CargoBookingContext, VoyagePlanningContext, LocationContext
 
-  CargoBookingContext [SK]<->[SK] VoyagePlanningContext
+  CargoBookingContext [SK]<->[SK] VoyagePlanningContext
 }
-
+``` As you can see in the example above, it is also possible to name a context map (the name is optional). The equal sign (=) to assign an attribute value as done in the first example can be omitted as well. @@ -74,49 +76,59 @@ The symmetric relationships and their syntax are introduced on separate pages: [ Upstream-Downstream relationships can be defined with three different syntax variants, all illustrated with the examples below: -
CargoBookingContext [D]<-[U] LocationContext
-
+```cml +CargoBookingContext [D]<-[U] LocationContext +``` -
LocationContext [U]->[D] CargoBookingContext
-
+```cml +LocationContext [U]->[D] CargoBookingContext +``` -
LocationContext Upstream-Downstream CargoBookingContext
-
+```cml +LocationContext Upstream-Downstream CargoBookingContext +``` -
CargoBookingContext Downstream-Upstream LocationContext
-
+```cml +CargoBookingContext Downstream-Upstream LocationContext +``` All of the four variants are semantically equivalent. Note that the arrow _->_ always points from the upstream to the downstream and thus expresses an *influence flow* (the upstream has an influence on the downstream, but the downstream has no influence on the upstream). A colon at the end assigns a relationship a name: -
CargoBookingContext [D]<-[U] LocationContext : CargoLocationRelationship
-
+```cml +CargoBookingContext [D]<-[U] LocationContext : CargoLocationRelationship +``` **Note:** The following quick upstream/downstream syntax without brackets can be used as well. It denotes a common upstream/downstream relationship without any roles. However, with this syntax it is less clear for a reader that you declare an upstream/downstream and *not* a customer/supplier relationship. -
CargoBookingContext <- LocationContext
-
+```cml +CargoBookingContext <- LocationContext +``` -
LocationContext -> CargoBookingContext
-
+```cml +LocationContext -> CargoBookingContext +``` ### Relationship Roles You can further specify the relationship roles such as Open Host Service (OHS) or Anti-Corruption Layer (ACL) within the brackets. Roles must always be specified behind the **U** (upstream) and the **D** (downstream) if they are not omitted. -
VoyagePlanningContext [D,ACL]<-[U,OHS,PL] LocationContext
-
+```cml +VoyagePlanningContext [D,ACL]<-[U,OHS,PL] LocationContext +``` Since the arrow already indicates which Bounded Context is upstream and which is downstream, it is also possible to add the relationship roles within the brackets without the **U** and the **D**: -
VoyagePlanningContext [ACL]<-[OHS,PL] LocationContext
-
+```cml +VoyagePlanningContext [ACL]<-[OHS,PL] LocationContext +``` If you use the _Upstream-Downstream_ or _Downstream-Upstream_ keywords the roles are declared equivalently, but without the **D** and **U** (note that it does not matter if you write a whitespace before or after the brackets, or both): -
VoyagePlanningContext[ACL] Downstream-Upstream [OHS,PL]LocationContext
-
+```cml +VoyagePlanningContext[ACL] Downstream-Upstream [OHS,PL]LocationContext +``` Upstream roles are defined by the [Open Host Service (OHS)](/docs/open-host-service/) and [Published Language (PL)](/docs/published-language/) patterns. Downstream roles are [Conformist (CF)](/docs/conformist/) and @@ -131,19 +143,21 @@ By using brackets {}, you can specify additional attributes for a relationship: #### Implementation Technology Within the body of the declaration, it is possible to specify the implementation technology used to realize this relationship: -
VoyagePlanningContext [D,ACL]<-[U,OHS,PL] LocationContext {
-    implementationTechnology = "RESTful HTTP"
+```cml
+VoyagePlanningContext [D,ACL]<-[U,OHS,PL] LocationContext {
+    implementationTechnology = "RESTful HTTP"
 }
-
+``` #### Downstream Governance Rights The attribute _downstreamRights_ defines which governance rights, and therefore which influence, the downstream has on the upstream within the specified relationship: -
VoyagePlanningContext [D,ACL]<-[U,OHS,PL] LocationContext {
-    implementationTechnology = "RESTful HTTP"
-    downstreamRights = VETO_RIGHT
+```cml
+VoyagePlanningContext [D,ACL]<-[U,OHS,PL] LocationContext {
+    implementationTechnology = "RESTful HTTP"
+    downstreamRights = VETO_RIGHT
 }
-
+``` The possible governance rights values are: @@ -156,12 +170,13 @@ The possible governance rights values are: #### Exposed Aggregates The _exposedAggregates_ attribute offers the possibility to declare which [Aggregates](/docs/aggregate) of the **upstream** bounded context are exposed in order to realize this relationship. The attribute takes a comma-separated list of references to Aggregates. The referenced Aggregates must be part of the upstream context of the relationship. -
VoyagePlanningContext [D,ACL]<-[U,OHS,PL] LocationContext {
-    implementationTechnology = "RESTful HTTP"
-    downstreamRights = VETO_RIGHT
-    exposedAggregates = Customers, Addresses
+```cml
+VoyagePlanningContext [D,ACL]<-[U,OHS,PL] LocationContext {
+    implementationTechnology = "RESTful HTTP"
+    downstreamRights = VETO_RIGHT
+    exposedAggregates = Customers, Addresses
 }
-
+``` ### Special Case: Customer/Supplier For the Customer-Supplier relationship, which is a special form of Upstream-Downstream relationship, please visit [Customer-Supplier](/docs/customer-supplier). diff --git a/_docs/language-reference/customer-supplier.md b/_docs/language-reference/customer-supplier.md index 5b6d698..e6f3a7e 100644 --- a/_docs/language-reference/customer-supplier.md +++ b/_docs/language-reference/customer-supplier.md @@ -22,17 +22,21 @@ explicitly) ## Syntax Customer-Supplier relationships can be defined with three different syntax variants, all illustrated with the examples below: -
CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext
-
+```cml +CustomerSelfServiceContext [D,C]<-[U,S] CustomerManagementContext +``` -
CustomerManagementContext [U,S]->[D,C] CustomerSelfServiceContext
-
+```cml +CustomerManagementContext [U,S]->[D,C] CustomerSelfServiceContext +``` -
CustomerSelfServiceContext Customer-Supplier CustomerManagementContext
-
+```cml +CustomerSelfServiceContext Customer-Supplier CustomerManagementContext +``` -
CustomerManagementContext Supplier-Customer CustomerSelfServiceContext
-
+```cml +CustomerManagementContext Supplier-Customer CustomerSelfServiceContext +``` All of the four variants are semantically equivalent. Note that the arrow _->_ always points from the supplier (upstream) to the customer (downstream) and thus, expresses the influence flow (the supplier has an influence on the customer, but the customer has no influence on the supplier). @@ -40,14 +44,16 @@ and thus, expresses the influence flow (the supplier has an influence on the cus In a Customer/Supplier relationship definition you can also omit the **U** (upstream) and **D** (downstream) specification, since the supplier is always the upstream and the customer always the downstream: -
CustomerSelfServiceContext [C]<-[S] CustomerManagementContext
-
+```cml +CustomerSelfServiceContext [C]<-[S] CustomerManagementContext +``` With a colon at the end, you can give every relationship a name: -
CustomerSelfServiceContext [D,C,ACL]<-[U,S,PL] CustomerManagementContext : Customer_Frontend_Backend_Relationship { // Relationship name is optional
-  implementationTechnology = "RESTful HTTP"
+```cml
+CustomerSelfServiceContext [D,C,ACL]<-[U,S,PL] CustomerManagementContext : Customer_Frontend_Backend_Relationship { // Relationship name is optional
+  implementationTechnology = "RESTful HTTP"
 }
-
+``` Within the brackets you can further specify the relationship roles such as Open Host Service (OHS) or Anti-Corruption Layer (ACL). Roles must always be specified behind the **U**/**S** (upstream/supplier) and the **D**/**C** (downstream/customer) signs, as shown in the example above. @@ -56,8 +62,9 @@ Within the body of the declaration it is possible to specify the implementation If you use the _Customer-Supplier_ or _Supplier-Customer_ keyword instead of the arrows, the roles are declared equivalently, but without the **C**/**D** and **S**/**U**: (note that it does not matter if you write a whitespace before or after the brackets, or both) -
CustomerSelfServiceContext[ACL] Customer-Supplier [PL]CustomerManagementContext
-
+```cml +CustomerSelfServiceContext[ACL] Customer-Supplier [PL]CustomerManagementContext +``` Upstream roles are given by the [Open Host Service (OHS)](/docs/open-host-service/) and [Published Language (PL)](/docs/published-language/) patterns. Downstream roles are [Conformist (CF)](/docs/conformist/) and [Anticorruption Layer (ACL)](/docs/anticorruption-layer/). diff --git a/_docs/language-reference/domain-vision-statement.md b/_docs/language-reference/domain-vision-statement.md index 0e273e9..e52d1ff 100644 --- a/_docs/language-reference/domain-vision-statement.md +++ b/_docs/language-reference/domain-vision-statement.md @@ -9,27 +9,30 @@ The Domain Vision Statement pattern from the ["blue book"](https://www.amazon.co ## Syntax The following two code snippets show an example for a bounded context, a domain, and a subdomain accordingly: -
BoundedContext CustomerContext {
-  domainVisionStatement = "This context is responsible for ..."
+```cml
+BoundedContext CustomerContext {
+  domainVisionStatement = "This context is responsible for ..."
 }
-
+``` -
Domain Insurance {
-  domainVisionStatement = "Insurance domain vision ..."
+```cml
+Domain Insurance {
+  domainVisionStatement = "Insurance domain vision ..."
 
-  Subdomain Customers {
-    /* subdomain specification */
+  Subdomain Customers {
+    /* subdomain specification */
   }
 
-  Subdomain PolicyManagement {
-    /* subdomain specification */
+  Subdomain PolicyManagement {
+    /* subdomain specification */
   }
 }
-
+``` -
Subdomain CustomerManagementDomain {
-  type = CORE_DOMAIN
-  domainVisionStatement = "Subdomain managing everything customer-related."
+```cml
+Subdomain CustomerManagementDomain {
+  type = CORE_DOMAIN
+  domainVisionStatement = "Subdomain managing everything customer-related."
 }
-
+``` diff --git a/_docs/language-reference/imports.md b/_docs/language-reference/imports.md index b56cd0f..12e24cf 100644 --- a/_docs/language-reference/imports.md +++ b/_docs/language-reference/imports.md @@ -10,74 +10,77 @@ One `*.cml` file can only contain one Context Map. However, multiple Context Map The following CML snippet could be in a file `BoundedContexts.cml` and specify some Bounded Contexts: -
BoundedContext CustomerManagementContext implements CustomerManagementDomain {
-  Aggregate Customers {
-    Entity Customer {
-      aggregateRoot
-
-      - SocialInsuranceNumber sin
-      String firstname
-      String lastname
-      - List<Address> addresses
+```cml
+BoundedContext CustomerManagementContext implements CustomerManagementDomain {
+  Aggregate Customers {
+    Entity Customer {
+      aggregateRoot
+
+      - SocialInsuranceNumber sin
+      String firstname
+      String lastname
+      - List
addresses } - Entity Address { - String street - int postalCode - String city + Entity Address { + String street + int postalCode + String city } } } -BoundedContext PolicyManagementContext implements PolicyManagementDomain { - Aggregate Contract { - Entity Contract { - aggregateRoot +BoundedContext PolicyManagementContext implements PolicyManagementDomain { + Aggregate Contract { + Entity Contract { + aggregateRoot - - ContractId identifier - - Customer client - - List<Product> products + - ContractId identifier + - Customer client + - List products } - Entity Policy { - int policyNr - - Contract contract - BigDecimal price + Entity Policy { + int policyNr + - Contract contract + BigDecimal price } } } -
+``` A file containing the ContextMap can then import the Bounded Contexts with the **import keyword**: -
import "./BoundedContexts.cml"
+```cml
+import "./BoundedContexts.cml"
 
-ContextMap InsuranceContextMap {
-  contains CustomerManagementContext
-  contains PolicyManagementContext
+ContextMap InsuranceContextMap {
+  contains CustomerManagementContext
+  contains PolicyManagementContext
 
-  PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
-    implementationTechnology = "RESTfulHTTP"
-    exposedAggregates = Customers
+  PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
+    implementationTechnology = "RESTfulHTTP"
+    exposedAggregates = Customers
   }
 }
-
+``` It is also possible to import `*.cml` files located in other directories: -
import "./BoundedContexts/CustomerManagement.cml"
-import "./BoundedContexts/PolicyManagement.cml"
+```cml
+import "./BoundedContexts/CustomerManagement.cml"
+import "./BoundedContexts/PolicyManagement.cml"
 
-ContextMap InsuranceContextMap {
-  contains CustomerManagementContext
-  contains PolicyManagementContext
+ContextMap InsuranceContextMap {
+  contains CustomerManagementContext
+  contains PolicyManagementContext
 
-  PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
-    implementationTechnology = "RESTfulHTTP"
-    exposedAggregates = Customers
+  PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
+    implementationTechnology = "RESTfulHTTP"
+    exposedAggregates = Customers
   }
 }
-
+```
Note: Although you can import *.cml files from different directories, our Eclipse plugin will only be able to resolve files within the same Eclipse project. diff --git a/_docs/language-reference/knowledge-level.md b/_docs/language-reference/knowledge-level.md index ff6f19b..f4f10ce 100644 --- a/_docs/language-reference/knowledge-level.md +++ b/_docs/language-reference/knowledge-level.md @@ -11,25 +11,27 @@ The Knowledge Level pattern can be used on bounded contexts and aggregates to sp ## Syntax The following examples show how you can specify the knowledge level on a bounded context and on an aggregate: -
BoundedContext CustomerManagementContext implements CustomerManagementDomain {
-  type = FEATURE
-  domainVisionStatement = "The customer management context is responsible for ..."
-  implementationTechnology = "Java, JEE Application"
-  knowledgeLevel = CONCRETE
+```cml
+BoundedContext CustomerManagementContext implements CustomerManagementDomain {
+  type = FEATURE
+  domainVisionStatement = "The customer management context is responsible for ..."
+  implementationTechnology = "Java, JEE Application"
+  knowledgeLevel = CONCRETE
 }
-
+``` -
Aggregate Customers {
-  responsibilities = Customers, Addresses { "Address description ..." }
-  knowledgeLevel = CONCRETE
-    
-  Entity Customer { 
-    aggregateRoot
-    
-    - SocialInsuranceNumber sin
-    String firstname
-    String lastname
-    - List<Address> addresses
+```cml
+Aggregate Customers {
+  responsibilities = Customers, Addresses { "Address description ..." }
+  knowledgeLevel = CONCRETE
+
+  Entity Customer {
+    aggregateRoot
+
+    - SocialInsuranceNumber sin
+    String firstname
+    String lastname
+    - List
addresses } } -
+``` diff --git a/_docs/language-reference/open-host-service.md b/_docs/language-reference/open-host-service.md index 4d5133d..fe57cb6 100644 --- a/_docs/language-reference/open-host-service.md +++ b/_docs/language-reference/open-host-service.md @@ -9,10 +9,11 @@ The Open Host Service pattern describes a relationship between two bounded conte The Open Host Service pattern can be used as a role for the upstream context in a Upstream/Downstream relationship by using the **OHS** abbreviation. The following example illustrates the syntax: -
PrintingContext [U,OHS]->[D,ACL] PolicyManagementContext {
-  implementationTechnology = "SOAP"
+```cml
+PrintingContext [U,OHS]->[D,ACL] PolicyManagementContext {
+  implementationTechnology = "SOAP"
 }
-
+``` ## Semantic Rules Note that semantic rules (validators) exist for Open Host Service within CML. This means that not every combination of patterns and concepts is allowed, even if it would be syntactically correct. diff --git a/_docs/language-reference/partnership.md b/_docs/language-reference/partnership.md index d552903..c27ad4b 100644 --- a/_docs/language-reference/partnership.md +++ b/_docs/language-reference/partnership.md @@ -8,17 +8,19 @@ The Partnership pattern describes a symmetric relationship between two bounded c ## Syntax Note that currently two different syntax variants exist. The following code snippets illustrate both variants: -
ContractsContext [P]<->[P] ClaimsContext {
-  implementationTechnology = "Messaging"
+```cml
+ContractsContext [P]<->[P] ClaimsContext {
+  implementationTechnology = "Messaging"
 }
-
+``` Note that with this syntax (with the arrows _<->_) it does not matter which bounded context is on which side, since this is a symmetric relationship. If you switch the bounded contexts, it has the same meaning semantically. -
ContractsContext Partnership ClaimsContext {
-  implementationTechnology = "Messaging"
+```cml
+ContractsContext Partnership ClaimsContext {
+  implementationTechnology = "Messaging"
 }
-
+``` ### Implementation Technology With the _implementationTechnology_ keyword you can specify how the relationship is implemented. @@ -26,7 +28,8 @@ With the _implementationTechnology_ keyword you can specify how the relationship ### Relationship Name With a colon it is possible (optionally) to add a relationship name to the specification, as illustrated within this example: -
ContractsContext [P]<->[P] ClaimsContext : ContractClaimRelationship {
-  implementationTechnology = "Messaging"
+```cml
+ContractsContext [P]<->[P] ClaimsContext : ContractClaimRelationship {
+  implementationTechnology = "Messaging"
 }
-
+``` diff --git a/_docs/language-reference/published-language.md b/_docs/language-reference/published-language.md index 6ce0ded..cd7cf03 100644 --- a/_docs/language-reference/published-language.md +++ b/_docs/language-reference/published-language.md @@ -9,7 +9,8 @@ The Published Language pattern describes a relationship between two bounded cont The Published Language pattern can be used as a role for the upstream context in a Upstream/Downstream relationship by using the **PL** abbreviation. The following example illustrates the syntax: -
PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
-  implementationTechnology = "RESTful HTTP"
+```cml
+PolicyManagementContext [D,CF]<-[U,OHS,PL] CustomerManagementContext {
+  implementationTechnology = "RESTful HTTP"
 }
-
+``` diff --git a/_docs/language-reference/responsibility-layers.md b/_docs/language-reference/responsibility-layers.md index 574fa43..8f51726 100644 --- a/_docs/language-reference/responsibility-layers.md +++ b/_docs/language-reference/responsibility-layers.md @@ -8,24 +8,26 @@ The Responsibility Layers pattern from the ["blue book"](https://www.amazon.com/ ## Syntax The responsibilities can simply be defined with the keyword/attribute _responsibilities_ and a list of responsibilities (as strings): -
BoundedContext CustomerManagementContext implements CustomerManagementDomain {
-  type = FEATURE
-  domainVisionStatement = "The customer management context is responsible for ..."
-  implementationTechnology = "Java, JEE Application"
-  responsibilities = "Customers", "Addresses"
+```cml
+BoundedContext CustomerManagementContext implements CustomerManagementDomain {
+  type = FEATURE
+  domainVisionStatement = "The customer management context is responsible for ..."
+  implementationTechnology = "Java, JEE Application"
+  responsibilities = "Customers", "Addresses"
 }
-
+``` -
Aggregate Customers {
-  responsibilities = "Customers", "Addresses"
-  
-  Entity Customer { 
-    aggregateRoot
-    
-    - SocialInsuranceNumber sin
-    String firstname
-    String lastname
-    - List<Address> addresses
+```cml
+Aggregate Customers {
+  responsibilities = "Customers", "Addresses"
+
+  Entity Customer {
+    aggregateRoot
+
+    - SocialInsuranceNumber sin
+    String firstname
+    String lastname
+    - List
addresses } } -
+``` diff --git a/_docs/language-reference/shared-kernel.md b/_docs/language-reference/shared-kernel.md index 042ff62..1512530 100644 --- a/_docs/language-reference/shared-kernel.md +++ b/_docs/language-reference/shared-kernel.md @@ -8,25 +8,28 @@ The Shared Kernel pattern describes a relationship between two bounded contexts ## Syntax Note that currently two different syntax variants exist. The following code snippets illustrate both variants: -
CargoBookingContext [SK]<->[SK] VoyagePlanningContext {
-  implementationTechnology = "Java Library"
+```cml
+CargoBookingContext [SK]<->[SK] VoyagePlanningContext {
+  implementationTechnology = "Java Library"
 }
-
+``` Note that with this syntax (with the arrows _<->_) it does not matter which bounded context is on which side, since this is a symmetric relationship. If you switch the bounded contexts, it has the same meaning semantically. -
CargoBookingContext Shared-Kernel VoyagePlanningContext {
-  implementationTechnology = "Java Library"
+```cml
+CargoBookingContext Shared-Kernel VoyagePlanningContext {
+  implementationTechnology = "Java Library"
 }
-
+``` ### Default Symmetric Relationship **Note** that the Shared Kernel is the default symmetric relationship. Omitting the concrete relationship type within the brackets as follows, declares a Shared Kernel relationship too. However, with this syntax a reader has to know this behavior and cannot explicitly see that it is **not** a Partnership relationship: -
CargoBookingContext <-> VoyagePlanningContext
-
+```cml +CargoBookingContext <-> VoyagePlanningContext +``` ### Implementation Technology With the _implementationTechnology_ keyword you can specify how the relationship is implemented. @@ -34,7 +37,8 @@ With the _implementationTechnology_ keyword you can specify how the relationship ### Relationship Name With a colon it is possible (optionally) to add a relationship name to the specification, as illustrated within this example: -
CargoBookingContext Shared-Kernel VoyagePlanningContext : BookingVoyageRelationship {
-  implementationTechnology = "Java Library"
+```cml
+CargoBookingContext Shared-Kernel VoyagePlanningContext : BookingVoyageRelationship {
+  implementationTechnology = "Java Library"
 }
-
+``` diff --git a/_docs/language-reference/stakeholders.md b/_docs/language-reference/stakeholders.md index d5062e0..89ba088 100644 --- a/_docs/language-reference/stakeholders.md +++ b/_docs/language-reference/stakeholders.md @@ -10,94 +10,96 @@ The CML language supports the modelling of [stakeholders](https://en.wikipedia.o ## Stakeholders Container On the root level of a CML file, one first needs to create a `Stakeholders` container. This can be done as simply as follows: -
Stakeholders {
+```cml
+Stakeholders {
 
-  // add stakeholders and stakeholder groups here
+  // add stakeholders and stakeholder groups here
 
 }
-
+``` However, if you want to model the stakeholders for a specific [Bounded Context](/docs/bounded-context/), you can declare that as follows: -
BoundedContext ExampleContext
+```cml
+BoundedContext ExampleContext
 
-Stakeholders of ExampleContext {
+Stakeholders of ExampleContext {
 
-  // add stakeholders and stakeholder groups here
+  // add stakeholders and stakeholder groups here
 
 }
-
+``` ## Stakeholders Inside a `Stakeholders` container, you can define your stakeholders. This can be done with the `Stakeholder` keyword an the name of the stakeholder: -
BoundedContext ExampleContext
+```cml
+BoundedContext ExampleContext
 
-Stakeholders of ExampleContext {
+Stakeholders of ExampleContext {
 
-  Stakeholder Shopper
+  Stakeholder Shopper
 
-  Stakeholder Software_Engineer
+  Stakeholder Software_Engineer
 
-  Stakeholder Architect
+  Stakeholder Architect
 
-  // etc.
+  // etc.
 
-}
-
-
+} +``` In addition, you can provide additional information for a stakeholder using the `description`, `influence` and `interest` keywords: -
BoundedContext ExampleContext
+```cml
+BoundedContext ExampleContext
+
+Stakeholders of ExampleContext {
 
-Stakeholders of ExampleContext {
+  Stakeholder Shopper {
+    description "Is using the shopping system to by everday goods."
 
-  Stakeholder Shopper {
-    description "Is using the shopping system to by everday goods."
-    
-    influence MEDIUM
-    interest HIGH
-  }
+    influence MEDIUM
+    interest HIGH
+  }
 
-}
-
-
+} +``` The `description` just describes why and/or how the stakeholder uses the system or is impacted by the system. As suggested by many stakeholder mapping tutorials (see [Miro](https://miro.com/blog/stakeholder-mapping/) or [Mural](https://www.mural.co/blog/stakeholder-mapping)), you can define what the `influence` of the stakeholders is and how much they are interested (`interest`) in the new system or feature. ## Stakeholder Groups Stakeholder maps often group stakeholders of similar roles or with similar interest together. This is also possible in CML with the `StakeholderGroup` keyword, which can again contain stakeholders with the `Stakeholder` keyword: -
BoundedContext ExampleContext
-
-Stakeholders of ExampleContext {
-
-  StakeholderGroup Online_Shopping_Company {
-    Stakeholder Development_Team {
-      influence MEDIUM
-      interest HIGH
-    }
-    Stakeholder Product_Management {
-      influence HIGH
-      interest HIGH
-    }
-    Stakeholder Customer_Relationship_Manager {
-      influence HIGH
-      interest MEDIUM
-    }
-  }
-
-  Stakeholder Shopper {
-    description "Is using the shopping system to by everday goods."
-    
-    influence MEDIUM
-    interest HIGH
-  }
-
-}
-
-
+```cml +BoundedContext ExampleContext + +Stakeholders of ExampleContext { + + StakeholderGroup Online_Shopping_Company { + Stakeholder Development_Team { + influence MEDIUM + interest HIGH + } + Stakeholder Product_Management { + influence HIGH + interest HIGH + } + Stakeholder Customer_Relationship_Manager { + influence HIGH + interest MEDIUM + } + } + + Stakeholder Shopper { + description "Is using the shopping system to by everday goods." + + influence MEDIUM + interest HIGH + } + +} +``` ## Visualization: Stakeholder Map Once your stakeholders are modelled in CML, you can generate a visual stakeholder map automatically. Here is an example: @@ -107,7 +109,7 @@ Once your stakeholders are modelled in CML, you can generate a visual stakeholde Check out our [PlantUML generator](/docs/plant-uml/) on how to generate such a diagram. ## Stakeholders Export to CSV -In addition to the Stakeholder Map visualization, you can export your modelled stakeholder data as a CSV file. To do so, use the Freemarker temple [here](https://raw.githubusercontent.com/ContextMapper/context-mapper-dsl/master/org.contextmapper.dsl.ui/samples/freemarker/csv-files/stakeholders.csv.ftl) together with our [Generic Generator (Freemarker Templating)](/docs/generic-freemarker-generator/). +In addition to the Stakeholder Map visualization, you can export your modelled stakeholder data as a CSV file. To do so, use the Freemarker temple [here](https://github.com/ContextMapper/context-mapper-dsl/blob/master/samples/freemarker/csv-files/stakeholders.csv.ftl) together with our [Generic Generator (Freemarker Templating)](/docs/generic-freemarker-generator/). ## Transformations Note that we offer several transformations that might help modelling stakeholders and their values according to [VDAD (Value-Driven Analysis and Design)](https://ethical-se.github.io/value-driven-analysis-and-design) more efficiently. The transformations are documented on the following page: [Stakeholder and Value Modelling Transformations](/docs/stakeholder-and-value-modelling-transformations/) diff --git a/_docs/language-reference/subdomain.md b/_docs/language-reference/subdomain.md index 8684920..0170979 100644 --- a/_docs/language-reference/subdomain.md +++ b/_docs/language-reference/subdomain.md @@ -10,27 +10,28 @@ A bounded context can also implement the compete domain. Have a look at [bounded ## Syntax The following example illustrates how you can specify a domain with subdomains in CML: -
/* Syntax example: Domain and Subdomains */
-Domain Insurance {
-  domainVisionStatement = "Insurance domain vision statement ..."
-
-  Subdomain CustomerManagementDomain {
-    type = CORE_DOMAIN
-    domainVisionStatement = "Subdomain managing everything customer-related."
-
-    Entity Customer {
-      String firstname
-      String familyname
+```cml
+/* Syntax example: Domain and Subdomains */
+Domain Insurance {
+  domainVisionStatement = "Insurance domain vision statement ..."
+
+  Subdomain CustomerManagementDomain {
+    type = CORE_DOMAIN
+    domainVisionStatement = "Subdomain managing everything customer-related."
+
+    Entity Customer {
+      String firstname
+      String familyname
     }
 
-    /* Add more entities ... */
+    /* Add more entities ... */
   }
 
-  Subdomain ContractManagementDomain {}
+  Subdomain ContractManagementDomain {}
 
-  /* Add more subdomains ... */
+  /* Add more subdomains ... */
 }
-
+``` Note that the equal sign (=) to assign an attribute value as done in the example above is optional and can be omitted. @@ -45,35 +46,36 @@ With the _type_ keyword you specify of which type your subdomain is. The followi The CML language supports the specification of user requirements or features in the form of [use cases or user stories](/docs/user-requirements/). With the _supports_ keyword you can specify which user requirements a Subdomain implements. An example: -
/* Syntax example for Subdomain that supports specific user requirements: */
-Domain Insurance {
-  domainVisionStatement = "Insurance domain vision statement ..."
+```cml
+/* Syntax example for Subdomain that supports specific user requirements: */
+Domain Insurance {
+  domainVisionStatement = "Insurance domain vision statement ..."
 
-  Subdomain CustomerManagementDomain supports CreateCustomers, CreateCustomerAddresses {
-    type = CORE_DOMAIN
-    domainVisionStatement = "Subdomain managing everything customer-related."
+  Subdomain CustomerManagementDomain supports CreateCustomers, CreateCustomerAddresses {
+    type = CORE_DOMAIN
+    domainVisionStatement = "Subdomain managing everything customer-related."
 
-    Entity Customer {
-      String firstname
-      String familyname
+    Entity Customer {
+      String firstname
+      String familyname
     }
   }
 
 }
 
-UserStory CreateCustomers {
-  As an "Insurance Employee"
-    I want to "create" a "Customer" with its "firstname", "lastname"
-  so that "I am able to manage the customers data and offer them insurance contracts."
+UserStory CreateCustomers {
+  As an "Insurance Employee"
+    I want to "create" a "Customer" with its "firstname", "lastname"
+  so that "I am able to manage the customers data and offer them insurance contracts."
 }
 
-UserStory CreateCustomerAddresses {
-  As an "Insurance Employee"
-    I want to "create" an "Address" for a "Customer"
-    I want to "update" an "Address" for a "Customer"
-  so that "I am able to manage the customers addresses."
+UserStory CreateCustomerAddresses {
+  As an "Insurance Employee"
+    I want to "create" an "Address" for a "Customer"
+    I want to "update" an "Address" for a "Customer"
+  so that "I am able to manage the customers addresses."
 }
-
+``` ### Domain Vision Statement With the _domainVisionStatement_ keyword you can specify a vision statement for domains and subdomains, according to the DDD [Domain Vision Statement](/docs/domain-vision-statement/) diff --git a/_docs/language-reference/tactic-ddd.md b/_docs/language-reference/tactic-ddd.md index cf411cb..abf501e 100644 --- a/_docs/language-reference/tactic-ddd.md +++ b/_docs/language-reference/tactic-ddd.md @@ -18,15 +18,16 @@ An entity is declared with the _Entity_ keyword, as illustrated below. With the within your aggregate is the root entity. The language provides primitive data types such as _String_, _int_ and _boolean_ etc., similar to Java. You can further use the collection types _List_, _Set_ and _Bag_. -
Entity Customer {
-  aggregateRoot
-
-  SocialInsuranceNumber sin
-  String firstname
-  String lastname
-  List<Address> addresses
+```cml
+Entity Customer {
+  aggregateRoot
+
+  SocialInsuranceNumber sin
+  String firstname
+  String lastname
+  List
addresses } -
+``` As illustrated in the example above, you can declare your own types (such as _Address_ and _SocialInsuranceNumber_ above). These types don't have to be further specified anywhere. However, you can also use references to existing types (entities, value objects, etc.) as described @@ -35,27 +36,28 @@ below. ### Type References To reference another type of your model within an attribute, you have to use the **-** (minus) sign: -
Aggregate Customers {
-  Entity Customer { 
-    aggregateRoot
-    
-    - SocialInsuranceNumber sin // Reference syntax for simple attribute
-    String firstname
-    String lastname
-    - List<Address> addresses // Reference syntax for collections
+```cml
+Aggregate Customers {
+  Entity Customer {
+    aggregateRoot
+
+    - SocialInsuranceNumber sin // Reference syntax for simple attribute
+    String firstname
+    String lastname
+    - List
addresses // Reference syntax for collections } - - Entity Address { - String street - int postalCode - String city + + Entity Address { + String street + int postalCode + String city } - - ValueObject SocialInsuranceNumber { - String sin key + + ValueObject SocialInsuranceNumber { + String sin key } } -
+``` When you use this reference notation with the _-_ (minus) sign, the language checks that the types (_Address_ and _SocialInsuranceNumber_ @@ -66,57 +68,60 @@ Of course you can also declare methods/operations on your _Entities_, _Value Obj is started with the **def** keyword. As illustrated below, you can use abstract data types which are not further declared in your method parameters and return types: -
Entity Customer { 
-  aggregateRoot
-  
-  - SocialInsuranceNumber sin
-  String firstname
-  String lastname
-  - List<Address> addresses
-  
-  def AddressId createAddress(Address address);
-  def void changeCustomer(Customer customer, Address address);
+```cml
+Entity Customer {
+  aggregateRoot
+
+  - SocialInsuranceNumber sin
+  String firstname
+  String lastname
+  - List
addresses + + def AddressId createAddress(Address address); + def void changeCustomer(Customer customer, Address address); } -
+``` If you want to **refer** existing types in your operation/method parameters and return types, you have to use the **@** character: -
Aggregate Customers {
-  Entity Customer { 
-    aggregateRoot
-    
-    - SocialInsuranceNumber sin
-    String firstname
-    String lastname
-    - List<Address> addresses
-    
-    def @AddressId createAddress(@Address address); // Method/Operation declaration with references
-    def void changeCustomer(@Customer customer, @Address address); // Method/Operation declaration with references
+```cml
+Aggregate Customers {
+  Entity Customer {
+    aggregateRoot
+
+    - SocialInsuranceNumber sin
+    String firstname
+    String lastname
+    - List
addresses + + def @AddressId createAddress(@Address address); // Method/Operation declaration with references + def void changeCustomer(@Customer customer, @Address address); // Method/Operation declaration with references } - - Entity Address { - String street - int postalCode - String city + + Entity Address { + String street + int postalCode + String city } - - ValueObject SocialInsuranceNumber { - String sin key + + ValueObject SocialInsuranceNumber { + String sin key } - - ValueObject AddressId { - int id + + ValueObject AddressId { + int id } } -
+``` ## Value Objects The declaration of value objects is done with the _ValueObject_ keyword: -
ValueObject HandlingHistory {
-  - List<HandlingEvent> handlingEvents
+```cml
+ValueObject HandlingHistory {
+  - List handlingEvents
 }
-
+``` ### Attributes & Methods/Operations Attributes (incl. type references) and methods/operations in value objects can be specified exactly the same way as within entities (see sections above). @@ -124,25 +129,27 @@ Attributes (incl. type references) and methods/operations in value objects can b ## Domain Events The declaration of domain events is done with the _DomainEvent_ keyword: (alternatively you can use the keyword _Event_) -
DomainEvent HandlingEvent {
-  Type handlingType;
-  - Voyage voyage;
-  - LocationShared location;
-  Date completionTime;
-  Date registrationTime;
-  - Cargo cargo;
+```cml
+DomainEvent HandlingEvent {
+  Type handlingType;
+  - Voyage voyage;
+  - LocationShared location;
+  Date completionTime;
+  Date registrationTime;
+  - Cargo cargo;
 }
-
+``` ## Commands The declaration of commands is done with the _Command_ keyword: (alternatively you can use the original Sculptor keyword _CommandEvent_) -
Command RejectClaim {
+```cml
+Command RejectClaim {
   - Claim claim2Reject
   - Employee decisionMaker
-  String reason4Rejection
+  String reason4Rejection
 }
-
+``` ### Attributes & Methods/Operations Attributes (incl. type references) and methods/operations in domain events can be specified exactly the same way as within entities (see sections above). @@ -151,10 +158,11 @@ Attributes (incl. type references) and methods/operations in domain events can b Within your [bounded context](/docs/bounded-context) (or also inside aggregates) you can specify domain services according to the tactic DDD _Service_ pattern. Domain services are declared with the _Service_ keyword and contain one or more methods/operations. These methods/operations are declared exactly the same way as within entities, value objects or domain events, **but without the _def_ keyword**: -
Service RoutingService {
-  List<@Itinerary> fetchRoutesForSpecification(@RouteSpecification routeSpecification) throws LocationNotFoundException;
+```cml
+Service RoutingService {
+  List<@Itinerary> fetchRoutesForSpecification(@RouteSpecification routeSpecification) throws LocationNotFoundException;
 }
-
+``` With the _throws_ keyword you can specify that the method/operation can throw a specific exception (as in Java). @@ -166,30 +174,31 @@ which is ensured by a semantic checker of the language. A repository can contain the example below. These methods/operations are declared exactly the same way as within entities, value objects or domain events, **but without the _def_ keyword**: -
Aggregate Location {
-  Entity Location {
-    aggregateRoot
-    
-    PortCode portcode
-    - UnLocode unLocode;
-    String name;
-    
-    Repository LocationRepository {
+```cml
+Aggregate Location {
+  Entity Location {
+    aggregateRoot
+
+    PortCode portcode
+    - UnLocode unLocode;
+    String name;
+
+    Repository LocationRepository {
       @Location find(@UnLocode unLocode);
-      List<@Location> findAll();
+      List<@Location> findAll();
     }
   }
-  
-  ValueObject UnLocode {
-    String unLocode
+
+  ValueObject UnLocode {
+    String unLocode
   }
-  
-  ValueObject LocationShared {
-    PortCode portCode
-    - Location location
+
+  ValueObject LocationShared {
+    PortCode portCode
+    - Location location
   }
 }
-
+``` ## More Details about the Tactic DDD Syntax If you want to read more details about the syntax of the tactic DDD part within bounded contexts, we refer to the [Sculptor documentation](https://sculptor.github.io/documentation/advanced-tutorial). diff --git a/_docs/language-reference/user-requirements.md b/_docs/language-reference/user-requirements.md index 320a467..4bd946f 100644 --- a/_docs/language-reference/user-requirements.md +++ b/_docs/language-reference/user-requirements.md @@ -12,27 +12,29 @@ and the _benefit_ of a use case or user story. ## Use Case The syntax to declare a use case rather briefly is as follows: -
UseCase UC1_Example {
-  actor = "Insurance Employee"
-  interactions = create a "Customer", update a "Customer", "offer" a "Contract"
-  benefit = "I am able to manage the customers data and offer them insurance contracts."
+```cml
+UseCase UC1_Example {
+  actor = "Insurance Employee"
+  interactions = create a "Customer", update a "Customer", "offer" a "Contract"
+  benefit = "I am able to manage the customers data and offer them insurance contracts."
 }
-
+``` The predicate (verb) in the `interaction` can be one of the keywords `create`, `read`, `update`, `delete` (CRUD), or any string. Optionally, it is further possible to add _attributes_ to the Entities and/or a reference to another Entity that acts as a _container_. The following example illustrates the use case including this features: -
UseCase UC1_Example {
-  actor "Insurance Employee"
-  interactions
-    create a "Customer" with its "firstname", "lastname",
-    update an "Address" for a "Customer",
-    "offer" a "Contract" for a "Customer"
-  benefit "I am able to manage the customers data and offer them insurance contracts."
+```cml
+UseCase UC1_Example {
+  actor "Insurance Employee"
+  interactions
+    create a "Customer" with its "firstname", "lastname",
+    update an "Address" for a "Customer",
+    "offer" a "Contract" for a "Customer"
+  benefit "I am able to manage the customers data and offer them insurance contracts."
 }
-
+``` The entity attributes follow the keyword _with its_ as illustrated above. The reference to the container Entity can be modelled with the following keywords: _for a_, _for an_, _in a_, _in an_. @@ -42,56 +44,60 @@ Our grammar supports creating Use Cases according to the _brief_ or _casual_ for but gives the prose paragraphs some structure. The following example illustrates the Use Case 2 ("Get paid for car accident") of [A. Cockburn's book](https://www.amazon.de/Writing-Effective-Crystal-Software-Development/dp/0201702258) written in CML: -
UseCase Get_paid_for_car_accident { // title
-  actor "Claimant" // primary actor
-  scope "Insurance company" // scope
-  level "Summary" // level
-  benefit "A claimant submits a claim and and gets paid from the insurance company." // story (brief summary)
+```cml
+UseCase Get_paid_for_car_accident { // title
+  actor "Claimant" // primary actor
+  scope "Insurance company" // scope
+  level "Summary" // level
+  benefit "A claimant submits a claim and and gets paid from the insurance company." // story (brief summary)
 }
-
+``` We do not support all attributes for a _fully dressed_ Use Case (another style [suggested by A. Cockburn](https://en.wikipedia.org/wiki/Use_case#Cockburn_style)), but you can use the _interactions_ introduced above to model the _main success scenario_: -
UseCase Get_paid_for_car_accident { // title
-  actor "Claimant" // primary actor
-  scope "Insurance company" // scope
-  level "Summary" // level
-  benefit "A claimant submits a claim and and gets paid from the insurance company." // story (brief summary)
-  interactions
-    "submit" a "Claim",                // step 1: claimant submits claim
-    "verifyExistanceOf" "Policy",      // step 2: insurance company verifies that valid policy exists
-    "assign" an "Agent" for a "Claim", // step 3: agent is assigned to claim
-    "verify" "Policy",                 // step 4: agent verifies all details are within policy guidelines
-    "pay" "Claimant",                  // step 5 (1): claimant gets paid
-    "close" "Claim"                    // step 5 (2): file/claim gets closed
+```cml
+UseCase Get_paid_for_car_accident { // title
+  actor "Claimant" // primary actor
+  scope "Insurance company" // scope
+  level "Summary" // level
+  benefit "A claimant submits a claim and and gets paid from the insurance company." // story (brief summary)
+  interactions
+    "submit" a "Claim",                // step 1: claimant submits claim
+    "verifyExistanceOf" "Policy",      // step 2: insurance company verifies that valid policy exists
+    "assign" an "Agent" for a "Claim", // step 3: agent is assigned to claim
+    "verify" "Policy",                 // step 4: agent verifies all details are within policy guidelines
+    "pay" "Claimant",                  // step 5 (1): claimant gets paid
+    "close" "Claim"                    // step 5 (2): file/claim gets closed
 }
-
+``` ### Secondary Actors If your use case involves secondary actors, you can use the _secondaryActors_ keyword as shown in the following example: -
UseCase UC1_Example {
-  actor = "Insurance Employee"
-  secondaryActors = "Insurance Administrator", "Sales Person"
-  interactions = create a "Customer", update a "Customer", "offer" a "Contract"
-  benefit = "I am able to manage the customers data and offer them insurance contracts."
+```cml
+UseCase UC1_Example {
+  actor = "Insurance Employee"
+  secondaryActors = "Insurance Administrator", "Sales Person"
+  interactions = create a "Customer", update a "Customer", "offer" a "Contract"
+  benefit = "I am able to manage the customers data and offer them insurance contracts."
 }
-
+``` All actors are respected in our [PlantUML Generator (Use Case Diagram)](/docs/plant-uml/). ## User Story First and foremost, a user story is an invitation to communicate and collaborate, as well a planning item. That said, the [role-feature-reason template](https://www.agilealliance.org/glossary/user-story-template/) can also serve as a requirements specification element. Hence, the user story support in CML allows you to declare exactly the same information as seen in the use case above, but in another syntax: -
UserStory US1_Example {
-  As an "Insurance Employee"
-    I want to "create" a "Customer" with its "firstname", "lastname" // attributes are optional ('with its' part)
-    I want to "update" an "Address" for a "Customer" // reference is optional ('for a' part)
-    I want to "offer" a "Contract" for a "Customer" // reference is optional ('for a' part)
-  so that "I am able to manage the customers data and offer them insurance contracts."
+```cml
+UserStory US1_Example {
+  As an "Insurance Employee"
+    I want to "create" a "Customer" with its "firstname", "lastname" // attributes are optional ('with its' part)
+    I want to "update" an "Address" for a "Customer" // reference is optional ('for a' part)
+    I want to "offer" a "Contract" for a "Customer" // reference is optional ('for a' part)
+  so that "I am able to manage the customers data and offer them insurance contracts."
 }
-
+``` *Note:* As you can see above, both variants allow users to specify multiple _interactions_ or _I want to_ parts in one use case or user story. You can see this as a way of expressing related features, for instance those originating from splitting a larger story - or the steps in a use case scenario. @@ -99,12 +105,12 @@ expressing related features, for instance those originating from splitting a lar ### Story Valuation Since Context Mapper version 6.12.x, the user story syntax supports [story valuation](https://github.com/ethical-se/ese-practices/blob/main/practices/ESE-StoryValuation.md). A user story with the existing `As a`, `I want to` and `so that` parts can now be enhanced with promoted and harmed [ethical values](https://github.com/ethical-se/ese-practices/blob/v11/ESE-Glossary.md#ethical-value), as shown in the following example: -
UserStory SampleStory {
-  As a "prospective customer of Lakeside Mutual" // a fictitious insurance company
-  I want to "manage" the "PersonalDataProfile" 
-  so that "I am offered a valid and fair insurance rate"
-  and that "data privacy" is promoted
-  accepting that "accountability and auditability" are harmed
-}
-
-
+```cml +UserStory SampleStory { + As a "prospective customer of Lakeside Mutual" // a fictitious insurance company + I want to "manage" the "PersonalDataProfile" + so that "I am offered a valid and fair insurance rate" + and that "data privacy" is promoted + accepting that "accountability and auditability" are harmed +} +``` diff --git a/_docs/language-reference/values.md b/_docs/language-reference/values.md index ea476c5..04f4190 100644 --- a/_docs/language-reference/values.md +++ b/_docs/language-reference/values.md @@ -10,73 +10,73 @@ The CML language supports the modelling of stakeholders and their values that mi ## Value Register If you are interested in reading more about the ideas of a _value register_, we refer to the [IEEE 7000 standard](https://ieeexplore.ieee.org/document/9536679) or the [ESE Glossary](https://github.com/ethical-se/ese-practices/blob/main/ESE-Glossary.md). However, if you just want to move on quickly and model the values of your stakeholders - just consider the value register a _container object_ that allows to model values for a specific Bounded Context: -
BoundedContext Online_Shop_Same_Day_Delivery
+```cml
+BoundedContext Online_Shop_Same_Day_Delivery
 
-ValueRegister SDD_Stakeholder_Values for Online_Shop_Same_Day_Delivery {
-  // model values inside value register
-}
-
-
+ValueRegister SDD_Stakeholder_Values for Online_Shop_Same_Day_Delivery { + // model values inside value register +} +``` If you just want to start to model some values without separating by Bounded Contexts, you can create a `ValueRegister` without that reference: -
ValueRegister SDD_Stakeholder_Values {
-  // model values inside value register
-}
-
-
+```cml +ValueRegister SDD_Stakeholder_Values { + // model values inside value register +} +``` ## Values Inside a value register you can define the values important to your project, software and/or feature: -
ValueRegister SDD_Stakeholder_Values {
-  
-  Value Privacy
-  Value Respect
-  Value Integrity
-  Value Love
-  // etc.
+```cml
+ValueRegister SDD_Stakeholder_Values {
 
-}
-
-
+ Value Privacy + Value Respect + Value Integrity + Value Love + // etc. + +} +``` The following attributes that can be added, namely whether a value is a _core value_, _value demonstrators_, _related values_ and _opposing values_, follow the terminology of the [IEEE 7000 standard](https://ieeexplore.ieee.org/document/9536679). We refer to the standard for a more detailed introduction into these terms; in CML the attributes are however not mandatory. -
ValueRegister SDD_Stakeholder_Values {
-  
-  Value Privacy {
-    isCore
+```cml
+ValueRegister SDD_Stakeholder_Values {
 
-    demonstrator = "right to be left alone"
-    demonstrator = "the right to refuse sharing private data"
-    relatedValue = "Intimacy"
-    opposingValue = "Transparency"
-    opposingValue = "Inclusiveness"
-  }
+  Value Privacy {
+    isCore
 
-}
-
-
+ demonstrator = "right to be left alone" + demonstrator = "the right to refuse sharing private data" + relatedValue = "Intimacy" + opposingValue = "Transparency" + opposingValue = "Inclusiveness" + } + +} +``` As always in CML, the 'equal' (=) sign is optional: -
ValueRegister SDD_Stakeholder_Values {
-  
-  Value Privacy {
-    isCore
+```cml
+ValueRegister SDD_Stakeholder_Values {
 
-    demonstrator "right to be left alone"
-    demonstrator "the right to refuse sharing private data"
-    relatedValue "Intimacy"
-    opposingValue "Transparency"
-    opposingValue "Inclusiveness"
-  }
+  Value Privacy {
+    isCore
 
-}
-
-
+ demonstrator "right to be left alone" + demonstrator "the right to refuse sharing private data" + relatedValue "Intimacy" + opposingValue "Transparency" + opposingValue "Inclusiveness" + } + +} +```
Note: Just modelling values, as seen here, does not allow you to generate any visualization yet (at least for now). Continue with the section Stakeholder Priorisation, Impact & Consequences, to define how important these values are to individual stakeholders and how these stakeholders are affected. After that, you can generate a [Value Impact Map](https://ethical-se.github.io/value-driven-analysis-and-design/practices/value-impact-mapping) with the PlantUML generator. @@ -86,51 +86,51 @@ As always in CML, the 'equal' (=) sign is optional: If one applies or follows the [IEEE 7000 standard](https://ieeexplore.ieee.org/document/9536679), values are clustered around core values. For example, the value _confidentiality_ (a demonstrator could be: _right to be left alone_), is an enabler for the core value of _privacy_. Therefore the value _confidentiality_ would be added to the value cluster with the core value _privacy_. This can be modelled in CML as follows: -
ValueRegister SDD_Stakeholder_Values {
-  
-  ValueCluster Privacy {
-    core PRIVACY
+```cml
+ValueRegister SDD_Stakeholder_Values {
 
-    Value Confidentiality {
-      demonstrator = "right to be left alone"  
-    }
-  }
+  ValueCluster Privacy {
+    core PRIVACY
 
-}
-
-
+ Value Confidentiality { + demonstrator = "right to be left alone" + } + } + +} +``` The _core value_ can be modelled as shown above, by using the enumeration CML provides. That enumeration contains all _core values_ according to the [IEEE 7000 standard](https://ieeexplore.ieee.org/document/9536679): `AUTONOMY`, `CARE`, `CONTROL`, `FAIRNESS`, `INCLUSIVENESS`, `INNOVATION`, `PERFECTION`, `PRIVACY`, `RESPECT`, `SUSTAINABILITY`, `TRANSPARENCY`, `TRUST`. Alteratively, you can define the core value by a custom string: -
ValueRegister SDD_Stakeholder_Values {
-  
-  ValueCluster MyCluster {
-    core "Respect"
-  }
+```cml
+ValueRegister SDD_Stakeholder_Values {
 
-}
-
-
+ ValueCluster MyCluster { + core "Respect" + } + +} +``` Further note that the attributes `demonstrator`, `relatedValue` and `opposingValue`, as documented for the `Value` object already, can also be applied to value clusters: -
ValueRegister SDD_Stakeholder_Values {
-  
-  ValueCluster Privacy {
-    core PRIVACY
+```cml
+ValueRegister SDD_Stakeholder_Values {
 
-    demonstrator = "right to be left alone"
-    demonstrator = "the right to refuse sharing private data"
-    relatedValue = "Intimacy"
-    opposingValue = "Transparency"
-    opposingValue = "Inclusiveness"
-  }
+  ValueCluster Privacy {
+    core PRIVACY
 
-}
-
-
+ demonstrator = "right to be left alone" + demonstrator = "the right to refuse sharing private data" + relatedValue = "Intimacy" + opposingValue = "Transparency" + opposingValue = "Inclusiveness" + } + +} +``` Generally, you can cluster values in CML but you do not necessarily have to. @@ -144,85 +144,85 @@ Note that the following model snippets require stakeholder modelling as precondi The following example illustrates how you can assign the values ​​to the stakeholders who care about them. For each stakeholder you can define the `PRIORITY` this value has for the stakeholder, as well as the `IMPACT`. The `consequences` section allows you to model `good`, `bad`, and `neutral` consequences your system or feature has to the given value - from the perspective of the specific stakeholder: -
BoundedContext SameDayDelivery
-
-Stakeholders of SameDayDelivery {
-  StakeholderGroup Customers_and_Shoppers
-  StakeholderGroup Delivery_Staff_of_Suppliers
-}
-
-ValueRegister SD_Values for SameDayDelivery {  
-  Value Freedom {
-      Stakeholder Customers_and_Shoppers {
-        priority HIGH
-        impact MEDIUM
-        consequences
-          good "increased freedom"
-      }
-      Stakeholder Delivery_Staff_of_Suppliers {
-        priority HIGH
-        impact HIGH
-        consequences
-          bad "work-life-balance"
-      }
-    }
-}
-
-
+```cml +BoundedContext SameDayDelivery + +Stakeholders of SameDayDelivery { + StakeholderGroup Customers_and_Shoppers + StakeholderGroup Delivery_Staff_of_Suppliers +} + +ValueRegister SD_Values for SameDayDelivery { + Value Freedom { + Stakeholder Customers_and_Shoppers { + priority HIGH + impact MEDIUM + consequences + good "increased freedom" + } + Stakeholder Delivery_Staff_of_Suppliers { + priority HIGH + impact HIGH + consequences + bad "work-life-balance" + } + } +} +``` This is again possible on the level of a `Value`, but as well on a `ValueCluster`: -
BoundedContext SameDayDelivery
-
-Stakeholders of SameDayDelivery {
-  StakeholderGroup Customers_and_Shoppers
-  StakeholderGroup Delivery_Staff_of_Suppliers
-}
-
-ValueRegister SD_Values for SameDayDelivery {  
-  ValueCluster Freedom {
-      core AUTONOMY
-      Stakeholder Customers_and_Shoppers {
-        priority HIGH
-        impact MEDIUM
-        consequences
-          good "increased freedom"
-      }
-      Stakeholder Delivery_Staff_of_Suppliers {
-        priority HIGH
-        impact HIGH
-        consequences
-          bad "work-life-balance"
-      }
-    }
-}
-
-
+```cml +BoundedContext SameDayDelivery + +Stakeholders of SameDayDelivery { + StakeholderGroup Customers_and_Shoppers + StakeholderGroup Delivery_Staff_of_Suppliers +} + +ValueRegister SD_Values for SameDayDelivery { + ValueCluster Freedom { + core AUTONOMY + Stakeholder Customers_and_Shoppers { + priority HIGH + impact MEDIUM + consequences + good "increased freedom" + } + Stakeholder Delivery_Staff_of_Suppliers { + priority HIGH + impact HIGH + consequences + bad "work-life-balance" + } + } +} +``` ## Mitigation Actions In case your system has negative impact on values, you might want to model the mitigation actions you consider to implement to reduce harm. The following example shows how to model such mitigation actions in CML: -
BoundedContext SameDayDelivery
-
-Stakeholders of SameDayDelivery {
-  StakeholderGroup Drivers
-}
-
-ValueRegister SD_Values for SameDayDelivery {  
-  Value WorkLifeBalance {
-    demonstrator "Drivers value a healthy work-life-balance"
-    Stakeholder Drivers {
-      priority HIGH
-      impact HIGH
-      consequences
-        bad "SDD will harm work-life-balance of drivers"
-          action "hire more drivers" ACT
-    }
-  }
-}
-
-
+```cml +BoundedContext SameDayDelivery + +Stakeholders of SameDayDelivery { + StakeholderGroup Drivers +} + +ValueRegister SD_Values for SameDayDelivery { + Value WorkLifeBalance { + demonstrator "Drivers value a healthy work-life-balance" + Stakeholder Drivers { + priority HIGH + impact HIGH + consequences + bad "SDD will harm work-life-balance of drivers" + action "hire more drivers" ACT + } + } +} +``` The action types can be `ACT` (actively do something to reduce harm to values), `MONITOR` (just monitor the issue; maybe to gather more information), or a custom string. @@ -234,7 +234,7 @@ Once you have modelled your values and stakeholder priorities and impact, you ca ![Exemplary Value Impact Map - Generated out of a CML model with the PlantUML generator](./../../img/value-impact-map-sdd-sample.png) ## Stakeholders Export to CSV -In addition to the Value Impact Map visualization, you can export your modelled value register data as a CSV file. To do so, use the Freemarker temple [here](https://raw.githubusercontent.com/ContextMapper/context-mapper-dsl/master/org.contextmapper.dsl.ui/samples/freemarker/csv-files/value-registers.csv.ftl) together with our [Generic Generator (Freemarker Templating)](/docs/generic-freemarker-generator/). +In addition to the Value Impact Map visualization, you can export your modelled value register data as a CSV file. To do so, use the Freemarker temple [here](https://github.com/ContextMapper/context-mapper-dsl/blob/master/samples/freemarker/csv-files/value-registers.csv.ftl) together with our [Generic Generator (Freemarker Templating)](/docs/generic-freemarker-generator/). ## Additional ESE Formats @@ -244,41 +244,41 @@ The following additional (experimental) CML features allow users to apply [Story Note: These language features are experimental and currently not used by any generator. The modelled information can therefore not be visualized, except you use the Generic Generator (Templating with Freemarker) and process the data on your own.
-
Stakeholders {
-  Stakeholder Conference_Participant
-}
-
-ValueRegister Conference_Management_Sample {  
-  ValueEpic Data_Privacy {
-    As a Conference_Participant
-    I value "data privacy"
-    as demonstrated in 
-      realization of "confidentiality of sensitive personal information such as my passport number" 
-      reduction of "efficiency of operations for conference mansagement staff"
-  }
-
-  ValueWeigthing Data_Privacy {
-    In the context of the SOI,
-    stakeholder Conference_Participant values "data privacy" more than "efficiency from a registration management staff point of view"
-    expecting benefits such as "confidentiality of sensitive personal information"
-    running the risk of harms such as "higher conference fees and a slower registration process."
-  }
-}
-
-ValueRegister Same_Day_Delivery_Sample {
-  ValueNarrative Sample_Narrative {
-    When the SOI executes "the same say delivery epic (incl. split user stories that meet the INVEST criteria)",
-    stakeholders expect it to promote, protect or create "freedom and quality of life",
-    possibly degrading or prohibiting "work-life balance of suppliers and shopper privacy"
-    with the following externally observable and/or internally auditable behavior:
-
-    "Given: Shop is operational and suited suppliers and logistics firms are available. 
-    When: Same day delivery is promised during order acceptance and confirmation. 
-    Then: Order arrives at shipment address until 11:59pm on the same say."
-  }
-}
-
-
+```cml +Stakeholders { + Stakeholder Conference_Participant +} + +ValueRegister Conference_Management_Sample { + ValueEpic Data_Privacy { + As a Conference_Participant + I value "data privacy" + as demonstrated in + realization of "confidentiality of sensitive personal information such as my passport number" + reduction of "efficiency of operations for conference mansagement staff" + } + + ValueWeigthing Data_Privacy { + In the context of the SOI, + stakeholder Conference_Participant values "data privacy" more than "efficiency from a registration management staff point of view" + expecting benefits such as "confidentiality of sensitive personal information" + running the risk of harms such as "higher conference fees and a slower registration process." + } +} + +ValueRegister Same_Day_Delivery_Sample { + ValueNarrative Sample_Narrative { + When the SOI executes "the same say delivery epic (incl. split user stories that meet the INVEST criteria)", + stakeholders expect it to promote, protect or create "freedom and quality of life", + possibly degrading or prohibiting "work-life balance of suppliers and shopper privacy" + with the following externally observable and/or internally auditable behavior: + + "Given: Shop is operational and suited suppliers and logistics firms are available. + When: Same day delivery is promised during order acceptance and confirmation. + Then: Order arrives at shipment address until 11:59pm on the same say." + } +} +``` ## Transformations Note that we offer several transformations that might help modelling stakeholders and their values according to [VDAD (Value-Driven Analysis and Design)](https://ethical-se.github.io/value-driven-analysis-and-design) more efficiently. The transformations are documented on the following page: [Stakeholder and Value Modelling Transformations](/docs/stakeholder-and-value-modelling-transformations/). diff --git a/_docs/modeling-tools/rapid-ooad.md b/_docs/modeling-tools/rapid-ooad.md index b38e00f..623e3d2 100644 --- a/_docs/modeling-tools/rapid-ooad.md +++ b/_docs/modeling-tools/rapid-ooad.md @@ -39,33 +39,35 @@ brief [use cases](https://medium.com/@warren2lynch/all-you-need-to-know-about-us templates widely; however, CML supports the same [role-feature-reason](https://www.agilealliance.org/glossary/user-story-template/) structure for both of them at present. The following example illustrates the syntax for both notations: -
UserStory US1_Example {
-  As an "Insurance Employee" I want to "create" a "Customer" so that "I am able to manage customer data ..."
+```cml
+UserStory US1_Example {
+  As an "Insurance Employee" I want to "create" a "Customer" so that "I am able to manage customer data ..."
 }
 
-UseCase UC1_Example {
-  actor = "Insurance Employee"
-  interactions = "create" a "Customer"
-  benefit = "I am able to manage customer data ..."
+UseCase UC1_Example {
+  actor = "Insurance Employee"
+  interactions = "create" a "Customer"
+  benefit = "I am able to manage customer data ..."
 }
-
+``` It is also possible to specify multiple features or interactions in one use case or user story: -
UserStory US1_Example {
-  As an "Insurance Employee"
-    I want to "create" a "Customer"
-    I want to "update" a "Customer"
-    I want to "offer" a "Contract"
-  so that "I am able to manage the customers data and offer them insurance contracts."
+```cml
+UserStory US1_Example {
+  As an "Insurance Employee"
+    I want to "create" a "Customer"
+    I want to "update" a "Customer"
+    I want to "offer" a "Contract"
+  so that "I am able to manage the customers data and offer them insurance contracts."
 }
 
-UseCase UC1_Example {
-  actor = "Insurance Employee"
-  interactions = "create" a "Customer", "update" a "Customer", "offer" a "Contract"
-  benefit = "I am able to manage the customers data and offer them insurance contracts."
+UseCase UC1_Example {
+  actor = "Insurance Employee"
+  interactions = "create" a "Customer", "update" a "Customer", "offer" a "Contract"
+  benefit = "I am able to manage the customers data and offer them insurance contracts."
 }
-
+``` ## Step 2: Derive Subdomains (with Services and Entities) Once you have specified your user stories and/or use cases, you can select them in the CML editor and derive Subdomains that contain tentative Entities and Services automatically. @@ -82,19 +84,20 @@ You can update a Subdomain with new user stories or use cases iteratively withou If we use the example user story above and apply the transformation, we get the following Subdomain: -
Domain InsuranceDomain {
-  Subdomain CustomerDomain {
-    domainVisionStatement "Aims at promoting the following benefit for a Insurance Employee: I am able to manage the customers data and offer them insurance contracts."
-    Entity Customer
-    Entity Contract
-    Service US1_ExampleService {
+```cml
+Domain InsuranceDomain {
+  Subdomain CustomerDomain {
+    domainVisionStatement "Aims at promoting the following benefit for a Insurance Employee: I am able to manage the customers data and offer them insurance contracts."
+    Entity Customer
+    Entity Contract
+    Service US1_ExampleService {
       createCustomer;
       updateCustomer;
       offerContract;
     }
   }
 }
-
+``` The resulting Subdomains contain entities that are derived from the objects that the use case/user story works with as as well as services that represent the use case/user story; the interactions are transformed into draft operations. @@ -112,28 +115,29 @@ Note that the transformation always creates one Bounded Context for all selected Using the example Subdomain above, the transformation generates the following Bounded Context: -
BoundedContext NewContextFromSubdomains implements CustomerDomain {
-  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerDomain"
-  /* This Aggregate contains the entities and services of the 'CustomerDomain' subdomain.
-   * TODO: You can now refactor the Aggregate, for example by using the 'Split Aggregate by Entities' architectural refactoring.
-   * TODO: Add attributes and operations to the entities.
-   * TODO: Add operations to the services.
-   * Find examples and further instructions on our website: https://contextmapper.org/docs/rapid-ooad/ */
-  Aggregate CustomerDomainAggregate {
-    Service US1_ExampleService {
+```cml
+BoundedContext NewContextFromSubdomains implements CustomerDomain {
+  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerDomain"
+  /* This Aggregate contains the entities and services of the 'CustomerDomain' subdomain.
+   * TODO: You can now refactor the Aggregate, for example by using the 'Split Aggregate by Entities' architectural refactoring.
+   * TODO: Add attributes and operations to the entities.
+   * TODO: Add operations to the services.
+   * Find examples and further instructions on our website: https://contextmapper.org/docs/rapid-ooad/ */
+  Aggregate CustomerDomainAggregate {
+    Service US1_ExampleService {
       CreateCustomerOutput createCustomer (CreateCustomerInput input);
       UpdateCustomerOutput updateCustomer (UpdateCustomerInput input);
       OfferContractOutput offerContract (OfferContractInput input);
     }
-    Entity Customer {
+    Entity Customer {
       CustomerID customerId
     }
-    Entity Contract {
+    Entity Contract {
       ContractID contractId
     }
   }
 }
-
+``` The generated Bounded Context implements the previously selected Subdomains and initially contains an Aggregate per Subdomain that includes all entities and services of those Subdomains. The entities are enriched with identify attributes, and the services operations receive a generic return type and parameter. @@ -163,54 +167,55 @@ and frontend context shall integrate: Applying the transformation as shown above generates the following Bounded Contexts and Context Map relationship: -
ContextMap {
-  contains CustomerManagementFrontend
-  contains CustomerManagementBackend
+```cml
+ContextMap {
+  contains CustomerManagementFrontend
+  contains CustomerManagementBackend
 
-  CustomerManagementBackend [PL] -> [CF] CustomerManagementFrontend {
-    implementationTechnology "RESTful HTTP"
-    exposedAggregates CustomerManagementAggregateBackend
+  CustomerManagementBackend [PL] -> [CF] CustomerManagementFrontend {
+    implementationTechnology "RESTful HTTP"
+    exposedAggregates CustomerManagementAggregateBackend
   }
 }
 
-BoundedContext CustomerManagementBackend implements CustomerManagement {
-  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerManagement"
-  type SYSTEM
-  implementationTechnology "Sprint Boot"
-  Aggregate CustomerManagementAggregateBackend {
-    Service US1_ExampleService {
+BoundedContext CustomerManagementBackend implements CustomerManagement {
+  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerManagement"
+  type SYSTEM
+  implementationTechnology "Sprint Boot"
+  Aggregate CustomerManagementAggregateBackend {
+    Service US1_ExampleService {
       CreateCustomerOutput createCustomer (CreateCustomerInput input);
       UpdateCustomerOutput updateCustomer (UpdateCustomerInput input);
       OfferContractOutput offerContract (OfferContractInput input);
     }
-    Entity CustomerBackend {
+    Entity CustomerBackend {
       CustomerID customerId
     }
-    Entity ContractBackend {
+    Entity ContractBackend {
       ContractID contractId
     }
   }
 }
 
-BoundedContext CustomerManagementFrontend implements CustomerManagement {
-  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerManagement"
-  type SYSTEM
-  implementationTechnology "Angular"
-  Aggregate CustomerManagementAggregateViewModel {
-    Service US1_ExampleService {
+BoundedContext CustomerManagementFrontend implements CustomerManagement {
+  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerManagement"
+  type SYSTEM
+  implementationTechnology "Angular"
+  Aggregate CustomerManagementAggregateViewModel {
+    Service US1_ExampleService {
       CreateCustomerOutput createCustomer (CreateCustomerInput input);
       UpdateCustomerOutput updateCustomer (UpdateCustomerInput input);
       OfferContractOutput offerContract (OfferContractInput input);
     }
-    Entity CustomerViewModel {
+    Entity CustomerViewModel {
       CustomerID customerId
     }
-    Entity ContractViewModel {
+    Entity ContractViewModel {
       ContractID contractId
     }
   }
 }
-
+``` Now you already have an Upstream-Downstream relationship that exposes an Aggregate, which means you can generate a service contract with our [MDSL (Micro-)Service Contracts Generator](/docs/mdsl/). Of course you can use all the other [generators](/docs/generators/) as well. @@ -229,64 +234,65 @@ _Note:_ This transformation does not create two new Bounded Contexts. It uses th The transformation leads to the following result (with the configuration as shown above): -
ContextMap {
-  contains CustomerManagementFrontend
-  contains CustomerManagementDomainLogic
-  contains CustomerManagementDatabase
+```cml
+ContextMap {
+  contains CustomerManagementFrontend
+  contains CustomerManagementDomainLogic
+  contains CustomerManagementDatabase
 
-  CustomerManagementDomainLogic [PL] -> [CF] CustomerManagementFrontend {
-    implementationTechnology "RESTful HTTP"
-    exposedAggregates CustomerManagementAggregateBackend
+  CustomerManagementDomainLogic [PL] -> [CF] CustomerManagementFrontend {
+    implementationTechnology "RESTful HTTP"
+    exposedAggregates CustomerManagementAggregateBackend
   }
 
-  CustomerManagementDatabase [PL] -> [CF] CustomerManagementDomainLogic {
-    implementationTechnology "JDBC"
+  CustomerManagementDatabase [PL] -> [CF] CustomerManagementDomainLogic {
+    implementationTechnology "JDBC"
   }
 }
 
-BoundedContext CustomerManagementFrontend implements CustomerManagement {
-  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerManagement"
-  type SYSTEM
-  implementationTechnology "Angular"
-  Aggregate CustomerManagementAggregateViewModel {
-    Service US1_ExampleService {
+BoundedContext CustomerManagementFrontend implements CustomerManagement {
+  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerManagement"
+  type SYSTEM
+  implementationTechnology "Angular"
+  Aggregate CustomerManagementAggregateViewModel {
+    Service US1_ExampleService {
       CreateCustomerOutput createCustomer (CreateCustomerInput input);
       UpdateCustomerOutput updateCustomer (UpdateCustomerInput input);
       OfferContractOutput offerContract (OfferContractInput input);
     }
-    Entity CustomerViewModel {
+    Entity CustomerViewModel {
       CustomerID customerId
     }
-    Entity ContractViewModel {
+    Entity ContractViewModel {
       ContractID contractId
     }
   }
 }
 
-BoundedContext CustomerManagementDomainLogic implements CustomerManagement {
-  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerManagement"
-  type SYSTEM
-  implementationTechnology "Sprint Boot"
-  Aggregate CustomerManagementAggregateBackend {
-    Service US1_ExampleService {
+BoundedContext CustomerManagementDomainLogic implements CustomerManagement {
+  domainVisionStatement "This Bounded Context realizes the following subdomains: CustomerManagement"
+  type SYSTEM
+  implementationTechnology "Sprint Boot"
+  Aggregate CustomerManagementAggregateBackend {
+    Service US1_ExampleService {
       CreateCustomerOutput createCustomer (CreateCustomerInput input);
       UpdateCustomerOutput updateCustomer (UpdateCustomerInput input);
       OfferContractOutput offerContract (OfferContractInput input);
     }
-    Entity CustomerBackend {
+    Entity CustomerBackend {
       CustomerID customerId
     }
-    Entity ContractBackend {
+    Entity ContractBackend {
       ContractID contractId
     }
   }
 }
 
-BoundedContext CustomerManagementDatabase {
-  type SYSTEM
-  implementationTechnology "JDBC"
+BoundedContext CustomerManagementDatabase {
+  type SYSTEM
+  implementationTechnology "JDBC"
 }
-
+``` _Note:_ It is also possible to copy the domain model into the second subsystem (was not selected for the _CustomerManagementDatabase_ context above) with the corresponding checkbox on the dialog. diff --git a/_docs/modeling-tools/story-splitting.md b/_docs/modeling-tools/story-splitting.md index 7d9013d..2b070ed 100644 --- a/_docs/modeling-tools/story-splitting.md +++ b/_docs/modeling-tools/story-splitting.md @@ -15,10 +15,11 @@ As a first proof of concept for this feature we implemented the transformation " We illustrate the idea with the following user story written in CML: -
UserStory Account_Admin_Story {
-    As an "Admin" I want to "manage" an "Account" so that "can enable users to work with the system."
+```cml
+UserStory Account_Admin_Story {
+    As an "Admin" I want to "manage" an "Account" so that "can enable users to work with the system."
 }
-
+``` The Context Mapper editor provides a quick fix on the verb: @@ -38,18 +39,19 @@ Once you entered all desired verbs, you can press `ESC` and the transformation w The resulting CML model is: -
UserStory Account_Admin_Story split by Account_Admin_Story_Split {
-	As an "Admin" I want to "manage" an "Account" so that "can enable users to work with the system."
+```cml
+UserStory Account_Admin_Story split by Account_Admin_Story_Split {
+	As an "Admin" I want to "manage" an "Account" so that "can enable users to work with the system."
 }
 
-UserStory Account_Admin_Story_Split {
-	As an "Admin"
-	I want to "cancel" an "Account"
-	I want to "edit" an "Account"
-	I want to create an "Account"
-	so that "can enable users to work with the system."
+UserStory Account_Admin_Story_Split {
+	As an "Admin"
+	I want to "cancel" an "Account"
+	I want to "edit" an "Account"
+	I want to create an "Account"
+	so that "can enable users to work with the system."
 }
-
+``` With the _split by_ keyword we provide a back-reference so that you still know which story was split by which other story (and how the original story looked like). diff --git a/_docs/reverse-engineering/reverse-engineering.md b/_docs/reverse-engineering/reverse-engineering.md index 576526d..0065c6d 100644 --- a/_docs/reverse-engineering/reverse-engineering.md +++ b/_docs/reverse-engineering/reverse-engineering.md @@ -10,7 +10,7 @@ The discovery library supports the reverse engineering of bounded contexts and c Contributions to the discovery library are very welcome! If you implement a new discovery strategy for another programming language or framework, please contribute it to our project and create a Pull Request (PR) in our [GitHub repository](https://github.com/ContextMapper/context-map-discovery). ## Usage -The latest version of the discovery library is available through Maven Central: [![Maven Central](https://img.shields.io/maven-central/v/org.contextmapper/context-map-discovery.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22org.contextmapper%22%20AND%20a:%22context-map-discovery%22) +The latest version of the discovery library is available through Maven Central: [org.contextmapper:context-map-discovery on Maven Central](https://central.sonatype.com/artifact/org.contextmapper/context-map-discovery) You can find all information about the library, how to use it, and how to extend it with new discovery strategies in our Github repository: @@ -74,88 +74,89 @@ derives [Bounded Contexts](/docs/language-reference/bounded_context) from applic The code above creates the following context map for the application: -
ContextMap {
-  contains PolicyManagement
-  contains CustomerManagement
-  contains CustomerSelfService
-  contains CustomerCore
+```cml
+ContextMap {
+  contains PolicyManagement
+  contains CustomerManagement
+  contains CustomerSelfService
+  contains CustomerCore
 
-  CustomerCore -> PolicyManagement
+  CustomerCore -> PolicyManagement
 
-  CustomerCore -> CustomerManagement
+  CustomerCore -> CustomerManagement
 
-  PolicyManagement -> CustomerSelfService
+  PolicyManagement -> CustomerSelfService
 
-  CustomerCore -> CustomerSelfService
+  CustomerCore -> CustomerSelfService
 
 }
 
-BoundedContext PolicyManagement {
-  implementationTechnology "Spring Boot"
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.policymanagement.interfaces.RiskComputationService.
-  Aggregate riskfactor
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.policymanagement.interfaces.InsuranceQuoteRequestInformationHolder.
-  Aggregate PolicyManagement_insurance_quote_requests {
-    /* removed to save space here */
+BoundedContext PolicyManagement {
+  implementationTechnology "Spring Boot"
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.policymanagement.interfaces.RiskComputationService.
+  Aggregate riskfactor
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.policymanagement.interfaces.InsuranceQuoteRequestInformationHolder.
+  Aggregate PolicyManagement_insurance_quote_requests {
+    /* removed to save space here */
   }
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.policymanagement.interfaces.PolicyInformationHolder.
-  Aggregate policies {
-    /* removed to save space here */
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.policymanagement.interfaces.PolicyInformationHolder.
+  Aggregate policies {
+    /* removed to save space here */
   }
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.policymanagement.interfaces.CustomerInformationHolder.
-  Aggregate PolicyManagement_customers {
-    /* removed to save space here */
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.policymanagement.interfaces.CustomerInformationHolder.
+  Aggregate PolicyManagement_customers {
+    /* removed to save space here */
   }
 }
 
-BoundedContext CustomerManagement {
-  implementationTechnology "Spring Boot"
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customermanagement.interfaces.CustomerInformationHolder.
-  Aggregate CustomerManagement_customers {
-    /* removed to save space here */
+BoundedContext CustomerManagement {
+  implementationTechnology "Spring Boot"
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customermanagement.interfaces.CustomerInformationHolder.
+  Aggregate CustomerManagement_customers {
+    /* removed to save space here */
   }
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customermanagement.interfaces.InteractionLogInformationHolder.
-  Aggregate interaction_logs {
-    /* removed to save space here */
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customermanagement.interfaces.InteractionLogInformationHolder.
+  Aggregate interaction_logs {
+    /* removed to save space here */
   }
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customermanagement.interfaces.NotificationInformationHolder.
-  Aggregate notifications
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customermanagement.interfaces.NotificationInformationHolder.
+  Aggregate notifications
 }
 
-BoundedContext CustomerSelfService {
-  implementationTechnology "Spring Boot"
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.AuthenticationController.
-  Aggregate auth
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.CityStaticDataHolder.
-  Aggregate cities {
-    /* removed to save space here */
+BoundedContext CustomerSelfService {
+  implementationTechnology "Spring Boot"
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.AuthenticationController.
+  Aggregate auth
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.CityStaticDataHolder.
+  Aggregate cities {
+    /* removed to save space here */
   }
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.InsuranceQuoteRequestInformationHolder.
-  Aggregate insurance_quote_requests {
-    /* removed to save space here */
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.InsuranceQuoteRequestInformationHolder.
+  Aggregate insurance_quote_requests {
+    /* removed to save space here */
   }
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.CustomerInformationHolder.
-  Aggregate customers {
-    /* removed to save space here */
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.CustomerInformationHolder.
+  Aggregate customers {
+    /* removed to save space here */
   }
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.UserInformationHolder.
-  Aggregate user {
-    /* removed to save space here */
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customerselfservice.interfaces.UserInformationHolder.
+  Aggregate user {
+    /* removed to save space here */
   }
 }
 
-BoundedContext CustomerCore {
-  implementationTechnology "Spring Boot"
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customercore.interfaces.CityStaticDataHolder.
-  Aggregate CustomerCore_cities {
-    /* removed to save space here */
+BoundedContext CustomerCore {
+  implementationTechnology "Spring Boot"
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customercore.interfaces.CityStaticDataHolder.
+  Aggregate CustomerCore_cities {
+    /* removed to save space here */
   }
-  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customercore.interfaces.CustomerInformationHolder.
-  Aggregate CustomerCore_customers {
-    /* removed to save space here */
+  // This Aggregate has been created on the basis of the Spring REST controller com.lakesidemutual.customercore.interfaces.CustomerInformationHolder.
+  Aggregate CustomerCore_customers {
+    /* removed to save space here */
   }
 }
-
+``` Note that we removed the entities in the CML model above in order to save space here. The full example and the project source code can be found [here](https://github.com/ContextMapper/context-map-discovery/tree/master/Examples/LakesideMutual). diff --git a/_docs/standalone-usage.md b/_docs/standalone-usage.md index 408588e..d3c048f 100644 --- a/_docs/standalone-usage.md +++ b/_docs/standalone-usage.md @@ -23,7 +23,7 @@ implementation 'org.contextmapper:context-mapper-dsl:{our-latest-version}' ``` -The latest release can be found here: [![Maven Central](https://img.shields.io/maven-central/v/org.contextmapper/context-mapper-dsl.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22org.contextmapper%22%20AND%20a:%22context-mapper-dsl%22) +The latest release can be found here: [org.contextmapper:context-mapper-dsl on Maven Central](https://central.sonatype.com/artifact/org.contextmapper/context-mapper-dsl) ## Example Project If you want to use Context Mapper as library within your application, have a look at our standalone example project: diff --git a/_docs/tutorials/architecture-validation-with-archunit.md b/_docs/tutorials/architecture-validation-with-archunit.md index 9769843..5a43bee 100644 --- a/_docs/tutorials/architecture-validation-with-archunit.md +++ b/_docs/tutorials/architecture-validation-with-archunit.md @@ -22,59 +22,60 @@ In this tutorial we assume that you are aware of the [Context Mapper DSL (CML) l We will illustrate our validation approach with [ArchUnit](https://www.archunit.org/) with a small, exemplary domain model: -
BoundedContext eCommerceContext {
+```cml
+BoundedContext eCommerceContext {
 
-  Aggregate Product {
-    Entity Product {
-      aggregateRoot
+  Aggregate Product {
+    Entity Product {
+      aggregateRoot
 
-      - ProductId id;
-      String name;
-      String description;
-      double price;
+      - ProductId id;
+      String name;
+      String description;
+      double price;
     }
 
-    ValueObject ProductId {
-      String value;
+    ValueObject ProductId {
+      String value;
     }
   }
 
-  Aggregate Order {
-    Entity Order {
-      aggregateRoot
+  Aggregate Order {
+    Entity Order {
+      aggregateRoot
 
-      - OrderId id;
-      - UserId purchaserId;
-      - List<OrderItem> items;
-      DateTime ordered;
+      - OrderId id;
+      - UserId purchaserId;
+      - List items;
+      DateTime ordered;
     }
 
-    ValueObject OrderItem {
-      - ProductId productId;
-      int amount;
+    ValueObject OrderItem {
+      - ProductId productId;
+      int amount;
     }
 
-    ValueObject OrderId {
-      String value;
+    ValueObject OrderId {
+      String value;
     }
   }
 
-  Aggregate User {
-    Entity User {
-      aggregateRoot
+  Aggregate User {
+    Entity User {
+      aggregateRoot
 
-      - UserId id;
-      String name;
-      String ^email;
+      - UserId id;
+      String name;
+      String ^email;
     }
 
-    ValueObject UserId {
-      String value;
+    ValueObject UserId {
+      String value;
     }
   }
 
 }
-
+``` With our [PlantUML generator](/docs/plant-uml/) we can visualize the model as follows: diff --git a/_docs/tutorials/event-sourcing-and-cqrs-modeling.md b/_docs/tutorials/event-sourcing-and-cqrs-modeling.md index 7080671..b1831b3 100644 --- a/_docs/tutorials/event-sourcing-and-cqrs-modeling.md +++ b/_docs/tutorials/event-sourcing-and-cqrs-modeling.md @@ -34,7 +34,7 @@ suggests that the scope of domain events should always be based on Aggregates. T The following example illustrates how you can model domain events within your Aggregate: -```text +```cml abstract DomainEvent AbstractDomainEvent { Date timestamp } @@ -57,7 +57,7 @@ ValueObject AddressDto { You can also reference your events in services, repositories, or any other tactic DDD objects: -```text +```cml Service AddressService { @AddressUpdatedEvent updateAddress(@AddressDto address); } @@ -73,7 +73,7 @@ this architectural pattern by #### Step 1: Separating Queries and Commands Here is an example of a conventional service interface that exposes both create, read, update, delete, and search methods/operations: -```text +```cml ValueObject CustomerDTO { String customerId CustomerProfileDto customerProfile @@ -91,7 +91,7 @@ Service CustomerService { You can CQRS-ify the above interface by splitting it into two service interfaces: -```text +```cml Service CustomerCommandService { @CustomerId createCustomer(@CustomerDTO customer); void updateCustomer(@CustomerDTO customer); @@ -107,7 +107,7 @@ Service CustomerQueryService { Additionally, Sculptor introduces so-called *command events* to support CQRS explicitly (described [here](https://sculptor.github.io/documentation/event-driven-tutorial#commandevent)). In comparison to a domain event which describes something that has happened, a command event is something that the system is asked to perform. The following CML/Sculptor snippet illustrates an example how to model command events: -```text +```cml CommandEvent RecordAddressChange { -AddressDto newAddress Date changeDate @@ -117,7 +117,7 @@ CommandEvent RecordAddressChange { #### Step 2: Separating Read and Command Models In a second step you may want to define completely different models for read and command access. At present, the Context Mapper DSL does not have any specific language construct for read models; we suggest that you use the Michael's Aggregate rule from above to specify read models. The following example illustrates how you could model your Aggregate (command model) and your read model: -```text +```cml Aggregate CustomerAggregate { ValueObject CustomerId { UUID uniqueCustomerId diff --git a/_docs/tutorials/event-storming.md b/_docs/tutorials/event-storming.md index 53a1a18..a781bff 100644 --- a/_docs/tutorials/event-storming.md +++ b/_docs/tutorials/event-storming.md @@ -61,7 +61,7 @@ The tactic DDD syntax of CML is based on the [Sculptor DSL](https://sculptor.git Hence, you can model _DomainEvents_ within your Aggregates. The following examples illustrate how we modeled the domain events from our Event Storming for Lakeside Mutual: -```text +```cml abstract DomainEvent AbstractClaimEvent { Date timestamp - Claim claim @@ -83,7 +83,7 @@ sourcing and CQRS based systems can be modeled in Context Mapper. Domain events often result from a user action or _command_ execution. Commands in CML can either be modeled as methods in services or as _CommandEvent_'s (or both). The following examples illustrate how you can model commands in CML: -```text +```cml abstract CommandEvent AbstractClaimCommand { - Claim claim } @@ -119,7 +119,7 @@ For example: If the `CheckClaimDocumentation` command is performed, an event `Cl Policies can be modeled in the same way, and optionally their if-then rule character can be modeled explicitly. For example: -```text +```cml abstract DomainEvent AbstractPolicy DomainEvent CustomerNotificationPolicy // triggers CustomerNotified event @@ -130,7 +130,7 @@ Aggregates are supported by CML and can be modeled within Bounded Contexts. The The following example illustrates the `Notification` Aggregate derived from our Event Storming example above: -```text +```cml Aggregate Notification { Entity Notification { aggregateRoot @@ -161,7 +161,7 @@ the project straight away. The Lakeside Mutual Event Storming output above contains two issues ([the two red cards in the Event Storming above](#example-lakeside-mutual)) for which we created the following comment in our CML model: -```text +```cml /** * The 'Claims Management' context below is a result of our Event Storming for the new * claim processing feature. @@ -178,7 +178,7 @@ BoundedContext ClaimsManagement { At present, there is no concept of a user role in the Context Mapper DSL; however, we used [Sculptor](https://sculptor.github.io/)'s `doc` comment which can be added to all domain objects. Thereby we declare the user roles on our commands: -```text +```cml "role: Administrator in charge" CommandEvent CheckClaimDocumentation extends @AbstractClaimCommand @@ -198,7 +198,7 @@ CommandEvent RejectClaim extends @AbstractClaimCommand In our Event Storming for claims processing at Lakeside Mutual we did not work with read models; Context Mapper does not support read models explicitly yet. However, it is of course possible that you define your read model simply by using separate Aggregates or Entities. For example: -```text +```cml Aggregate ClaimReadModel { Entity ClaimReadModel { String claimIdentifier @@ -215,7 +215,7 @@ for the Lakeside Mutual claim processing has been modeled. Just like Bounded Contexts, Subdomains are root objects and first class citizens in CML. The Subdomain syntax is documented [here](/docs/subdomain/). The following CML example illustrates how you can define Subdomains and how Bounded Contexts can implement those Subdomains: -```text +```cml Domain InsuranceDomain { Subdomain ClaimProcessing { type CORE_DOMAIN @@ -243,7 +243,7 @@ illustrated graphic above proceeds from left to right. Context Mapper does not provide any support for modeling this event flow (time) explicitly yet. For this reason we simply worked with comments to indicate which command is triggered after an event has been emitted: -```text +```cml "role: Administrator in charge" CommandEvent CheckClaimDocumentation extends @AbstractClaimCommand diff --git a/_docs/tutorials/jhipster-microservice-generation.md b/_docs/tutorials/jhipster-microservice-generation.md index 4ebc392..1a32879 100644 --- a/_docs/tutorials/jhipster-microservice-generation.md +++ b/_docs/tutorials/jhipster-microservice-generation.md @@ -29,81 +29,83 @@ Please note that the current JDL template only filters/ignores Bounded Contexts (FEATURES, APPLICATIONS, and SYSTEMS) are mapped to a corresponding microservice. Our example Context Map, shown in the following CML snippet, contains several Bounded Contexts of the type _SYSTEM_. The generator creates one microservice per Bounded Context. -
ContextMap InsuranceContextMap {
-  type = SYSTEM_LANDSCAPE
-  state = TO_BE
+```cml
+ContextMap InsuranceContextMap {
+  type = SYSTEM_LANDSCAPE
+  state = TO_BE
 
-  contains CustomerManagement, CustomerSelfService, Printing
-  contains PolicyManagement, RiskManagement, DebtCollection
+  contains CustomerManagement, CustomerSelfService, Printing
+  contains PolicyManagement, RiskManagement, DebtCollection
 
-  CustomerSelfService [D,C]<-[U,S] CustomerManagement {
-    exposedAggregates = Customers
+  CustomerSelfService [D,C]<-[U,S] CustomerManagement {
+    exposedAggregates = Customers
   }
 
-  CustomerManagement [D,ACL]<-[U,OHS,PL] Printing {
-    implementationTechnology = "SOAP"
-    downstreamRights = INFLUENCER
-    exposedAggregates = Printing
+  CustomerManagement [D,ACL]<-[U,OHS,PL] Printing {
+    implementationTechnology = "SOAP"
+    downstreamRights = INFLUENCER
+    exposedAggregates = Printing
   }
 
-  Printing [U,OHS,PL]->[D,ACL] PolicyManagement {
-    implementationTechnology = "SOAP"
-    exposedAggregates = Printing
+  Printing [U,OHS,PL]->[D,ACL] PolicyManagement {
+    implementationTechnology = "SOAP"
+    exposedAggregates = Printing
   }
 
-  RiskManagement [P]<->[P] PolicyManagement {
-    implementationTechnology = "RabbitMQ"
+  RiskManagement [P]<->[P] PolicyManagement {
+    implementationTechnology = "RabbitMQ"
   }
 
-  PolicyManagement [D,CF]<-[U,OHS,PL] CustomerManagement {
-    implementationTechnology = "RESTfulHTTP"
-    exposedAggregates = Customers
+  PolicyManagement [D,CF]<-[U,OHS,PL] CustomerManagement {
+    implementationTechnology = "RESTfulHTTP"
+    exposedAggregates = Customers
   }
 
-  DebtCollection [D,ACL]<-[U,OHS,PL] Printing {
-    implementationTechnology = "SOAP"
-    exposedAggregates = Printing
+  DebtCollection [D,ACL]<-[U,OHS,PL] Printing {
+    implementationTechnology = "SOAP"
+    exposedAggregates = Printing
   }
 
-  PolicyManagement [SK]<->[SK] DebtCollection {
-    implementationTechnology = "Shared Java Library, Communication over RESTful HTTP"
+  PolicyManagement [SK]<->[SK] DebtCollection {
+    implementationTechnology = "Shared Java Library, Communication over RESTful HTTP"
   }
 }
-
+``` Each Bounded Context of the model contains Aggregates with Entities and Services. The following CML snippet (CustomerManagement) illustrates an example: -
BoundedContext CustomerManagement implements CustomerManagementDomain {
-  type = SYSTEM
-  domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
-  implementationTechnology = "Java, JEE Application"
-  responsibilities = "Customers, Addresses"
+```cml
+BoundedContext CustomerManagement implements CustomerManagementDomain {
+  type = SYSTEM
+  domainVisionStatement = "The customer management context is responsible for managing all the data of the insurance companies customers."
+  implementationTechnology = "Java, JEE Application"
+  responsibilities = "Customers, Addresses"
 
-  Aggregate Customers {
-    Entity Customer {
-      aggregateRoot
+  Aggregate Customers {
+    Entity Customer {
+      aggregateRoot
 
-      - SocialInsuranceNumber sin
-      String firstname
-      String lastname
-      - List<Address> addresses
+      - SocialInsuranceNumber sin
+      String firstname
+      String lastname
+      - List
addresses - def AddressId createAddress(@Address address); - def boolean changeCustomer(String firstname, String lastname); + def AddressId createAddress(@Address address); + def boolean changeCustomer(String firstname, String lastname); } - Entity Address { - String street - int postalCode - String city + Entity Address { + String street + int postalCode + String city } - ValueObject SocialInsuranceNumber { - String sin key + ValueObject SocialInsuranceNumber { + String sin key } } } -
+``` All other Bounded Context definitions and the complete model can be found [here](https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/microservice-generation/JDL-example), as already mentioned. @@ -117,7 +119,7 @@ the corresponding Entities in each Bounded Context manually (for now). ## Generate JDL with Context Mapper Once you modeled your Bounded Contexts with the Entities, you can generate a JDL file using our [generic generator](/docs/generic-freemarker-generator/). -The Freemarker template can be downloaded [here](https://github.com/ContextMapper/context-mapper-dsl/blob/master/org.contextmapper.dsl.ui/samples/freemarker/jhipster/JDL.ftl). In Eclipse you can also import the template by [creating the example templates project](/docs/generic-freemarker-generator/#user-guide) (VS Code users please download the template manually). +The Freemarker template can be downloaded [here](https://github.com/ContextMapper/context-mapper-dsl/blob/master/samples/freemarker/jhipster/JDL.ftl). In Eclipse you can also import the template by [creating the example templates project](/docs/generic-freemarker-generator/#user-guide) (VS Code users please download the template manually). You can the call the generator through the context menu of the CML editor (a more detailed documentation how to use our generators can be found [here](/docs/generators/#using-the-generators)). The Eclipse plugin or VS Code extension will ask you to choose the Freemarker template. Select the JDL.ftl file. Context Mapper will also ask you to choose a name for the output file. In this case type a file name ending with *.jdl. diff --git a/_docs/tutorials/systematic-service-decomposition.md b/_docs/tutorials/systematic-service-decomposition.md index d56059f..b84a2c8 100644 --- a/_docs/tutorials/systematic-service-decomposition.md +++ b/_docs/tutorials/systematic-service-decomposition.md @@ -19,55 +19,56 @@ We use the [DDD sample application (Cargo Tracking)](https://github.com/citerus/ We modeled the domain inside one single Bounded Context. The context contains four Aggregates with its Entities and Value Objects: -
BoundedContext CargoTracking {
-  Aggregate Cargo {
-    owner CargoPlaner
-
-    Entity Cargo {
-      aggregateRoot
-      - TrackingId trackingId
-      - Location origin
-      - RouteSpecification routeSpecification
-      - Itinerary itinerary
-      - Delivery delivery
+```cml
+BoundedContext CargoTracking {
+  Aggregate Cargo {
+    owner CargoPlaner
+
+    Entity Cargo {
+      aggregateRoot
+      - TrackingId trackingId
+      - Location origin
+      - RouteSpecification routeSpecification
+      - Itinerary itinerary
+      - Delivery delivery
     }
-    /* shortened Aggregate here */
+    /* shortened Aggregate here */
   }
-  Aggregate Location {
-    owner Administrators
+  Aggregate Location {
+    owner Administrators
 
-    Entity Location {
-      aggregateRoot
-      - UnLocode unLocode
-      String name
+    Entity Location {
+      aggregateRoot
+      - UnLocode unLocode
+      String name
     }
-    /* shortened Aggregate here */
+    /* shortened Aggregate here */
   }
-  Aggregate Handling {
-    owner CargoTracker
-
-    DomainEvent HandlingEvent {
-      - HandlingEventType handlingEventType
-      - Voyage voyage
-      - Location location
-      Date completionTime
-      Date registrationTime
-      - Cargo cargo
+  Aggregate Handling {
+    owner CargoTracker
+
+    DomainEvent HandlingEvent {
+      - HandlingEventType handlingEventType
+      - Voyage voyage
+      - Location location
+      Date completionTime
+      Date registrationTime
+      - Cargo cargo
     }
-    /* shortened Aggregate here */
+    /* shortened Aggregate here */
   }
-  Aggregate Voyage {
-    owner VoyageManager
+  Aggregate Voyage {
+    owner VoyageManager
 
-    Entity Voyage {
-      aggregateRoot
-      - VoyageNumber voyageNumber
-      - Schedule schedule
+    Entity Voyage {
+      aggregateRoot
+      - VoyageNumber voyageNumber
+      - Schedule schedule
     }
-    /* shortened Aggregate here */
+    /* shortened Aggregate here */
   }
 }
-
+``` The CML code above just gives you an impression how the model looks like but is shortened a lot. Find the complete model [here](https://github.com/ContextMapper/context-mapper-examples/blob/master/src/main/cml/ddd-service-cutting-sample/DDD-Sample.cml). The following PlantUML diagram (generated with Context Mapper) illustrates the domain model graphically: @@ -78,38 +79,39 @@ With a Bounded Context definition as the one above you are already able to gener On the [User Requirements](/docs/user-requirements/) page of our language reference you can find out how use cases or user stories are modeled in CML. For this tutorial based on the DDD sample application we modeled the use cases provided by the [Service Cutter sample files](https://github.com/ServiceCutter/ServiceCutter/tree/master/Samples): -
UseCase ViewTracking {
-  interactions
-    read "Cargo" with its "trackindId",
-    read "HandlingEvent" with its "handlingEventType", "location", "completionTime",
-    read "Delivery" with its "transportStatus", "estimatedArrivalTime", "misdirected", 
-    read "Voyage" with its "voyageNumber",
-    read "RouteSpecification" with its "destination"
+```cml
+UseCase ViewTracking {
+  interactions
+    read "Cargo" with its "trackindId",
+    read "HandlingEvent" with its "handlingEventType", "location", "completionTime",
+    read "Delivery" with its "transportStatus", "estimatedArrivalTime", "misdirected",
+    read "Voyage" with its "voyageNumber",
+    read "RouteSpecification" with its "destination"
 }
 
-UseCase ViewCargos {
-  interactions
-    read "Cargo" with its "trackingId",
-    read "RouteSpecification" with its "destination", "arrivalDeadline",
-    read "Delivery" with its "routingStatus"
+UseCase ViewCargos {
+  interactions
+    read "Cargo" with its "trackingId",
+    read "RouteSpecification" with its "destination", "arrivalDeadline",
+    read "Delivery" with its "routingStatus"
 }
 
-UseCase BookCargo {
-  interactions
-    read "Location" with its "unLocode",
-    update "Cargo" with its "trackingId",
-    update "RouteSpecification" with its "origin", "arrivalDeadline", "destination"
+UseCase BookCargo {
+  interactions
+    read "Location" with its "unLocode",
+    update "Cargo" with its "trackingId",
+    update "RouteSpecification" with its "origin", "arrivalDeadline", "destination"
 }
 
-UseCase ChangeCargoDestination {
-  interactions
-    read "Cargo" with its "trackingId",
-    read "RouteSpecification" with its "destination",
-    update "RouteSpecification" with its "destination"
+UseCase ChangeCargoDestination {
+  interactions
+    read "Cargo" with its "trackingId",
+    read "RouteSpecification" with its "destination",
+    update "RouteSpecification" with its "destination"
 }
 
-/* we shortened this listing to save space (find all use cases in the original CML file) */
-
+/* we shortened this listing to save space (find all use cases in the original CML file) */ +``` Note that we only modeled the Entities with its _read_ and _written_ attributes (nanoentities) here. The CML syntax allows you to add [more details to use cases and/or user stories](/docs/user-requirements/), but the information above are absolutely necessary for Context Mapper to use the cases/stories as user representations in Service Cutter. @@ -120,35 +122,36 @@ A Bounded Contexts is not necessarily a system or component. A team can constitu This might not make sense for the DDD sample application, as the domain model is not that big. However, we assigned the Aggregates to four different teams to illustrate how this is done: -
BoundedContext CargoTracking {
-  Aggregate Cargo {
-    owner CargoPlaner
+```cml
+BoundedContext CargoTracking {
+  Aggregate Cargo {
+    owner CargoPlaner
 
-    /* removed content here to save space */
+    /* removed content here to save space */
   }
-  Aggregate Location {
-    owner Administrators
+  Aggregate Location {
+    owner Administrators
 
-    /* removed content here to save space */
+    /* removed content here to save space */
   }
-  Aggregate Handling {
-    owner CargoTracker
+  Aggregate Handling {
+    owner CargoTracker
 
-    /* removed content here to save space */ 
+    /* removed content here to save space */
   }
-  Aggregate Voyage {
-    owner VoyageManager
+  Aggregate Voyage {
+    owner VoyageManager
 
-    /* removed content here to save space */
+    /* removed content here to save space */
   }
 }
 
-/* team definitions: */
-BoundedContext CargoPlaner { type TEAM }
-BoundedContext CargoTracker { type TEAM }
-BoundedContext VoyageManager { type TEAM }
-BoundedContext Administrators { type TEAM }
-
+/* team definitions: */ +BoundedContext CargoPlaner { type TEAM } +BoundedContext CargoTracker { type TEAM } +BoundedContext VoyageManager { type TEAM } +BoundedContext Administrators { type TEAM } +``` The CML team assignments will be mapped to the Service Cutter's [_Shared Owner Group_ definition](https://github.com/ServiceCutter/ServiceCutter/wiki/Shared-owner-groups). diff --git a/_docs/value-driven-analysis-and-design/vdad-support.md b/_docs/value-driven-analysis-and-design/vdad-support.md index fb324a9..83691e6 100644 --- a/_docs/value-driven-analysis-and-design/vdad-support.md +++ b/_docs/value-driven-analysis-and-design/vdad-support.md @@ -26,7 +26,7 @@ By using the language features mentioned above, you can automatically generate: * CSV files with the stakeholder data by using our [Generic Generator (Freemarker Templating)](/docs/generic-freemarker-generator/) * CSV files with the value register data by using our [Generic Generator (Freemarker Templating)](/docs/generic-freemarker-generator/) -**Note**: The freemarker templates can be found [here](https://github.com/ContextMapper/context-mapper-dsl/tree/master/org.contextmapper.dsl.ui/samples/freemarker/csv-files). +**Note**: The freemarker templates can be found [here](https://github.com/ContextMapper/context-mapper-dsl/tree/master/samples/freemarker/csv-files). ## Background and Further Information diff --git a/_includes/docs_nav.html b/_includes/docs_nav.html index fa438ae..b0d614f 100644 --- a/_includes/docs_nav.html +++ b/_includes/docs_nav.html @@ -1,22 +1,19 @@ -
-{% for section in site.data.docs %} -
- -
-
- {% for item in section.docs %} - {% assign item_url = item | prepend:"/docs/" | append:"/" %} - {% assign p = site.docs | where:"url", item_url | first %} - {{ p.title }} - {% endfor %} -
-
-
-{% endfor %} -
+ diff --git a/_includes/footer.html b/_includes/footer.html index 2093c0a..4f2b791 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -1,10 +1,15 @@ -