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

Modular Architecture for Pragmatic Developers

Modular Architecture for Pragmatic Developers

Modularity and Domain Driven Design has never been on the focus of software development. We think that all these concepts can be implemented by Microservices. I believe we need to focus of some design fundamentals to boost modularity in our codebase again.

I cover the following topics for understanding the roots of modularity better:

* Layered Architecture
* Spaghetti Code / Lasagna Code / Ravioli Code
* Separation of Concerns
* Information Hiding
* Inversion of Control
* Dependency Injection
* Dependency Inversion
* Hexagonal Architecture
* Microservice Architecture
* Domain Driven Design

I delivered the deck at "DevNot's DDD and Microservices Conference" in Turkey.

Lemi Orhan Ergin

June 20, 2020
Tweet

More Decks by Lemi Orhan Ergin

Other Decks in Technology

Transcript

  1. LEMi ORHAN ERGiN co-founder, Craftbase founder, Software Craftsmanship Turkey alumni,

    Sony, eBay, ACM, iyzico programming, since 2001 with love practitioner, modular design for years speakerdeck.com/lemiorhan @lemiorhan
  2. We build webapps webapp user database CRUD operations could be

    the most implemented feature in software history. Whatever you aim to build, you will need your data to be saved, updated, deleted and retrieved.
  3. Layered architecture Web Domain Persistence From a certain layer, we

    can only access components in the same layer or in a layer below. LAYERS OF Isolation
  4. No way to understand what the code is about Domain

    logic is sca!ered throughout the layers Hard to understand where domain logic is Layers encourage horizontal coupling DDD do not work on partitioned architecture Many uncategorized components
  5. Your architectures should tell readers about the system, not about

    the frameworks you used in your system. SCREAMING ARCHITECTURE https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html Screaming Architecture, Robert C. Martin
  6. Web Domain Persistence Architecture sinkhole anti-pa!ern The fast lane reader

    anti-pa!ern You have to be self-disciplined Domain logic sca!ered throughout the layers Database/state drives the design Uncategorized helper and utility classes Monolith in nature Changing existing code instead of adding new Hard to change over time When it grows, it’s hard to test Open for hacking your own code Documentation is critical The Inconvenient truth
  7. Dependencies are out of control Business and infra logic mixed

    Lack of testing, hard to maintain Information is duplicated or global Any change triggers a ripple effect Big ball of mud defined in a paper released in 1997 by Brian Foote and Joseph Yoder “A Big Ball of Mud is a haphazardly structured, sprawling, sloppy, duct-tape-and-baling-wire, spaghetti-code jungle.”
  8. Spaghetti code Multiple app entry points High cyclomatic complexity Too

    complex to maintain High coupling, low cohesion Lack of testing, hard to debug
  9. Order, Account, Image Product, Restaurant, Matching Payment, Scheduler, Invoice Messaging,

    Balance, Location and new integrations to Ka#a, Redis, MongoDB, etc. Add new flows & Features
  10. Requests pass-through between each layers Changes cause the ripple effect

    Data mapped objects again and again Lasagna/Baklava code A layered architecture becomes a lasagna when you push yourself obey architectural standards. Better than spagetti, but code smells continue.
  11. we build monoliths "A monolith is an application with an

    over-engineered micro and macro design but a completely under-engineered architecture" Sandro Mancuso, from his talk "a case for outside-in design"
  12. ravioli code Hands on Game Development Patterns with Unity 2019,

    David Baron Ravioli code is the result of overzealous encapsulation and an architecture that's divided into too many individual classes. Bit size, independent components seems good but over-use can cause over-engineered, not understandable, unreadable so$ware. "Everything should be made as simple as possible, but not simpler" - Albert Einstein
  13. Robert C. Martin Author of Clean Code and Clean Coder

    Owner of cleancoders.com training site If your so$ware is ge!ing harder and harder to develop, you are doing something wrong https://twitter.com/unclebobmartin/status/555013005751377920
  14. If your so$ware is ge!ing harder and harder to develop,

    you are doing something wrong https://twitter.com/mob__mentality/status/1273982958831980546 partitioning,
  15. If your so$ware is ge!ing harder and harder to develop,

    you are doing something wrong https://twitter.com/AjeyGore/status/1266402718140137473
  16. If your so$ware is ge!ing harder and harder to develop,

    you are doing something wrong https://twitter.com/davefarley77/status/1266846897093967874
  17. If your so$ware is ge!ing harder and harder to develop,

    you are doing something wrong a so!ware system must be decomposed into parts that overlap in functionality as li"le as possible. SEPARATION OF CONCERNS make sure to not mix different dimensions, concepts together a set of information that affects the code of a computer program PRINCIPLE
  18. If your so$ware is ge!ing harder and harder to develop,

    you are doing something wrong Edsger W. Dijkstra coined the term to describe the mentality behind modularization, which allows the programmer to reduce the complexity of the system being designed. SEPARATION OF CONCERNS PRINCIPLE
  19. COUPLING COHESION the strength of independence connections between classes/modules sense

    of belonging together how we keep code on a unified purpose SEPARATION OF CONCERNS the main goal of design principles is to improve the separation of concerns PRINCIPLE
  20. HIGH COUPLING dependent to frameworks & technologies components leak implementation

    details hacking code to add new features changing code starts riddle effect hard to refactor LOW COHESION new features require many places to work sca"ered knowledge cause complex tests hard to understand the whole design blurring responsibilities, long methods hard to reuse SEPARATION OF CONCERNS PRINCIPLE
  21. SEPARATION OF CONCERNS INFORMATION HIDING INVERSION OF CONTROL DEPENDENCY INJECTION

    DEPENDENCY INVERSION COUPLING COHESION wiring direction shape isolation responsibility dependency THE MODULARITY MINDSET PRINCIPLE PRINCIPLE PATTERN PRINCIPLE
  22. INFORMATION HIDING DECOUPLING CONCERNS BY hiding the area of complexity

    (i.e implementation details and design decisions) from the rest of the so!ware system through interfaces and private constraints PRINCIPLE
  23. INVERSION OF CONTROL refers to additional responsibilities a class can

    have, other than its main responsibility, like object creation, dependency binding and application flow THE HOLYWOOD PRINCIPLE: DON’T CALL US, WE’LL CALL YOU! PRINCIPLE
  24. instead of driving the car by yourself you call a

    taxi and taxi driver drives the car delegate control to someone else who will drive the flow PRINCIPLE INVERSION OF CONTROL THE HOLYWOOD PRINCIPLE: DON’T CALL US, WE’LL CALL YOU!
  25. INVERSION OF CONTROL Separate WHAT-TO-DO part from WHEN-TO-DO part implementation

    event-handlers interfaces event triggers THE HOLYWOOD PRINCIPLE: DON’T CALL US, WE’LL CALL YOU! dependency injection pa"ern observer pa"ern strategy pa"ern callback pa"ern Make someone DRIVES THE FLOW PRINCIPLE
  26. DEPENDENCY INJECTION decouples the creation of an object from its

    use configuration, construction of an object, i.e. the creation of the object and handling the dependencies of that object objects should not be responsible for looking up the resources or collaborators on which they depend. IoC container does it for the objects. can be implemented by constructor injection, se"er injection or method injection subtype of IoC, focusing on one aspect: component assembly PATTERN
  27. abstractions should not depend on details details should depend on

    abstractions DEPENDENCY INVERSION PRINCIPLE high-level modules should not depend on low-level modules both should depend on abstractions business code integration code interfaces implementation we don't care how the behavior is implemented and which implementation will be used The D of SOLID Principles MAKE THE BUSINESS INDEPENDENT OF EXTERNAL SYSTEMS
  28. PRINCIPLE cache interface cache implementation business object uses domain, business

    code code we really care about changes o!en integrations, infra code write once and forget hard to change abstractions should not depend on details details should depend on abstractions DEPENDENCY INVERSION high-level modules should not depend on low-level modules both should depend on abstractions HIGH LEVEL MODULE LOW LEVEL MODULE
  29. PRINCIPLE cache interface cache implementation business object uses domain, business

    code code we really care about changes o!en integrations, infra code write once and forget hard to change abstractions should not depend on details details should depend on abstractions DEPENDENCY INVERSION high-level modules should not depend on low-level modules both should depend on abstractions HIGH LEVEL MODULE LOW LEVEL MODULE safe for refactoring safe for refactoring
  30. cache interface cache implementation business object uses repository interface repository

    implementation business object uses redis POSTGRES payment interface payment implementation business object
  31. cache interface cache implementation business object uses repository interface repository

    implementation business object uses redis POSTGRES payment interface payment implementation business object business object queue interface queue implementation RABBITMQ
  32. cache interface cache implementation business object uses repository interface repository

    implementation business object uses redis POSTGRES payment interface payment implementation business object business object queue interface queue implementation RABBITMQ business object business object business object rest controller soap controller command-line controller uses uses uses REQUEST REQUEST REQUEST
  33. cache interface cache implementation business object uses repository interface repository

    implementation business object uses redis POSTGRES payment interface payment implementation business object business object queue interface queue implementation RABBITMQ business object business object business object rest controller soap controller command-line controller uses uses uses REQUEST REQUEST REQUEST infra domain application
  34. cache interface cache implementation business object uses repository interface repository

    implementation business object uses redis POSTGRES payment interface payment implementation business object business object queue interface queue implementation RABBITMQ business object business object business object rest controller soap controller command-line controller uses uses uses REQUEST REQUEST REQUEST HEXAGONAL ARCHTECTURE Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases. - Alistair Cockburn, 2005
  35. cache interface cache implementation business object uses repository interface repository

    implementation business object uses redis POSTGRES payment interface payment implementation business object business object queue interface queue implementation RABBITMQ business object business object business object rest controller soap controller command-line controller uses uses uses REQUEST REQUEST REQUEST HEXAGONAL ARCHTECTURE puts the domain center of architecture inverts dependencies towards domain code design driven by business needs ENABLER OF DDD: