Documenting Application Modules
通过`ApplicationModules`创建的应用程序模块模型可以用来创建文档摘录,以包含到用Asciidoc撰写的开发人员文档中。Spring Modulith的`Documenter`抽象可以生成两种不同类型的摘录:
The application module model created via ApplicationModules
can be used to create documentation snippets for inclusion into developer documentation written in Asciidoc.
Spring Modulith’s Documenter
abstraction can produce two different kinds of snippets:
-
C4 and UML component diagrams describing the relationships between the individual application modules
-
A so-called Application Module Canvas, a tabular overview about the module and the most relevant elements in those (Spring beans, aggregate roots, events published and listened to as well as configuration properties).
Generating Application Module Component diagrams
文档摘录可以通过将`ApplicationModules`实例传递到`Documenter`中来生成。
The documentation snippets can be generated by handing the ApplicationModules
instance into a 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组件图,其中包含系统中的所有模块。
The first call on Documenter
will generate a C4 component diagram containing all modules within the system.
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()
第二次调用将创建其他图,这些图将仅包括模块及其直接依赖关系画布上。
The second call will create additional diagrams that only include the individual module and the ones they directly depend on on the canvas.
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`,以使用那种样式,如下所示:
If you prefer the traditional UML style component diagrams, tweak the DiagramOptions
to rather use that style as follows:
-
Java
-
Kotlin
DiagramOptions.defaults()
.withStyle(DiagramStyle.UML);
DiagramOptions.defaults()
.withStyle(DiagramStyle.UML)
这将导致生成的图看起来像这样:
This will cause the diagrams to look like this:
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()`生成应用程序模块画布:
The Application Module Canvases can be generated by calling 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`文件夹。生成的画布看起来像这样:
By default, the documentation will be generated to spring-modulith-docs
folder in your build system’s build folder.
A generated canvas looks like this:
Base package |
|
---|---|
Spring components |
Services
Repositories
Event listeners
Configuration properties
Others
|
Aggregate roots |
|
Published events |
|
Events listened to |
|
Properties |
|
它包含以下部分:
It consists of the following sections:
-
The application module’s base package.
-
The Spring beans exposed by the application module, grouped by stereotype. — In other words, beans that are located in either the API package or any named interface package. This will detect component stereotypes defined by jMolecules architecture abstractions, but also standard Spring stereotype annotations.
-
Exposed aggregate roots — Any entities that we find repositories for or explicitly declared as aggregate via jMolecules.
-
Application events published by the module — Those event types need to be demarcated using jMolecules
@DomainEvent
or implement itsDomainEvent
interface. -
Application events listened to by the module — Derived from methods annotated with Spring’s
@EventListener
,@TransactionalEventListener
, jMolecules'@DomainEventHandler
or beans implementingApplicationListener
. -
Configuration properties — Spring Boot Configuration properties exposed by the application module. Requires the usage of the
spring-boot-configuration-processor
artifact to extract the metadata attached to the properties.