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

SOLID Is Dead, Long Live SOLID

SOLID Is Dead, Long Live SOLID

Lemi Orhan Ergin

November 26, 2023
Tweet

More Decks by Lemi Orhan Ergin

Other Decks in Technology

Transcript

  1. SOLID DEAD
    IS
    SOLID
    LONG
    LIVE
    LEMİ ORHAN ERGİN co-founder, craftgate
    THE NEW PERSPECTIVE
    THE OLD LEGACY

    View full-size slide

  2. I know SOLID
    principles
    Really?
    How you
    apply?
    S for Single
    responsibility.
    I forgot the
    others.
    Of course we know SOLID. We think we use it all the
    time while coding and during code reviews. And of
    course it is a good thing. I've never heard the opposite.
    EVERYONE KNOWS SOLID PRINCIPLES, KNOWS THEM WELL!

    View full-size slide

  3. Preexisting knowledge impedes one’s
    ability to reach an optimal solution
    Every a
    tt
    empt referring to past
    solutions adds a new bracket to the
    wall of illusion of competence
    Agile, Devops, Clean Coding, SOLID, else?
    THE EINSTELLUNG EFFECT
    means mindset, attitude
    you past experience gives strong opinion about what it really is
    WE ALREADY KNOW IT, WHY BOTHERS?
    you never doubt the truth of what you know

    View full-size slide

  4. UNLEARN
    forget what you already know
    try to look from other perspectives
    re-learn from different views
    WHAT IF ALL WE KNOW IS WRONG, OR INCOMPLETE, OR MISSING
    years can change how things look, like how paintings change.
    real mona lisa seems different, isn’t it ?

    View full-size slide

  5. GROWS
    SOFTWARE
    HOW
    LET’S START FROM A NEW PERSPECTIVE!

    View full-size slide

  6. Payment API
    after a payment are completed,
    we save the data to database
    every design starts with
    the simpliest solution
    IMPLEMENT PAYMENT OPERATIONS 1
    Save payment
    Retrieve payment
    GROWS
    SOFTWARE
    HOW
    DB

    View full-size slide

  7. Payment API
    We need to search existing payments
    FEATURE
    REQUEST
    where do we need to add the search operation ?
    It is a payment operation, so add it to same service ?
    Save payment
    Retrieve payment
    DB

    View full-size slide

  8. Payment API
    it’s a simple as querying the database
    with a search criteria and returning the results
    we add it to payment component as
    a new responsibility, a new flow
    2
    ADD SEARCH TO EXISTING FLOW
    Save payment
    Retrieve payment
    Search payment
    start with the simplest solution
    DB

    View full-size slide

  9. Payment API
    Search service requires additional models, introduces new dependencies and differentiates
    from core payment flow
    payment service starts to be huge and unmaintainable
    (new dependencies for search operation are not
    used and relevant with core payment flow)
    search flow has different business needs
    and triggered by different roles
    a change in the repository for search improvements
    directly triggers change in core payment flow
    Save payment
    Retrieve payment
    Search payment
    DB

    View full-size slide

  10. Payment API
    separate the search db operation from other db
    operations
    SPLIT INTO BOUNDED CONTEXTS 3
    Save payment
    Retrieve payment
    Search payment
    two bounded contexts
    DB

    View full-size slide

  11. Search results are expected to be returned as files in csv and excel formats
    FEATURE
    REQUEST
    Payment API
    Save payment
    Retrieve payment
    Search payment
    DB

    View full-size slide

  12. Payment API
    generate report simply searches the data and
    fills it in a file with the given extension
    ADD NEW FLOW TO SEARCH MODULE 4
    Save payment
    Retrieve payment
    Search payment
    Generate report
    we put generate report to
    the context of search
    DB

    View full-size slide

  13. Payment API
    Improvements in report generation triggers deployments on search, which is used excessively
    deploying the whole api is required whenever something
    added to report logic, that increases the risc on payment
    Save payment
    Retrieve payment
    Search payment
    Generate report
    DB
    the user of report generation is different than
    the users of payment and search operations

    View full-size slide

  14. Payment API Report API
    it’s time to introduce a new reporting api
    with generate report capabilities
    MOVE TO A NEW MICRO SERVICE 5
    Save payment
    Retrieve payment
    Generate report
    Search payment
    DB

    View full-size slide

  15. Report generation takes time and users wait too long, timeout errors start to occur
    Payment API Report API
    things go even worse when multiple users
    trigger reports at the same time
    Save payment
    Retrieve payment
    Generate report
    Search payment
    DB

    View full-size slide

  16. Payment API Report API
    QUEUE
    each demand is queued,
    the throttlling logic can
    be managed
    Save payment
    Retrieve payment
    Generate report
    Search payment
    Demand report
    QUEUE DEMANDS AND PROCESS 6
    two bounded contexts
    DB

    View full-size slide

  17. Payment API Report API
    QUEUE
    Report generation affects performance of search operations
    since the data source is shared, the load of reporting
    api has direct impact on payment operations
    Generate report
    Demand report
    Save payment
    Retrieve payment
    Search payment
    DB

    View full-size slide

  18. Payment API Report API
    QUEUE
    ELASTIC
    separate the read model of
    report generation from the
    model of payment operations
    Generate report
    Demand report
    Save payment
    Retrieve payment
    Search payment
    SEPARATE THE DATASOURCE 7
    DB

    View full-size slide

  19. Payment API Report API
    ELASTIC
    Inform the user when the report is generated
    FEATURE
    REQUEST
    Save payment
    Retrieve payment
    Search payment
    QUEUE
    Generate report
    Demand report
    Report API
    DB

    View full-size slide

  20. Payment API
    ELASTIC
    Notification API
    email
    notification api directly sends
    emails and slack messages
    that provided by the report api
    INTRODUCE NOTIFICATION SERVICE 8
    Save payment
    Retrieve payment
    Search payment
    Report API
    QUEUE
    Generate report
    Demand report
    Report API
    Send Slack message
    Send email
    DB

    View full-size slide

  21. Payment API
    ELASTIC
    Notification API
    email
    Report needs to know notification api and how to trigger its functionalities
    If notification api stops
    working, we lose messages
    Save payment
    Retrieve payment
    Search payment
    Report API
    QUEUE
    Generate report
    Demand report
    Report API
    Send Slack message
    Send email
    DB

    View full-size slide

  22. Payment API
    ELASTIC
    email
    QUEUE
    keep messages in queue and manage
    the error logic with retries
    QUEUE NOTIFICATION MESSAGES 9
    Save payment
    Retrieve payment
    Search payment
    Report API
    QUEUE
    Generate report
    Demand report
    Report API Notification API
    Send Slack message
    Send email
    DB

    View full-size slide

  23. Payment API
    ELASTIC
    email
    QUEUE
    Whenever queue stops responding, the whole flow stops and messages are lost
    we lose messages when the queue is
    down :(
    Save payment
    Retrieve payment
    Search payment
    Report API
    QUEUE
    Generate report
    Demand report
    Report API Notification API
    Send Slack message
    Send email
    we lose demands when
    the queue is down :(
    DB

    View full-size slide

  24. Payment API
    ELASTIC
    email
    Outbox
    Inbox
    make messaging transactional and
    be sure you create messages
    MAKE MESSAGING TRANSACTIONAL 10
    Save payment
    Retrieve payment
    Search payment
    Report API
    Generate report
    Demand report
    Report API Notification API
    Send Slack message
    Send email
    Generate
    report
    Send
    notification
    DB

    View full-size slide

  25. Payment API
    ELASTIC
    email
    Outbox
    Inbox
    We design a kind-a maintainable, expandable, robust system at the end
    make messaging transactional and
    be sure you create messages
    Save payment
    Retrieve payment
    Search payment
    Report API
    Generate report
    Demand report
    Report API Notification API
    Send Slack message
    Send email
    DB
    Generate
    report
    Send
    notification

    View full-size slide

  26. Extract to method, to classes, to functions
    Centralize decision making (behavior)
    Make responsible of one behavior
    Apply design patters
    Clearify boundaries of contexts
    Extract functionality as a new microservice
    Seperate by behaviors, not models or packages
    Avoid layered arc, build with hexagonal arch
    Avoid wrappers around CRUD operations
    Do not depend on same datasource
    Avoid distributed monoliths
    Avoid centralized common modules
    Do not depend on implementations
    Let the control of flow inverted (IoC)
    Prefer duplication to make independent
    Introduce abstrations to eliminate down times
    WE MANAGED
    COMPLEXITY
    BY DECREASING
    COUPLING AND
    INCREASING
    COHESION WHILE
    REFACTORING
    AND ADDING
    NEW CODE

    View full-size slide

  27. https://twitter.com/KentBeck/status/10668695983
    THE LAWS OF PHYSICS OF
    SOFTWARE DESIGN

    View full-size slide

  28. COUPLING
    In highly coupled systems, one change
    triggers a change in somewhere else
    The measure of the strength of
    interconnection, measure of independence
    If one system waits, changes, works, fails,
    starts, stops due to another systems action,
    these systems are highly coupled
    with the butterfly effect, every change
    thiggers something bigger
    Controller
    Service Service Service
    Repository Repository
    Utility
    Rest
    Client

    View full-size slide

  29. COHESION
    The code that changes together (i.e. in the
    same feature), stays together (only coupled
    to each other)
    Belonging together, relatedness, sharing
    same purpose/responsibility
    Cohesiveness exists inside boundaries, that
    makes it a module, a component, an
    element, a team, an organization

    View full-size slide

  30. Coupling & Cohesion perfectly fit to many
    other levels of abstractions of the world
    ONE TEAM
    TEAM A
    TEAM B
    when do we decide to
    split a team / an api /
    a module into two ?
    like team topologies

    View full-size slide

  31. EPENDENCY INVERSION PRINCIPLE
    INGLE RESPONSIBILITY PRINCIPLE
    PEN-CLOSED PRINCIPLE
    ISKOV SUBSTITUTION PRINCIPLE
    NTERFACE SEGREGATION PRINCIPLE
    S
    O
    L
    I
    D

    View full-size slide

  32. Solid is not about good or simple design, it's about be
    tt
    er design.
    Solid is not about understanding OOP be
    tt
    er, it is about
    understanding the code (i.e. the design) be
    tt
    er.
    Solid is not the goal, it is a guideline for evaluating the way you
    refactor so
    ft
    ware into a be
    tt
    er design.
    IS NOT ABOUT...
    SOLID

    View full-size slide

  33. IS ABOUT MANAGING COMPLEXITY
    BY TAKING THE CONTROL OF COST BY
    COUPLING & COHESION
    SOLID
    SOLID is about limiting the impact of change
    by making easy to change
    the cost of change is the
    cost of software
    the impact of dependencies
    on easiness of change
    CODE
    PLANS
    PRIORITIES
    DECISIONS
    TEAMS
    APIS/SERVICES
    INFRASTRUCTURE

    View full-size slide

  34. is it about not
    writing too much
    code in one place ?
    SINGLE RESPONSIBILITY PRINCIPLE
    SRP

    View full-size slide

  35. SINGLE RESPONSIBILITY PRINCIPLE
    A class should only have a one single responsibility.
    There should never be more than one reason to change.
    A component should do only one thing, and do it right.
    This principle is about people.
    WHAT WE HAVE LEARNED SO FAR
    SRP

    View full-size slide

  36. SINGLE RESPONSIBILITY PRINCIPLE
    what is responsibility ?
    from what perspective ?
    many small classes ?
    you mean "high cohesion" ?
    what about fixing bugs
    and adding features ?
    what about cross cutting concerns ?
    converters ? facades ? patterns ?
    that's not always true
    A class should only have a one single responsibility.
    There should never be more than one reason to change.
    A component should do only one thing, and do it right.
    This principle is about people.
    multi layered architecture
    is not about SRP
    Programmers stated that needs clarifications
    WHAT WE HAVE LEARNED SO FAR SHOULD BE CHALLENGED
    SRP

    View full-size slide

  37. SEPARATED CONCERN PRINCIPLE
    SRP is all about separation of concerns & contexts and
    increasing cohesion in an optimum level.
    A component should belong to one concern based on business
    responsibilities. Without context, every module can violate SPR
    to some extend.
    There is no such a thing as "do one thing” or “single”. There exists
    di
    ff
    erent levels of abstractions.
    It triggers how we split things into pieces.
    PRODUCT TEAMS
    FINE-GRAINED TASKS
    TEAM TOPOLOGIES
    BOUNDED CONTEXTS
    ENCAPSULATION
    INFIRMATION HIDING
    COGNITIVE FIT
    AGGREGATES
    MICROSERVICES
    SINGLE RESPONSIBILITY PRINCIPLE
    SRP
    keep cohesion as high as possible

    View full-size slide

  38. is it about small
    interfaces on top
    of huge codebase ?
    INTERFACE SEGREGATION PRINCIPLE
    ISP

    View full-size slide

  39. Clients should not be forced to depend on methods they do not use.
    Many client specific interfaces are be
    tt
    er than one general purpose
    interface.
    Interfaces should be small.
    INTERFACE SEGREGATION PRINCIPLE
    ISP
    WHAT WE HAVE LEARNED SO FAR

    View full-size slide

  40. Clients should not be forced to depend on methods they do not use.
    Many client specific interfaces are be
    tt
    er than one general purpose
    interface.
    Interfaces should be small.
    Programmers stated that needs clarifications
    is having interfaces a must ?
    should every class have an interface ?
    interface soup ?
    single method interfaces ?
    then aggregate again ?
    INTERFACE SEGREGATION PRINCIPLE
    WHAT WE HAVE LEARNED SO FAR SHOULD BE CHALLENGED
    ISP
    WHAT WE HAVE LEARNED SO FAR SHOULD BE CHALLENGED

    View full-size slide

  41. Limit coupling surface, minimize number of methods in
    the contract, limiting points to communicate.
    Keep abstractions highly cohesive so that users don’t end
    up depending on things they don’t need.
    Avoid depending on things that you do not use.
    INTERFACE SEGREGATION PRINCIPLE
    GATEWAY
    INFO HIDING
    ISOLATION
    COMPOSITION
    LIMITED CONTACT SURFACE PRINCIPLE
    ISP
    LIMIT DEPENDENCIES
    RICH DOMAIN MODEL
    lower the number
    the touching points
    of coupling

    View full-size slide

  42. is it about
    subtypes that
    I've never used ?
    LISKOV SUBSTITUTION PRINCIPLE
    LSP

    View full-size slide

  43. LISKOV SUBSTITUTION PRINCIPLE
    LSP
    If an object y has all the properties of object x, then we can safely use
    y anywhere we use x and that y is a subtype of x. If y does not have
    all the properties of x, it is not a subtype of x.
    Every derived class should be substitutable for their base class.
    WHAT WE HAVE LEARNED SO FAR

    View full-size slide

  44. If an object y has all the properties of object x, then we can safely use
    y anywhere we use x and that y is a subtype of x. If y does not have
    all the properties of x, it is not a subtype of x.
    Every derived class should be substitutable for their base class.
    isn't it all OOP related ?
    what if we do not use
    subtypes at all ?
    Programmers stated that needs clarifications
    LISKOV SUBSTITUTION PRINCIPLE
    LSP
    is inheritance a must ?
    WHAT WE HAVE LEARNED SO FAR SHOULD BE CHALLENGED
    WHAT WE HAVE LEARNED SO FAR SHOULD BE CHALLENGED

    View full-size slide

  45. A class/module/team should do what it sounds like it does.
    Any behavioral change breaking this that should be a
    di
    ff
    erent dependency.
    LSP is not about inheritance, it is about behaviour of code
    units.
    Build so
    ft
    ware systems from interchangeable parts, those
    parts must adhere to a contract that allows those parts to be
    substituted one for another.
    LISKOV SUBSTITUTION PRINCIPLE
    LSP
    GATEWAY
    INFO HIDING
    ISOLATION
    COMPOSITION
    TEST DOUBLES
    INTER-CHANGEABLE DEPENDENCIES
    PRINCIPLE
    prefer un-fixed dependencies

    View full-size slide

  46. is it dependency
    injection
    in reality ?
    DEPENDENCY INVERSION PRINCIPLE
    DIP

    View full-size slide

  47. DEPENDENCY INVERSION PRINCIPLE
    DIP
    High-level modules should not depend on low-level modules.
    from code that
    is stable
    separate code that
    changes frequently
    business code
    domain logic
    integration code
    client specific code
    framework dependent code
    delay technological decisions
    immune to technical evolution
    test domain in isolation
    knows about
    needs
    WHAT WE HAVE LEARNED SO FAR

    View full-size slide

  48. DEPENDENCY INVERSION PRINCIPLE
    DIP
    Abstractions should not depend on details.
    Details should depend on abstractions.
    interfaces
    ports
    implementations
    adapters
    the depending class has no knowledge about
    the concrete class that it is going to use
    WHAT WE HAVE LEARNED SO FAR

    View full-size slide

  49. DEPENDENCY INVERSION PRINCIPLE
    DIP
    High-level modules should not depend on low-level modules.
    Abstractions should not depend on details
    Details should depend on abstractions.
    WHAT WE HAVE LEARNED SO FAR SHOULD BE CHALLENGED
    WHAT WE HAVE LEARNED SO FAR SHOULD BE CHALLENGED
    Programmers stated that needs clarifications
    where is the inversion ? isn’t it too abstract ?
    concrete classes are depent on
    interfaces in nature, so what ?

    View full-size slide

  50. DIP is about making the business independent of external systems by
    making coupling cheap and so
    ft
    .
    Decouple your behavioral models from your data models.
    DIP decouples the construction of an object from its use.
    DEPENDENCY INVERSION PRINCIPLE
    DIP
    PORTS & ADAPTERS
    HOLLYWOOD PRINCIPLE
    EVENT DRIVEN DESIGN
    INVERSION OF CONTROL
    SELF ORGANIZATION
    MODULAR DESIGN
    PLUGINS & ADD-ONS
    soften the impact of coupling
    and improve cohesiveness
    DECOUPLED DEPENDENCIES PRINCIPLE

    View full-size slide

  51. OPEN CLOSED PRINCIPLE
    OCP
    am I not allowed
    to change existing
    code anymore ?

    View full-size slide

  52. OPEN CLOSED PRINCIPLE
    OCP
    So
    ft
    ware entities should be open for extension, but closed for modification.
    Developers must support new functionality without editing the source code
    of the existing modules.
    The source code of such a [class] is inviolate. No one is allowed to make
    source code changes to it.
    You can use interfaces as extension points to make your code truly
    adaptable.
    WHAT WE HAVE LEARNED SO FAR

    View full-size slide

  53. OPEN CLOSED PRINCIPLE
    OCP
    So
    ft
    ware entities should be open for extension, but closed for modification.
    Developers must support new functionality without editing the source code
    of the existing modules.
    The source code of such a [class] is inviolate. No one is allowed to make
    source code changes to it.
    You can use interfaces as extension points to make your code truly
    adaptable.
    Programmers stated that needs clarifications
    source code can’t be changed ?
    who can write perfect code ?
    abuse of inheritance ?
    change requires refactoring
    WHAT WE HAVE LEARNED SO FAR SHOULD BE CHALLENGED
    WHAT WE HAVE LEARNED SO FAR SHOULD BE CHALLENGED

    View full-size slide

  54. Expose potential extension points.
    For protection against change to the
    existing code, identify points of
    evolution points, create
    a stable interface around them.
    We need just enough adaptability.
    You should be explicit in what you
    allow and disallow to be extended.
    PROTECTED
    VARIATION
    PRINCIPLE
    ROOT OF ALL PATTERNS
    OPEN CLOSED PRINCIPLE
    OCP
    information hiding, PV and OCP are all
    same principle with a different name and view
    PROTECTED VARIATION PRINCIPLE
    manage the growth
    of codebase by adding
    coupling in control
    EVOLUTIONARY DESIGN
    TEAM STANDARDS
    CONTINUOUS REFACTORING
    CONWAY’S LAW

    View full-size slide

  55. SRP
    Separated
    Concerns
    keep cohesion as
    high as possible
    ISP
    Limited
    Contact Surface
    lower the number
    the touching points
    of coupling
    prefer un-fixed
    dependencies
    Interchangeable
    Dependencies
    LSP
    DIP manage the growth of
    codebase by adding
    coupling in control
    Decoupled
    Dependencies
    OCP
    Protected
    Variation
    so
    ft
    en the impact of coupling
    and improve cohesiveness
    Cohesion Coupling
    SOLID PRINCIPLES

    View full-size slide

  56. One-Stop-Shop
    Payment Orchestration
    [email protected]
    we are hiring!
    co-founder, craftgate
    https://speakerdeck.com/lemiorhan
    LEMİ ORHAN ERGİN

    View full-size slide