Fundamentals 22 min read

Mastering DDD as Code: Using ContextMapper DSL to Standardize Architecture

This article explains how to treat Domain‑Driven Design as code by leveraging ContextMapper's DSL to model strategic and tactical aspects, define subdomains, bounded contexts, context maps, and generate consistent documentation and code artifacts for microservice architectures.

Alibaba Cloud Developer
Alibaba Cloud Developer
Alibaba Cloud Developer
Mastering DDD as Code: Using ContextMapper DSL to Standardize Architecture

Introduction

Domain‑Driven Design (DDD) is often abstract and interpreted differently by developers; the article proposes the concept of “DDD as Code” using a DSL to express DDD ideas uniformly and reduce ambiguity.

Strategic vs. Tactical Design

Strategic DDD focuses on bounded contexts, context maps, and relationships such as Partnership, Shared Kernel, Customer‑Supplier, etc., while tactical DDD deals with entities, value objects, aggregates, services, repositories, and factories.

ContextMapper Overview

ContextMapper is an open‑source project that provides DSL support for strategic DDD, context mapping, bounded‑context modeling, and service decomposition. It enables developers to describe domains, subdomains, and their relationships in code.

Project Background

The example follows a member‑system architecture consisting of three applications (member center API, registration/login, and profile management). The author, acting as an architect, uses ContextMapper to model the system.

Subdomain Modeling

Three subdomain types are defined: Generic (e.g., logging, metrics), Supporting (customized internal services), and Core (business‑critical logic). The article shows how to classify subdomains and illustrates the relationships with diagrams.

ContextMapper DSL Examples

<span>Domain User {</span>
    <span>domainVisionStatement = "User domain to manage account, tags, profiles and payment profile."</span>
    <span>Subdomain AccountDomain {</span>
       <span>type = CORE_DOMAIN</span>
       <span>domainVisionStatement = "Account domain to save sensitive data and authentication"</span>
    <span>}</span>
    <span>Subdomain UserTagDomain {</span>
       <span>type = GENERIC_SUBDOMAIN</span>
       <span>domainVisionStatement = "UserTag domain manage user's KV and Boolean tag"</span>
    <span>}</span>
    <span>Subdomain PaymentProfileDomain {</span>
        <span>type = CORE_DOMAIN</span>
        <span>domainVisionStatement = "User payment profile domain to manage credit/debit card, Alipay payment information"</span>
    <span>}</span>
    <span>Subdomain SnsProfileDomain {</span>
        <span>type = CORE_DOMAIN</span>
        <span>domainVisionStatement = "User Sns profile domain to manage user Sns profile for Weibo, Wechat, Facebook and Twitter."</span>
    <span>}</span>
    <span>Subdomain ProfilesDomain {</span>
        <span>type = CORE_DOMAIN</span>
        <span>domainVisionStatement = "User profiles domain to manage user basic profile, interest profile etc"</span>
    <span>}</span>
<span>}</span>
<span>ContextMap UserContextMap {</span>
   <span>type = SYSTEM_LANDSCAPE</span>
   <span>state = TO_BE</span>
   <span>contains AccountContext</span>
   <span>contains UserTagContext</span>
   <span>contains PaymentProfileContext</span>
   <span>contains SnsProfileContext</span>
   <span>contains ProfilesContext</span>
   <span>contains UserLoginContext</span>
   <span>contains UserRegistrationContext</span>
   <span>UserLoginContext [D]<-[U] AccountContext {</span>
        <span>implementationTechnology = "RSocket"</span>
        <span>exposedAggregates = AccountFacadeAggregate</span>
   <span>}</span>
   <span>ProfilesContext [D]<-[U] UserTagContext {</span>
        <span>implementationTechnology = "RSocket"</span>
        <span>exposedAggregates = UserTags</span>
   <span>}</span>
   <span>UserRegistrationContext [D,C]<-[U,S] UserTagContext {</span>
        <span>implementationTechnology = "RSocket"</span>
        <span>exposedAggregates = UserTags</span>
   <span>}</span>
   <span>UserRegistrationContext [D,C]<-[U,S] SnsProfileContext {</span>
        <span>implementationTechnology = "RSocket"</span>
   <span>}</span>
<span>}</span>
<span>BoundedContext AccountContext implements AccountDomain {</span>
    <span>type = APPLICATION</span>
    <span>domainVisionStatement = "Managing account basic data"</span>
    <span>implementationTechnology = "Kotlin, Spring Boot, MySQL, Memcached"</span>
    <span>responsibilities = "Account", "Authentication"</span>
    <span>Aggregate AccountFacadeAggregate {</span>
       <span>ValueObject AccountDTO {</span>
          <span>long id</span>
          <span>String nick</span>
          <span>String name</span>
          <span>int status</span>
          <span>Date createdAt</span>
          <span>def toJson();</span>
       <span>}</span>
       <span>Service AccountFacade {</span>
          <span>@AccountDTO findById(Integer id);</span>
       <span>}</span>
    <span>}</span>
    <span>Aggregate Accounts {</span>
         <span>Entity Account {</span>
            <span>long id</span>
            <span>String nick</span>
            <span>String mobile</span>
            <span>String ^email</span>
            <span>String name</span>
            <span>String salt</span>
            <span>String passwd</span>
            <span>int status</span>
            <span>Date createdAt</span>
            <span>Date updatedAt</span>
         <span>}</span>
    <span>}</span>
<span>}</span>

User Story and Use Case DSL

<span>UserStory Customers {</span>
    <span>As a "Login User"</span>
    I want to update a "Avatar"
    I want to update an "Address"
    so that "I can manage the personal data."
<span>}</span>
<span>UseCase UC1_Example {</span>
  <span>actor = "Insurance Employee"</span>
  interactions = create a "Customer", update a "Customer", "offer" a "Contract"
  benefit = "I am able to manage the customers data and offer them insurance contracts."
<span>}</span>

Benefits of Using ContextMapper

Standardized architecture description reduces ambiguity.

DSL can be validated by IDEs, preventing syntactic errors.

Generators can produce code, context‑map diagrams, PlantUML, JHipster Domain Language, etc.

Supports integration with microservice contracts and reactive messaging.

Real‑World DDD Process

Before modeling, teams should perform domain discovery (EventStorming, Bounded Context Canvas) to gather requirements, then translate findings into DSL, user stories, and use cases.

Conclusion

ContextMapper’s DSL makes DDD documentation clearer and more consistent, lowers the entry barrier for beginners, and integrates well with code generation and microservice design, though practical effectiveness still depends on real‑world adoption.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DSLMicroservicesDDDDomain-Driven DesignContextMapper
Alibaba Cloud Developer
Written by

Alibaba Cloud Developer

Alibaba's official tech channel, featuring all of its technology innovations.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.