Documenting Application Modules
通过`ApplicationModules`创建的应用程序模块模型可以用来创建文档摘录,以包含到用Asciidoc撰写的开发人员文档中。Spring Modulith的`Documenter`抽象可以生成两种不同类型的摘录:
-
描述单个应用程序模块之间关系的 C4 和 UML 组件图
-
所谓的 Application Module Canvas,关于模块和其中最相关元素的表格概览(Spring bean、聚合根、发布和侦听的事件以及配置属性)。
Generating Application Module Component diagrams
文档摘录可以通过将`ApplicationModules`实例传递到`Documenter`中来生成。
Documenter
-
Java
-
Kotlin
class DocumentationTests {
ApplicationModules modules = ApplicationModules.of(Application.class);
@Test
void writeDocumentationSnippets() {
new Documenter(modules)
.writeModulesAsPlantUml()
.writeIndividualModulesAsPlantUml();
}
}
class DocumentationTests {
private val modules = ApplicationModules.of(Application::class)
@Test
fun writeDocumentationSnippets() {
Documenter(modules)
.writeModulesAsPlantUml()
.writeIndividualModulesAsPlantUml()
}
}
对`Documenter`的首次调用将生成一个C4组件图,其中包含系统中的所有模块。
top to bottom direction
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4.puml !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml
Container_Boundary("Modulith.Application_boundary", "Application") { Component(Modulith.Application.core, "core", "Module", "", $tags="") Component(Modulith.Application.catalog, "catalog", "Module", "", $tags="") Component(Modulith.Application.inventory, "inventory", "Module", "", $tags="") Component(Modulith.Application.order, "order", "Module", "", $tags="") Component(Modulith.Application.customer, "customer", "Module", "", $tags="") }
Rel_D(Modulith.Application.order, Modulith.Application.core, "depends on", $tags="") Rel_D(Modulith.Application.order, Modulith.Application.customer, "uses", $tags="") Rel_D(Modulith.Application.catalog, Modulith.Application.core, "depends on", $tags="") Rel_D(Modulith.Application.inventory, Modulith.Application.order, "listens to", $tags="") Rel_D(Modulith.Application.inventory, Modulith.Application.catalog, "uses", $tags="") Rel_D(Modulith.Application.inventory, Modulith.Application.order, "uses", $tags="") Rel_D(Modulith.Application.inventory, Modulith.Application.core, "uses", $tags="") Rel_D(Modulith.Application.order, Modulith.Application.catalog, "depends on", $tags="")
SHOW_LEGEND()
第二次调用将创建其他图,这些图将仅包括模块及其直接依赖关系画布上。
top to bottom direction
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4.puml !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml
Container_Boundary("Modulith.Application_boundary", "Application") { Component(Modulith.Application.core, "core", "Module", "", $tags="") Component(Modulith.Application.catalog, "catalog", "Module", "", $tags="") Component(Modulith.Application.order, "order", "Module", "", $tags="") Component(Modulith.Application.customer, "customer", "Module", "", $tags="") }
Rel_D(Modulith.Application.order, Modulith.Application.core, "depends on", $tags="") Rel_D(Modulith.Application.order, Modulith.Application.customer, "uses", $tags="") Rel_D(Modulith.Application.catalog, Modulith.Application.core, "depends on", $tags="") Rel_D(Modulith.Application.order, Modulith.Application.catalog, "depends on", $tags="")
SHOW_LEGEND()
Using Traditional UML Component Diagrams
如果您更喜欢传统的UML样式组件图,请调整`DiagramOptions`,以使用那种样式,如下所示:
-
Java
-
Kotlin
DiagramOptions.defaults()
.withStyle(DiagramStyle.UML);
DiagramOptions.defaults()
.withStyle(DiagramStyle.UML)
这将导致生成的图看起来像这样:
skinparam { shadowing false arrowColor #707070 actorBorderColor #707070 componentBorderColor #707070 rectangleBorderColor #707070 noteBackgroundColor #ffffff noteBorderColor #707070 defaultTextAlignment center wrapWidth 200 maxMessageSize 100 componentStyle uml1 } package "Application" [Container] { component 4 [Component: Module] #dddddd [ com.acme.commerce.catalog ] component 3 [Component: Module] #dddddd [ com.acme.commerce.core ] component 7 [Component: Module] #dddddd [ com.acme.commerce.customer ] component 5 [Component: Module] #dddddd [ com.acme.commerce.inventory ] component 6 [Component: Module] #dddddd [ com.acme.commerce.order ] } 4 .[#707070].> 3 : depends on 5 .[#707070].> 4 : uses 5 .[#707070].> 3 : uses 5 .[#707070].> 6 : uses 5 .[#707070].> 6 : listens to 6 .[#707070].> 4 : depends on 6 .[#707070].> 3 : depends on 6 .[#707070].> 7 : uses
skinparam { shadowing false arrowColor #707070 actorBorderColor #707070 componentBorderColor #707070 rectangleBorderColor #707070 noteBackgroundColor #ffffff noteBorderColor #707070 defaultTextAlignment center wrapWidth 200 maxMessageSize 100 componentStyle uml1 } package "Application" [Container] { component 4 [Component: Module] #dddddd [ com.acme.commerce.catalog ] component 3 [Component: Module] #dddddd [ com.acme.commerce.core ] component 7 [Component: Module] #dddddd [ com.acme.commerce.customer ] component 6 [Component: Module] #dddddd [ com.acme.commerce.order ] } 4 .[#707070].> 3 : depends on 6 .[#707070].> 4 : depends on 6 .[#707070].> 3 : depends on 6 .[#707070].> 7 : uses
Generating Application Module Canvases
可以通过调用`Documenter.writeModuleCanvases()`生成应用程序模块画布:
Documenter
-
Java
-
Kotlin
class DocumentationTests {
ApplicationModules modules = ApplicationModules.of(Application.class);
@Test
void writeDocumentationSnippets() {
new Documenter(modules)
.writeModuleCanvases();
}
}
class DocumentationTests {
private val modules = ApplicationModules.of(Application::class)
@Test
fun writeDocumentationSnippets() {
Documenter(modules)
.writeModuleCanvases()
}
}
默认情况下,会在您的构建系统的构建文件夹中生成文档`spring-modulith-docs`文件夹。生成的画布看起来像这样:
Base package |
|
---|---|
Spring components |
Services* |
Aggregate roots |
|
Published events |
|
Events listened to |
|
Properties |
|
它包含以下部分:
-
The application module’s base package.
-
The Spring beans exposed by the application module, grouped by stereotype. - 换句话说,bean 位于 API 包或任何 named interface package 中。这将检测由 jMolecules architecture abstractions 定义的组件类型,但也将检测标准 Spring 类型注解。
-
Exposed aggregate roots - 任何我们为其找到存储库或通过 jMolecules 明确声明为聚合的实体。
-
Application events published by the module - 这些事件类型需要使用 jMolecules
@DomainEvent
划定或实现其DomainEvent
接口。 -
Application events listened to by the module - 源自使用 Spring
@EventListener
、@TransactionalEventListener
、jMolecules@DomainEventHandler
注释或实现ApplicationListener
的 bean 的方法。 -
Configuration properties - 应用程序模块公开的 Spring Boot 配置属性。要求使用
spring-boot-configuration-processor
工件来提取附加到属性的元数据。