Git Product home page Git Product logo

solid_notes_about_solid's Introduction

Design principles: SOLID

Personal digest of Clean Architecture: A Craftsman's Guide to Software Structure and Design by Robert C. Martin (2017), Design Principles and Design Patterns by Robert C. Martin (2000) & else around the internet about SOLID principles.

Content

  1. 1st: Symptoms of rotting design - poor architecture
  2. 2nd: Causes to rot
  3. 3rd: Solution - Principles of Object Oriented Class Design
    3.1 What is SOLID
    3.2 Goal of SOLID
    3.3 SRP - Single Responsibility Principle
    3.4 OCP - Open-Closed Principle
    3.5 LSP - Liskov Substitution Principle
    3.6 ISP - Interface Segregation Principle
    3.7 DIP - Dependency Inversion Principle
  4. Concepts 💡
  5. Links

🚩 Rigidity (stiffness, fixed)
When easy change causes cascade of changes in dependent modules. If manager’s start to fear to fix problems or refuse to allow changes - design deficiency becomes an adverse management policy.
🚩 Fragility
Breaks everytime changed. Impossible to maintain & probability of breakage increases with time.
🚩 Immobility
Inability to reuse. Module has too much baggage it depends upon. Safer is to rewrite than reuse.
🚩 Viscosity (swamp)
Easy to do the wrong thing, hard to do the right thing. Viscosity of environment - long compiles, source code control system requires a long time to check-in - engineers' temptation to todo as few check-in’s as possible/make changes that don’t force large recompiles.

  • Changing requirements - initial design left behind - design not resilient to changes.
  • New unplanned dependencies between modules of software. Need of ependency management - creation of dependency firewalls.

The SOLID principles - principles, that tell us how to arrange our functions and data structures into classes, and how those classes should be interconnected.

The goal of the principles is the creation of mid-level💡 software structures that:

  1. Tolerate change
  2. Are easy to understand
  3. Make components to be reused in many software systems

There should never be more than one reason for a class to change.

or

Each software module should have one and only one reason to change.

or

A module should be responsible to one, and only one, actor.

What SRP is NOT:

“A function should do one, and only one, thing.” - it’s a refactoring principle, to refactor large functions into smaller functions; we use it at the lowest levels. But it’s NOT the SRP.

What SRP IS:

  • SRP is the reason we separate concerns.
  • Gather together the things that change for the same reasons. Separate those things that change for different reasons.
  • We want to increase the cohesion💡 between things that change for the same reasons, and we want to decrease the coupling💡 between those things that change for different reasons.
  • An active corollary to Conway’s law💡: The best structure for a software system is heavily influenced by the social structure of the organization that uses it so that each software module has one, and only one, reason to change.

What is the reason to change?

  • When you write a software module, you want to make sure that when changes are requested, those changes can only originate from a single person, or rather, a single tightly coupled group of people representing a single narrowly defined business function. You want to isolate your modules from the complexities of the organization as a whole, and design your systems such that each module is responsible (responds to) the needs of just that one business function.

Symptoms of SRP violation

  1. Accidental duplication. These problems occur because we put code that different actors depend on into close proximity. The SRP says to separate the code that different actors depend on.

  2. Merges. Multiple people changing the same source file for different reasons. To avoid this problem is to separate code that supports different actors. Solution - move the functions into different classes.

SRP appears at two different levels:

A module should be open for extension but closed for modification.

Main idea

Software must be designed to allow the behavior of it to be changed by adding new code, rather than changing existing code.

Goal of OCP

To make the system easy to extend without incurring a high impact of change. Modules are extensible without being changed, ability to add new features without changing existing code.

If simple extensions to the requirements force massive changes to the software, then the architects of that software system have engaged in a spectacular failure.

Take in account

  • Directional control (make sure that the dependencies between the components pointed in the correct direction)
  • Information hiding (protect from knowing too much)

Technique: Abstraction.
Solutions:

Solution Description
Dynamic polymorphism Run time. Overriding, virtual functions (depending on interfaces, new types get new class, no main function that handles types with switch…case, no modification when adding new type)
Static polymorphism Compile time. Overloading (templates or generics)

Here is an illustration on how using Open-Closed Principle looks like when adding new feature:

Subclasses should be substitutable for their base classes.

or

Methods that use references to base classes must be able to use objects of derived classes without knowing it.

About LSP

Substitutable - capable of being exchanged. Users of a base class should continue to function properly if a derivative of that base class is passed to it. Violations of LSP are latent (hidden) violations of OCP. Repercussions (unintended consequences) of LSP violation can be using if/else statements as a fix for such violations.

Contracts

Contract Description
Implicit contract Set of rules or constraints that a subclass must adhere to in order to be used as a substitute for its superclass. This contract is implicit because it is not explicitly defined, but rather is implied by the behavior of the superclass and the relationship between the subclass and superclass.
Explicit contract Set of rules or constraints that a subclass must adhere to in order to be used as a substitute for its superclass. These rules or constraints are explicitly defined in the code, documentation, or other forms of communication. This allows other developers to understand how to use the subclass and what behavior to expect from it. By adhering to an explicit contract, the subclass can be used in place of the superclass without causing any unexpected behavior or errors in the code.

To build software from interchangeable parts, those parts must adhere to a contract that allows those parts to be substituted one for another.

Solutions:

  1. Design by contract (contract of the base class must be honored by the derived class)
  2. Derived class is substitutable (capable of being exchanged) for its base class if:
    • Its preconditions (declarations that are true before the method is called) are no stronger than the base class method.
    • Its postconditions (declarations what method guarantees will be true once its completed) are no weaker than the base class method.
  3. Derived methods should expect no more and provide no less.

Many client specific interfaces are better than one general purpose interface.

Technique:

  • If you have a class that has several clients, rather than loading the class with all the methods that the clients need, create specific interfaces for each client and multiply inherit them into the class.
  • Without ISP components and classes would be much less useful and portable.
  • Avoid depending on things that you don’t use.

Solutions:

Solution Description
Client Specific Categorizing clients by their type, and interfaces for each type of client should be created. If two or more different client types need the same method, the method should be added to both of their interfaces.
Changing Interfaces Clients of the old interface that wish to access methods of the new interface, can query the object for that interface (but do not overdo it).

Depend upon Abstractions. Do not depend upon concretions.

About DIP

It’s a strategy of depending upon interfaces or abstract functions & classes, rather than upon concrete functions & classes.

Problem

Procedural architecture - dependency structure - like hierarchy in organisation management. High level modules deal with the high level policies of application. High level modules directly depend on implementation modules.

Practices

  • Don’t refer to volatile concrete classes. Don’t refer to volatile concrete classes.
  • Don’t derive from volatile concrete classes
  • Don’t override concrete functions. Concrete functions often require source code dependencies. When you override those functions, you do not eliminate those dependencies—indeed, you inherit them. To manage those dependencies, you should make the function abstract and create multiple implementations.
  • Never mention the name of anything concrete and volatile

Solution: Object-oriented architecture

  1. Dependencies point towards abstractions
  2. Dependencies are inverted (upside-down)
  3. Modules with implementation are not depended upon (main modules -> mid modules -> detail) but depend themselves upon abstractions (high level -> abstraction <- detail)
  4. Depending upon abstractions - every dependency in design should target an interface, or an abstract class. No dependency should target a concrete class.
  5. Abstractions are “hinge points”, they represent the places where the design can bend or be extended, without themselves being modified (OCP).
  6. Abstract factory

Motivation

  • Concrete things change a lot, abstract - less frequently.
  • DIP prevents from depending upon volatile (nepastovių) modules.
  • Anything concrete is volatile (exceptions in early development)
  • Non-volatility is not a replacement for the substitutability of an abstract interface. Consistency < interface.
  • Concrete class design creates instances -> littering architecture with dependencies upon abstract classes.

💡 Mid-level
Principles are applied by programmers working at the module level. Applied just above the level of the code and help to define the kinds of software structures used within modules and components.

💡 Conway’s law
An adage that states organizations design systems that mirror their own communication structure. It’s an observation that the architectures of software systems look remarkably similar to the organization of the development team that built it.

💡 Cohesion (bond)
The degree to which the elements inside a module belong together. In one sense, it is a measure of the strength of relationship between the methods and data of a class and some unifying purpose or concept served by that class. The force that binds together the code responsible to a single actor.

💡 Coupling
Degree of interdependence between software modules.

💡 Axis of Change
An idea that changes in a system tend to occur around the axis of a class's responsibility. When a change is needed, it's likely to be in the area of a class's responsibility. By having each class focus on a single responsibility, it becomes easier to manage changes because they are likely to be localized to specific classes.

  1. Clean Architecture: A Craftsman's Guide to Software Structure and Design by Robert C. Martin
  2. Design Principles and Design Patterns by Robert C. Martin (2000)
  3. Wikipedia about Cohesion
  4. Wikipedia about Coupling
  5. Wikipedia about Conway's Law
  6. Conway's Law by Martin Fowler
  7. Common Closure Principle
  8. Common Closure Principle: The story of an evolving architecture
  9. SOLID Principles Swift

solid_notes_about_solid's People

Contributors

rusenaite avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Forkers

xpepper

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.