Hard to find the right cable you need Sometimes we connect wrong cables to wrong adapters Requires time and patience to simplify the clutter At some point, we pour the box and reorganize all the cables Throwing the box away completely would also be a solution
Tests Feign Client Docker Jenkins Sonar MongoDB JWT React Prometheus Grafana Elastic Search Object Mapper Actuator Open API Swagger Config Server Euroka Kotlin Groovy Spring Cloud JPA Go Node Kibana Mockito THE REALITY Spring Boot
Tests Feign Client Docker Jenkins Sonar MongoDB JWT React Prometheus Grafana Elastic Search Object Mapper Actuator Open API Swagger Config Server Euroka Kotlin Groovy Spring Cloud JPA Go Node Kibana Mockito Spring Boot the implementation of customers’ needs THE REALITY Where is the business logic?
Tests Feign Client Docker Jenkins Sonar MongoDB JWT React Prometheus Grafana Elastic Search Object Mapper Actuator Open API Swagger Config Server Euroka Kotlin Groovy Spring Cloud JPA Go Node Kibana Mockito Spring Boot scattered somewhere in the code THE REALITY Where is the business logic?
Hard to find the right cable you need Sometimes we connect wrong cables to wrong adapters Requires time and patience to simplify the clutter At some point, we pour the box and reorganize all the cables Throwing the box away completely would also be a solution place to update the code grow the codebase the codebase stop adding new features and refactor Deleting legacy code and rewriting dependencies
rises till the dead end You either redesign or rewrite to continue adding new features Adding new people to the team makes the progress slower Microservices transformation projects usually aim to fix these kinds of legacy projects THE IMPACT OF COMPLEXITY AS USUAL Feature Count Time Growth Limit Growth Limit let’s split it into microservices we need to rewrite it again Difficulty Level While Adding New Features Time refactor redesign zone Growth Limit Growth Limit the increase in endurance level is due to the new senior endurance level: do not touch if it works transfor- mation project zone go-live night
New Features Time THE IMPACT OF MANAGABLE COMPLEXITY aka. SUSTAINABLE GROWTH No need for big redesigns or rewrites, refactoring is enough Refactoring should be continuous The system should be open to extension and close to modification Adding new people to the team has a positive impact No direct need for microservices
an exercise in What is Software Design? The C++ Journal Vol. 2, No. 2. 1992 http://user.it.uu.se/~carle/softcraft/notes/Reeve_SourceCodeIsTheDesign.pdf Reference: Jack W. Reeves Author of the "(B)leading Edge" column for the publication C++ Report “ managing complexity.
the business domain itself. “Interview With Eric Evans; Why DDD Matters Today” Dec 20, 2006 http://www.infoq.com/articles/eric-evans-ddd-matters-today Reference: Eric Evans Author of the "Domain-Driven Design: Tackling Complexity in Software" “
elbise-yi dene-mek iste-r-im needs a paradigm shift like the difference between structure in English and Turkish Unlearn what you’ve known so far and Relearn with no biases and limits
Boot, Frameworks Cloud Engineering Event-based architecture Distributed systems Scrum, Kanban, etc. Story point estimations Packaging by infrastructure Dependency Injection Having modules anywhere These may decrease complexity but not enough for sustainable growth
PRINCIPLE DEPENDENCY INVERSION PRINCIPLE COUPLING COHESION sustainable growth The mentality behind modularization, i.e. the principle of “Separation of Concerns” - Edsget W. Dijkstra 1 Know The Fundamentals Details can be found in my talk: Modular Architecture For Pragmatic Developer https://speakerdeck.com/lemiorhan/modular-architecture-for-pragmatic-developers PRINCIPLES
internal properties and behaviors should be. - Alan Kay 2 Focus on Modules & Communication Details can be found in my talk: Unlearn OOP https://speakerdeck.com/lemiorhan/unlearn-oop-deleted-scenes-misconceptions-unspoken-truths OBJECT ORIENTED PROGRAMMING PRINCIPLES
the impact of change. - Robert C. Martin 3 Learn How to Manage Dependencies Details can be found in my talk: It’s Not SOLID Anymore https://speakerdeck.com/lemiorhan/it-is-not-solid-anymore DESIGN PRINCIPLES PRINCIPLES
to separate code rather than change frequently from stable code. - James Coplien 4 Protect Business Logic from Poisoning Details can be found in my talk: Growing Hexagonal Microservices with TDD https://speakerdeck.com/lemiorhan/growing-hexagonal-microservices-by-tdd HEXAGONAL ARCHITECTURE APPROACH
be adding a new behavior rather than adding a method or class. - Ian Cooper 5 Test Really What Matters: Behaviors Details can be found in my talk: Unlearn Unit Testing https://speakerdeck.com/lemiorhan/unlearn-unit-testing UNIT TESTING APPROACH
Dave Thomas 6 Focus on Contexts, Build Rules Around Details can be found in my talk: Pure Agile https://speakerdeck.com/lemiorhan/pure-agile-building-a-culture-without-scrum-kanban-and-xp-extended-version-v22-dot-11 AGILE IS DEAD LONG LIVE AGILITY APPROACH there are no rules in software, there are patterns. The critical part is deciding which patterns to use
goal, context represents use cases, one per use case - James Coplien 7 Put Bricks on the Wall One-by-One Details can be found in my talk: Domain Driven Modular Architecture https://speakerdeck.com/lemiorhan/domain-driven-modular-architecture USE CASE DRIVEN APPROACH DESIGN
modules are chapters. It isn’t just code being divided into modules, but concepts. - Eric Evans 8 Shape Software based on Contexts BOUNDED CONTEXT DOMAIN DRIVEN DESIGN Details can be found in my talk: Domain Driven Modular Architecture https://speakerdeck.com/lemiorhan/domain-driven-modular-architecture DESIGN
on the Wall One-by-One 6 Focus on Contexts, Build Rules Around 5 Test Really What Matters: Behaviors 4 Protect Business Logic from Poisoning APPROACH Modularity & Sustainable Growth 3 Learn How to Manage Dependencies 2 Focus on Modules & Communication 1 Know The Fundamentals PRINCIPLES
UNIT TESTING HEXAGONAL ARCHITECTURE AGILE IS DEAD LONG LIVE AGILITY APPROACH SEPARATION OF CONCERNS INFORMATION HIDING PRINCIPLE INVERSION OF CONTROL PRINCIPLE DEPENDENCY INVERSION PRINCIPLE COUPLING COHESION OBJECT ORIENTED PROGRAMMING DESIGN PRINCIPLES PRINCIPLES
needs to be always consistent An aggregate is just a construct to organize business rules Aggregate is a unit for the purpose of data changes CARD PAYMENT CONTEXT
is the facade representing the whole structure, and it is the gateway. It enforces the aggregate's business/consistency rules References to aggregate internals from the outer world are strictly forbidden CARD PAYMENT CONTEXT
INPUT OUTPUT Each BC is loosely coupled & independent and has its own ubiquitous language, own data, and an explicit owner. We split software into BCs, like microservices. Unlike modules, which are organized primarily around technical concerns, BCs are organized around business concerns. is it a realization of Moduliths ?
includes a high-level view of the domains involved, along with the relationships and interactions between them communication patters used in microservices are applicable here Relationship Models Customer-Supplier Conformist Partneship Anti-Corruption Layer Separate Ways Open-Host Service Shared Kernel
software is Different than relationship models Strategies Chained - Unchained Transactional - Non-Transactional CONTEXT A CONTEXT B CONTEXT C CONTEXT D
CASE USER CREATED MESSAGE OUTBOX SAVED MESSAGE CUSTOMER NOTIFIED MESSAGE TRANSACTIONAL SINGLE TRANSACTION One exception triggers rollbacking of all previous operations in multiple contexts
and then rebuild the system every time you make these shifts Two patterns closely related with each other to achieve this A. Configurable Connection Pattern B. Configurable Dependency Pattern https://alistaircockburn.com/Configurable%20Connection%20Configurable%20Dependency.pdf
on any receiver. It’s like polymorphism from OOP. Sender has a source-code dependency on the receiver. SENDER RECEIVER 1 RECEIVER 2 RECEIVER3 sender’s provided interface sender’s required interface RECEIVER CONTRACT Sender asks the configurator which receiver to use, like in dependency lookup. Sender contains a hard-coded reference to the configurator. We avoid hard-coding the names of classes on which we depend in our code. Sender has a source-code dependency on the configurator. SENDER RECEIVER 1 RECEIVER 2 RECEIVER3 RECEIVER CONTRACT CONFIGURATOR CONFIGURATOR CONFIGURATOR B application context spring SENDER RECEIVER 1 RECEIVER 2 RECEIVER3 sender’s provided interface sender’s required interface RECEIVER CONTRACT CONFIGURATOR Configurator tells the sender what receiver to use, like in dependency injection. Receiver is held in sender in a local variable. It is set the receiver during execution, or at initialization. Sender still has a source-code dependency on the receiver. A spring
sender calls it via static methods. Receivers register themselves at initialization to the configurator. Configurator knows which receiver to select. Sender has no source-code dependency. SENDER RECEIVER 1 RECEIVER 2 RECEIVER3 RECEIVER CONTRACT CONFIGURATOR CONFIGURATOR CONFIGURATOR the new approach publisher Sender asks the configurator which receiver to use, like in dependency lookup. Sender contains a hard-coded reference to the configurator. We avoid hard-coding the names of classes on which we depend in our code. Sender has a source-code dependency on the configurator. SENDER RECEIVER 1 RECEIVER 2 RECEIVER3 RECEIVER CONTRACT CONFIGURATOR CONFIGURATOR CONFIGURATOR B application context spring SENDER RECEIVER 1 RECEIVER 2 RECEIVER3 sender’s provided interface sender’s required interface RECEIVER CONTRACT CONFIGURATOR Configurator tells the sender what receiver to use, like in dependency injection. Receiver is held in sender in a local variable. It is set the receiver during execution, or at initialization. Sender still has a source-code dependency on the receiver. A spring
it via static methods. Receivers register themselves at initialization to the configurator. Configurator knows which receiver to select. Sender has no source-code dependency. SENDER RECEIVER 1 RECEIVER 2 RECEIVER3 RECEIVER CONTRACT CONFIGURATOR CONFIGURATOR CONFIGURATOR the new approach publisher CONFIGURATOR: MESSAGE PUBLISHER SENDER RECEIVER: USE CASE HANDLER
Spring into the registry, which is accessed by Message Publisher to submit messages HANDLER REGISTRATION Receivers are extended by MessageHandlers not only for being detected by Spring, and also for providing base “handle method” infrastructure STEP 1
coupled, real-time dependency strategy to bounded contexts Supports aggregate roots and domain events Supports use-case driven approach and hexagonal architecture Supports transactional flows among aggregates Supports sync and async call chains between bounded contexts Contains unit tests for the API and acceptance tests for checking possible flows Detailed documentation describing why we need that & how it works Actively being used in production craftgate-modulith-messaging
defined input/output interfaces Each module hides implementation details and exposes a high-level contract Each module handles multiple use cases directly related to user needs Each module extends by one use case at a time, no bloating experienced Each module is loosely coupled and highly coherent
mail: [email protected] CRAFTGATE one-stop shop payment gateway payment hub for your virtual poses with dynamic pos routing, you always pay the lowest commission to banks craftgate.io @craftgateio