Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Moduar Monolith @Codecamp 2023

Moduar Monolith @Codecamp 2023

Victor Rentea

November 17, 2023
Tweet

More Decks by Victor Rentea

Other Decks in Technology

Transcript

  1. The Way of the
    Modular Monolith
    [email protected] ♦ ♦ @victorrentea ♦ VictorRentea.ro

    View full-size slide

  2. 👉 victorrentea.ro/training-offer
    Hi, I'm Victor Rentea 🇷🇴 PhD(CS)
    Java Champion, 17 years of code, code, code, code, code....
    Consultant & Trainer: 5000 developers of 100+ companies in EU:
    ❤ Clean Code, Architecture, Unit Tes3ng
    🛠 Spring, Hibernate, Reactor
    ⚡ Java Performance, Secure Coding 🔐
    Conference Speaker – many conferences talks on YouTube
    Founder of European SoLware CraLers (5500+ members)
    🔥 Free monthly webinars, 1 hour a9er work 👉 victorrentea.ro/community
    Past events on my channel: youtube.com/vrentea
    Father of 👧👦, host of a 🐈, weekend gardener 🌼
    h"ps://VictorRentea.ro

    View full-size slide

  3. Modular Monolith

    View full-size slide

  4. 4 VictorRentea.ro
    a training by
    The Monolith
    Tangled highly-coupled code
    Full of dirty fixes
    Slow and risky to change
    Craving for refactoring, but lacking unit tests
    The architecture of many successful systems in produc@on today
    aka Big Ball of Mud

    View full-size slide

  5. 5 VictorRentea.ro
    a training by
    h-ps://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

    View full-size slide

  6. 6 © VictorRentea.ro
    a training by
    A large project is more likely to suffer
    from internal coupling
    (ie. domain dilu6on, scope creep)
    than from coupling to external APIs and Libraries
    Elders Wisdom
    Focus of tradi6onal
    Concentric Architectures
    (Clean, Onion, Hexagonal, Ports-Adapters)

    View full-size slide

  7. 7 © VictorRentea.ro
    a training by
    Microservices🌈
    ü Faster Time-to-Market ⭐
    ü Smaller Teams (Two-Pizza-sized)
    ü Improved Scalability
    ü Fault Tolerance
    ü Programming Language Agnos?c
    ü Data Security
    Microservice
    💰 Premium 💰
    - Network Latency
    - Timeout/Retry
    - Idempotency
    - Load balancing
    - Rate Limiter
    - Bulkhead
    - Circuit Breaker/503
    - Distributed cache
    - Log aggregaGon
    - Request tracing
    - Message queues
    - k8s, Docker
    - Mature DevOps culture

    View full-size slide

  8. 8 VictorRentea.ro
    a training by
    1) Big-Bang Rewrite
    - Start from scratch, re-specifying all behavior
    - New features in old system: delay or implement twice
    - 20-30% success rate
    - Likely to end up with a Distributed Monolith 😱
    2) Strangler-Fig Pa4ern
    - Implement new features in fresh microservices
    - Con6nuously strip bits of func6onality from the monolith
    3) Refactor to Modules > Extract 🌈
    - Decouple logic and data in the same monolithic codebase
    From a Legacy Monolith💀 to Microservices🌈
    Highly-coupled Distributed Systems

    View full-size slide

  9. 9 VictorRentea.ro
    a training by
    Modular Monolith
    is a safe Transi8oning Step from a
    Legacy Monolith è Microservices

    View full-size slide

  10. 10 VictorRentea.ro
    a training by
    What's faster to build from scratch?
    A Monolith or Microservices

    View full-size slide

  11. 11 VictorRentea.ro
    a training by
    What's faster to build from scratch?
    A Monolith or Microservices
    But coupling
    eventually starts
    slowing us down

    View full-size slide

  12. 12 VictorRentea.ro
    a training by
    Produc@vity
    Func@onal Complexity (Time)
    Microservices
    as complexity accumulates,
    produc6vity starts to drop
    overhead of managing
    distributed systems
    reduces ini6al produc6vity
    the decreased coupling of microservices
    outweighs their governance overhead
    Produc2vity
    years
    Monolith
    But I'm going to build
    a complex system!

    View full-size slide

  13. 13 VictorRentea.ro
    a training by
    "You shouldn't start a new project with microservices,
    even if you're sure your application
    will be big enough to make it worthwhile."
    - Martin Fowler
    h-ps://marKnfowler.com/bliki/MonolithFirst.html (2015)
    Start simple and address the natural bottlenecks of the system
    (functional/technical).

    View full-size slide

  14. 14 VictorRentea.ro
    a training by
    Modular Monolith
    is the best way to start a Greenfield

    View full-size slide

  15. 15 VictorRentea.ro
    a training by
    Monolith or Microservices?

    View full-size slide

  16. 16 VictorRentea.ro
    a training by
    What if we could have the best of both worlds?
    Physical architecture of a Monolith
    Logical architecture of Microservices
    Ability to easy extract a Microservice out when necessary

    View full-size slide

  17. Modular Monolith
    Modulith

    View full-size slide

  18. 18 VictorRentea.ro
    a training by
    Legacy Monolith Microservices
    Database
    eShop ApplicaGon Catalog
    Microservice
    Catalog DB
    Orders
    Microservice
    Orders DB
    REST REST/MQ
    Payment
    Microservice
    Payment DB
    Customer
    Microservice
    Customer DB
    vs

    View full-size slide

  19. 19 VictorRentea.ro
    a training by
    Modular Monolith
    Database
    E-Shop Modular Monolith ApplicaGon
    Catalog
    Module
    Orders
    Module
    Payment
    Module
    Customer
    Module

    View full-size slide

  20. 20 VictorRentea.ro
    a training by
    Life in a Modulith
    The complexity of the project
    is split in decoupled modules
    managed by separate teams
    🎉

    View full-size slide

  21. 21 VictorRentea.ro
    a training by
    Okay,
    But what IS a module?

    View full-size slide

  22. 22 VictorRentea.ro
    a training by
    Think of a module as a
    stand-alone logical applica/on
    (including its own frontend)

    View full-size slide

  23. 23 VictorRentea.ro
    a training by
    Internal Architecture of a Module
    Can be decided per-module

    View full-size slide

  24. 24 VictorRentea.ro
    a training by
    Internal Architecture of a Module
    Layered Architecture Presenta6on / API
    Service
    Repository

    View full-size slide

  25. 25 VictorRentea.ro
    a training by
    Internal Architecture of a Module
    Layered Architecture
    Clean, Pragma/c* Architecture Domain
    * Avoid over-engineering:
    h"ps://www.youtube.com/watch?v=ewe68u1v6bo

    View full-size slide

  26. 26 VictorRentea.ro
    a training by
    Internal Architecture of a Module
    Layered Architecture
    Clean, Pragma/c* Architecture
    Ver/cal Slice Architecture
    Presenta6on / API
    Service
    Repository
    Place Order
    Es6mate Shipping Date

    View full-size slide

  27. 27 VictorRentea.ro
    a training by
    Modulith Challenges
    Defining module boundaries
    CommunicaJon between modules
    Data independence

    View full-size slide

  28. 28 © VictorRentea.ro
    a training by
    Architecture is the art of drawing lines
    (boundaries)
    Elders Wisdom

    View full-size slide

  29. 29 VictorRentea.ro
    a training by
    .controller
    .service
    .repo
    .infra
    com.myorg.myapp
    .order
    .product
    Top Packages Reflec8ng Technical Layers
    (tradi'onal style)
    .entity
    .order
    .product
    To keep packages small,
    we introduce sub-packages

    View full-size slide

  30. 30 VictorRentea.ro
    a training by
    .service
    com.myorg.myapp .order
    .product .service
    The Screaming Architecture
    Top-level packages reflect your domain structure
    .entity
    .repo


    separate
    modules
    h"ps://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html

    View full-size slide

  31. 31 VictorRentea.ro
    a training by
    .order .product
    .fulfillment .catalog
    .invoice
    .invoicing
    Group by Business Capability
    (what value it brings the users)
    Group by Data Concept
    Module Names

    View full-size slide

  32. 32 VictorRentea.ro
    a training by
    Organize by Capability
    supports beIer the complexity
    Pricing Catalog
    Customer
    • customer first name
    • customer last name
    • product name
    • product description
    • customer status
    • product price
    class Customer {
    firstName
    lastName
    status
    !!...
    }
    class Product {
    name
    description
    price
    !!...
    }

    View full-size slide

  33. 33 VictorRentea.ro
    a training by
    A Module* is NOT:
    • Just Behavior
    Example: calcula6on, valida6on
    • Just CRUD Data
    Example: Country, Tenant, Clinic
    * the same applies for "Microservice"
    Microservices: configura6on or en6ty microservice
    CountryRepo in the 'shared' module

    View full-size slide

  34. 34 VictorRentea.ro
    a training by
    A Module* is the technical authority
    for a business capability
    .product .catalog
    * the same applies for "Microservice"

    View full-size slide

  35. 35 VictorRentea.ro
    a training by
    The boundary within which a Domain Model applies
    The smaller the boundary, the more useful the model.
    Bounded Context
    2003

    View full-size slide

  36. 36 VictorRentea.ro
    a training by
    How Big should a Module* be?
    * the same applies for "Microservice"
    As small
    as possible!

    View full-size slide

  37. 37 VictorRentea.ro
    a training by
    The Fallacy of Nano-Services

    View full-size slide

  38. 38 VictorRentea.ro
    a training by
    The Fallacy of Nano-Services
    Modules

    View full-size slide

  39. 39 VictorRentea.ro
    a training by
    The Fallacy of Nano-Modules*
    h)ps://vladikk.com/2020/04/09/untangling-microservices/
    * the same applies for "Microservice"
    Global Complexity
    of integraGng all the APIs
    Local Complexity
    of a single module
    High Cohesion, Low Coupling

    View full-size slide

  40. 40 VictorRentea.ro
    a training by
    Be brave and
    Keep It Super Simple
    When Complexity Grows > Extract it
    Evolutionary Architecture

    View full-size slide

  41. 41 VictorRentea.ro
    a training by
    Module A
    @Test !// unit test on CI
    public void independentSubdomains() {
    slices().matching("!..myapp.(*)!..*")
    .should().notDependOnEachOther()
    .ignoreDependency(resideInAnyPackage(
    "!..shared!..", "!..api!.."))
    .check(new ClassFileImporter().
    importPackages("com.myapp"));
    }
    2) Communica2on between Modules
    The internals of a module should never be accessed from another module
    Each Module exposes a Public API that other modules can reference
    Public
    API
    events
    calls
    1. Compiler-enforced
    Separate CompilaGon Units
    (eg Maven modules)
    2. Unit Tests on CI
    Code Analysis, eg ArchUnit:
    Part of the Public API can be exposed
    as External API to remote apps
    (eg via REST, MQ)
    External
    API

    View full-size slide

  42. 42 VictorRentea.ro
    a training by
    Module CommunicaJon via
    Method Calls
    calls
    Extremely simple
    Fast, in-memory calls (no networking)
    ⚠ Methods called and objects involved must be part of the Public API

    View full-size slide

  43. 43 VictorRentea.ro
    a training by
    ⚠ Published Events must be part of the Public API
    J Decoupled: publisher unaware of listeners (poten@ally mul@ple)
    J Poten@ally async
    J Poten@ally persisted
    L Not suitable for request-reply interac@on
    L Naviga@ng code is harder (than a method call)
    Event Types: No@fica@on {id}, or Heavy-Events {state}
    events
    Module CommunicaJon via
    Events / Messages

    View full-size slide

  44. 44 VictorRentea.ro
    a training by
    Cyclic Dependencies between Modules
    A B
    call
    call
    Build fails if modules are separate compila@on units
    (eg. Maven/Gradle modules)


    View full-size slide

  45. 45 VictorRentea.ro
    a training by
    api
    (shared)
    A B
    O
    orchestrator
    Keep Orchestra@on Up
    Just fix the build, allow the ó calls
    A B
    A-api B-api
    Extract API modules
    run'me calls
    Facade
    keep a coarse grained API,
    eg for a monolith site
    Fixing Cyclic Dependencies between Modules
    microservices: N/A
    microservices: events on queue
    microservices: interdependent microservices
    microservices: api gateway/bff/saga microservices: shared lib/3rd service microservices: merge?

    AB
    Merge Modules
    Tight Coupling
    (eg dozens of links)
    wrong boundaries?
    Using Dependency Inversion
    B can let A implement logic,
    without depending on A
    A B
    ç event
    call
    Publish Events (in-mem)
    ⭐Decoupled
    A B
    C
    commons
    Push Commons Down
    A B
    implements è
    call
    Dependency Inversion
    ⭐Decoupled
    AProviderImpl
    runKme call
    AProvider
    Module A must react to changes in B
    Technical
    Stuff Only
    send email
    countryRepo
    audit, ...
    uSls

    View full-size slide

  46. 46 VictorRentea.ro
    a training by
    A
    Surface of a Module
    publish events
    call
    interface
    implementa-on
    B
    command
    query
    (a) no-fica-on {id}
    (b) Heavy-Event {state}
    listen to events
    External
    API
    Public API

    View full-size slide

  47. 47 VictorRentea.ro
    a training by
    3) Module Data Independence
    Every module is responsible for its own data
    ⚠ A Module should not query the tables of another module
    (breaks encapsula@on)
    Instead, ask for that data via the Public API

    View full-size slide

  48. 48 VictorRentea.ro
    a training by
    Module Data Isola2on Levels
    No IsolaGon: Any module can freely read/write any table
    Write IsolaGon: A table is updated by ONE module, but can be read by other modules
    Table IsolaGon⭐: A module has exclusive access to its tables (usually separate schemas)
    Consistency IsolaGon - tables of different modules:
    (a) cannot share a Foreign Key, and
    (b) are never updated in the same DB transac@on
    Separate database instance / module
    Different database types, eg PostgresSQL / MongoDB
    Before extrac@ng
    a microservice

    View full-size slide

  49. 49 VictorRentea.ro
    a training by
    Tes8ng a Modulith
    End-to-end Tests
    are easier in a monolith
    Module Tests
    Integra0on tes0ng an Module in isola0on
    - mock public APIs of other modules
    - mock event bus
    è Spring Modulith project
    h4ps://spring.io/projects/spring-modulith

    View full-size slide

  50. 50 VictorRentea.ro
    a training by
    Modulith – Lessons Learned
    Ø Invest more @me to clarify module boundaries
    Ø Consider merging highly-coupled modules
    Ø Don't sacrifice consistency too early
    Ø Carefully design how data is shared between modules
    Ø Don't leak internal classes via module's Public API
    Ø Monitor architecture fitness func@ons using code analysis tools

    View full-size slide

  51. 51 VictorRentea.ro
    a training by
    •Migrating legacy monoliths
    eg. an existing large-scale banking platform monolith that
    needs to split into microservices, but isn't ready to separate
    into completely independent services.
    •A greenfield implementation
    eg. a new peer-to-peer lending platform in the early stages
    of growing into a full suite of financial services
    •A system with a low-moderate scale
    eg. a movie ticket booking platform that serves several
    thousand users and handles a few million transactions per
    week.
    •Non-complex software platforms
    eg. a notes/documents syncing and management platform
    for consumer apps.
    When to choose a Modulith? When to move to Microservices?
    •High Delivery Rate ?
    eg. the company decides investing in shipping to self-collect
    boxes on the street, and new versions are deployed weekly.
    •Scalability
    eg. the endpoint selecting the ad to insert in a live stream
    expected to take 1k-10k requests/second.
    •Fault-tolerance
    eg. in the same ad-insert solution, if the management part
    fails, the ads still have to be inserted
    •Different Programming Language
    eg. the senior developers of sales department are using C#
    while the rest of the teams use Java. Oh, and Kotlin rocks!🤘
    •Security
    eg. customer management has to be audited for GDPR
    compliance regarding PII information.

    View full-size slide

  52. 52 VictorRentea.ro
    a training by
    But remember,
    The Skills of the Team will outweigh
    any monolith/microservice choice
    A great team will build a great project
    whatever architectural style you choose
    #investInPeople

    View full-size slide

  53. thank you
    [email protected] ♦ ♦ @victorrentea ♦ VictorRentea.ro
    victorrentea.ro/community
    Want more? Register for my upcoming deep dive webinar on Architectures on May 29-30 at h"ps://clean.re
    For a company workshop see
    victorrentea.ro/training-offer

    View full-size slide

  54. 54 VictorRentea.ro
    a training by
    § Ugly (Successful) Monolith☠
    - "It works > Ship it now, refactor later" for 5-25 years
    § Domain-Driven Design (Eric Evans, 2003) link
    - Design Rich Domain Model for complex problems;
    - Split soluKon in Bounded Context
    § Onion/Clean Architecture (Jeffrey Palermo, Uncle Bob 2008) link
    - Keep core Domain Logic agnosKc from UI, APIs, DB, frameworks (by dep. inversion)
    § PragmaQc Onion link
    - Merge applicaKon with infrastructure, evolve layers as needed, tolerate ORM on Domain Model
    § Microservices (2011)
    - Loosely coupled, independent business capabiliKes deployed separately
    § Distributed Monolith☠ link
    - Tightly coupled microservices due to premature, too fine-grained breakdown
    § VerQcal Slice Architecture (Jimmy Bogard, 2018) link
    - Group code by feature, not by technical layer
    § Modular Monolith, aka Modulith (Simon Brown, 2018)
    - Implement business capabiliKes as loosely coupled modules in a single deployment unit
    Overview of Architecture Styles

    View full-size slide