Building Better Monoliths – Modulithic Applications with Spring Boot

Building Better Monoliths – Modulithic Applications with Spring Boot

How to improve the design of your monolithic applications build with Spring Boot.

977c74bb044a9d4fa90b305824eda390?s=128

Oliver Drotbohm

November 06, 2019
Tweet

Transcript

  1. Modulithic Applications
 with Spring Boot Building better monoliths Oliver Drotbohm

    ƀ odrotbohm@pivotal.io / odrotbohm
  2. 2

  3. Monolith VS. Microservice 3 Module
 A Module
 B Module
 C

    Module
 B Module
 C Module
 A Bounded Context Deployment Unit Internal invocation External invocation
  4. Monolith 4 The application packages the implementation of multiple Bounded

    Contexts as a single deployment unit. Easy to refactor Easy to test the overall system Likely to degrade unless explicitly managed Harder to test individual Bounded Contexts
  5. Microservices 5 A bounded context defines the boundaries of the

    deployment artifact. Often parts of the context are even deployed as separate processes. ◦ Bounded Context interaction is remote ◦ Testing individual modules Hard to refactor context boundaries Hard to test the overall system
  6. How to maintain structure in a monolithic codebase? 6 !

  7. Design goals 7 1. Minimally invasive As little additional metadata

    as possible required. Advanced customizations might need additional information. 2. Test support Individual modules should be testable standalone. 3. Minimize distance to development workflow Feedback about architecture violations as fast as possible.
  8. Development workflow 8 Compiler Tests Build Runtime Distance to edit

    / run cycle Where do I want my checks to live?
  9. The Sample Codebase https://github.com/st-tu-dresden/salespoint 9

  10. 10 Orders Business
 Time Catalog Inventory Component Dependency Type dependency

  11. Moduliths https://github.com/odrotbohm/moduliths Binaries available from https://repo.spring.io 11

  12. Moduliths 12 1. A convention to map contexts to packages

    Packages directly nested underneath the main application package are considered context ones.
  13. Package Conventions 13 ….modulith ….modulith.moduleA ….modulith.moduleB Visibility modifiers and the

    compiler enough to hide internals.
  14. Moduliths 14 1. A convention to map contexts to packages

    Packages directly nested underneath the main application package are considered context ones. 2. Simple set of access rules and API to verify Only access components in module API packages.
  15. Access Rules 15 Moduliths verifies a couple of rules imposed

    on your modules. No cyclic dependencies Only allows explicitly allowed dependencies Prevents field injection "
  16. Module dependency verification DEMO 16

  17. Access Rules 17 Moduliths verifies a couple of rules imposed

    on your modules. No cyclic dependencies Only allows explicitly allowed dependencies Prevents field injection " Use module base package as API package
  18. API Package Convention 18 ….modulith ….modulith.moduleA ….modulith.moduleB Visibility modifiers and

    the compiler enough to hide internals.
  19. API Package Convention 19 ….modulith ….modulith.moduleA ….modulith.moduleA.internal ….modulith.moduleB ….modulith.moduleB.internal Access

    to components residing in internal packages
 forbidden and checked during tests.
  20. Moduliths 20 1. A convention to map contexts to packages

    Packages directly nested underneath the main application package are considered context ones. 2. Simple set of access rules and API to verify Only access components in module API packages. 3. Test support to bootstrap modules Integration with Spring test context framework and Spring Boot integration test support to limit bootstrap (component & entity scanning) to only the involved packages.
  21. Web Business logic Data access @Data…Test Module A Module B

    Module C @WebMvcTest @…Test ?
  22. 22 package com.acme @SpringBootApplication class MyApplication { … } package

    com.acme.moduleA @ModuleTest // Instead of @SpringBootTest class MyModuleTests { … } Applies package conventions Bootstraps single module for test
  23. 24 Orders Business
 Time Catalog Inventory Component Dependency Type dependency

  24. Single module bootstrap DEMO 25

  25. Orders 28 Business
 Time Catalog Inventory Component Dependency Type dependency

  26. Detect and remove violation DEMO 29

  27. 30 Orders Business
 Time Catalog Inventory Component Dependency Type dependency

    
 Event Event publication
  28. Dependency types 32 1. Simple type dependency References to aggregates

    and entities of other modules. 2. Component dependency References to other Spring beans, required to bootstrap the module 3. Events & event listeners Dependency on some other module’s event type. Interesting as they’re great hooks for testing. #☝Avoid!
  29. 33 Orders Business
 Time Catalog Inventory Component Dependency Type dependency

    
 Event Event publication
  30. Multi module bootstrap DEMO 34

  31. Bootstrap modes 35 1. Standalone Bootstraps the module the test

    is contained in. Components in other modules the bootstrapped module depends on need to be provided through @MockBean. 2. Direct dependencies Bootstraps the module including the modules it directly depends on. Transitive dependencies have to be mocked just like in standalone mode. 3. All dependencies Bootstraps the entire sub-tree of modules starting from the current one.
  32. Moduliths 36 1. A convention to map contexts to packages

    Packages directly nested underneath the main application package are considered context ones. 2. Simple set of access rules and API to verify Only access components in module API packages. 3. Test support to bootstrap modules Integration with Spring test context framework and Spring Boot integration test support to limit bootstrap (component & entity scanning) to only the involved packages. 4. Documentation support PlantUML integration via Simon Brown’s Structurizr to document module structure and dependency types.
  33. Documentation DEMO 37

  34. Tool ecosystem and alternative approaches 38

  35. Multiple Artifacts 39 Every module port becomes a dedicated build

    artifact. Dedicated control over dependencies Test scope is defined by the artifact Potential explosion of number of artifacts Internal structure visible to the outside
  36. Java Module System 40 Every module becomes a Java 9+

    module. ◦ Strong coupling between module and artifact ◦ Semantics of the „opens“ keyword ◦ No test support
  37. External Tools 41 External tools (e.g. jQAssistant, Sonargraph, jDepend) integrated

    into the build and executed in the CI environment are used to signal structural violations. Most extensive option Distance to development workflow
  38. Development workflow 42 Compiler Tests Build Runtime Moduliths Maven Modules

    Jigsaw / OSGi jQA etc. Applies rules Invasiveness (bigger is stronger)
  39. Moduliths 43 1. A convention to map contexts to packages

    Packages directly nested underneath the main application package are considered context ones. 2. Simple set of access rules and API to verify Only access components in module API packages. 3. Test support to bootstrap modules Integration with Spring test context framework and Spring Boot integration test support to limit bootstrap (component & entity scanning) to only the involved packages. 4. Documentation support PlantUML integration via Simon Brown’s Structurizr to document module structure and dependency types.
  40. Resources 44 Moduliths Project website on GitHub Majestic Modular Monoliths

    Video on Youtube Modular Monoliths Simon Brown – Video on YouTube Refactoring to a System of Systems Video on YouTube
  41. Thank you! 45 Oliver Drotbohm ƀ odrotbohm@pivotal.io / odrotbohm