TechWriterDev
  • Cloud
    • AWS
      • 00_Doubts
      • CloudPractitioner
        • Cloud Computing
        • AWS Global Infrastructure
        • Introduction to AWS EC2
        • Elastic load balancer(ELB)
        • 04_Messaging_Queuing
        • Aditional Computing Service
        • Accessing AWS resources
        • AWS Networking
        • Storage
        • Amazon Database Solutions
        • Monitoring Tools
        • AWS Security
        • Distributed Denial Of Service Attacks
      • DeveloperAssociate
        • References
        • AWS DVA-C02 Services Index
        • Services
          • 00_IAM
            • Identity and Access Management (IAM)
            • Account Protection Mechanisms
            • Access Mechanism of AWS Resources
            • Security Tools
            • Responsibility Model
            • Advanced Concepts
          • 01_EC2
            • Elastic Compute Cloud (EC2)
            • EC2 Volume Types
            • Amazon Machine Image (AMI)
            • AWS charges for IPv4 address
          • 02_SecurityGroups
            • Security Groups
          • 03_Elastic_LoadBalancing
            • Terminology
            • Elastic load balancer
            • Features
            • Basics
          • 04_AutoScaling
            • Auto Scaling
          • 05_RDS
            • Relational Database Service (RDS)
            • Aurora
            • Security
            • RDS Proxy
          • 06_ElastiCache
            • Cache
            • Cache Offerings
          • 07_Route53
            • Basics of DNS
            • Route 53
          • 08_VPC
            • Virtual Private Cloud (VPC)
          • 09_S3
            • Simple Storage Service (S3)
            • S3 Features
            • S3 Encryption
            • S3 Features
            • S3 Bucket Policy and IAM Policy
          • 10_ECS
            • Elastic Container Service (ECS)
            • Elastic Container Registry (ECR)
            • AWS Copilot
          • 11_EKS
            • Elastic Kubernetes Service (EKS)
          • 12_SDK_CLI_Tips
            • Access AWS Resources
          • 13_CloudFront
            • Cloud Front
          • 14_Messaging
            • Simple Queue Service (SQS)
            • Simple Notification Service (SNS)
            • Fan Out Pattern
            • Kinesis
            • Compare and Contrast
          • 15_ElasticBeanStalk
            • Elastic Beanstalk
          • 16_CloudFormation
            • CloudFormation
            • Dynamic References
          • 17_Monitoring
            • AWS Monitoring
            • AWS CloudWatch
            • CloudWatch Alarms
            • Synthetics Canary
            • Amazon EventBridge (formerly CloudWatch Events)
            • X-Ray
            • OpenTelemetry
            • CloudTrail
          • 18_Lambda
            • Lambda
            • Lambda Integrations
            • Configuring Lambda
            • Lambda Layers
          • 19_API_Gateway
            • API Gateway
            • API Gateway Integrations
          • 20_DynamoDB
            • DynamoDB
            • Operations
            • Indexes
            • DynamoDB Accelerator (DAX)
            • DynamoDB Streams
            • Transactions
            • Integrations
          • 21_CICD
            • CICD
            • CodeCommit
            • CodePipeline
            • CodeBuild
            • CodeDeploy
            • CodeArtifact
            • CloudGuru
          • 22_SAM
            • Serverless Application Model (SAM)
          • 23_CDK
            • Cloud Development Kit (CDK)
          • 24_StepFunctions
            • Step Functions
            • Types of step function
          • 25_AppSync
            • AppSync
          • 26_Amplify
            • Amplify
          • 27_STS
            • Security Token Service (STS)
          • 28_DirectoryService
            • Active Directory
          • 29_KMS
            • Encryption
            • KMS API
            • Features
            • Cloud Hardware Security Module (HSM)
          • 30_SSM_Store
            • SSM Parameter Store
          • 31_SecretsManager
            • Secrets Manager
          • 32_Cognito
            • Cognito
      • Questions
        • AWS_Region
        • EC2
        • IAM
  • Database
    • MongoDb
      • Mongo db Basics
      • Mongo DB Atlas
      • Document
      • Import-Export based on Data Format
      • Mongo Shell Commands
      • Query Operators
      • Indexes
      • Upsert
      • MongoDB Aggregation Framework
      • Aggregation Framework Operators
    • PostgreSQL
      • POSTGRE SQL DataTypes
      • About table
      • Constraints
  • Technologies
    • RabbitMQ
      • RabbitMQ Concepts
      • Introduction to Exchanges
      • Introduction to Queues
    • Terraform
      • 00_Introduction
      • Configuration blocks
      • Commands
      • Variables
      • Terraform Cloud
      • Modules
  • Languages
    • Java
      • Logging
        • Getting Started
      • 00_Core
        • 00_Basics
          • Java Vs C++
          • Object oriented principles
          • Steps to compile a java program
          • JVM Internals
          • Understanding Java Development Kit
          • What is JIT Compiler?
          • Java data types
          • 07_identifiers_type_conversion
          • 08_references_and_packages
          • Steps for attaching scanner
        • Concurrency
          • 00_Threads
            • Threads
          • 01_ExecutorFramework
            • Executor Framework
            • Asynchronous Computation
      • 01_Backend
        • 01_HttpAndWebServerBasics
          • HTTP
          • Content Type
          • Web Server
        • 02_J2EE_Basics
          • J2EE_Basics
          • Why HttpServlet classs is declared as abstract class BUT with 100 % concrete functionality ?
        • 03_TomCatAndSession
          • What is a Session?
          • WebContainer
        • 04_PageNavigation
          • Cookies Additional Information
          • Page Navigation Techniques
        • 05_AboutServlet
          • CGI v/s Servlet
          • Executor Framework
          • Servlet Life cycle
          • SERVLET CONFIG
          • Servlet Context
          • Servlet Listener (web application listener)
        • 08_SpringBoot
          • Spring Boot
          • Some common annotations used in spring eco system
        • 09_SpringDataJPA
          • Spring Data JPA
        • Java_Language_Changes
          • JDK enhancement tracking reference
        • 06_ORM_Hibernate
          • readmes
            • Hibernate
            • Advantages of Hibernate
            • Hibernate Caching
            • Hibernate API
            • Hibernate Query API
            • Hibernate Annotations and JPQL
            • Entity and Value Type
        • 07_SpringFramework
          • bean_validation
            • Bean Validation
          • core
            • readme
              • Spring
              • Spring Framework Modules
              • Spring MVC Request flow
              • Dependency Injection
              • Spring Beans
              • 06_Spring_Framework_Annotations
      • 03_Tools
        • Maven
          • Maven
  • SoftwareEngineering
    • DesignPatterns
      • Notes
        • Basics
        • OOP
        • SOLID Principles
        • 03_Creational
          • Abstract Factory (aka Kit)
          • Builder
          • Factory Method (aka Virtual constructor)
          • Prototype
          • Singleton
        • 04_Structural
          • Adapter (aka Wrapper)
          • Bridge (aka Handle | Body)
          • Composite
          • Decorator (aka Wrapper)
          • Facade
          • Flyweight
          • Proxy (aka Surrogate)
        • 05_Behavioral
          • Chain of Responsibility
          • Command (aka Action | Transaction)
          • Iterator (aka Cursor)
          • Observer (aka Publish-Subscribe | Dependents)
          • Strategy (aka Policy)
    • Principles
      • REST
        • REST
  • Tools
    • Containers
      • Docker
        • Docker
        • Docker Image
        • Commands
        • Compose
        • Best Practices
      • Kubernetes
        • Kubernetes
    • VCS
      • Git
        • Quick reference of useful Git commands
Powered by GitBook
On this page
  1. SoftwareEngineering
  2. DesignPatterns
  3. Notes

SOLID Principles

PreviousOOPNext03_Creational

Last updated 4 months ago

Solid Image
  • Introduced by Robert C Martin in his 2000 and formed by Michael Feathers, these principle changed the way software is written.

  • These principle help us to write better code, code which are maintainable, understandable and flexible.

  • The following five concepts make up SOLID principles:

    • Single Responsibility Principle (SRP)

    • Open/Closed Principle (OCP)

    • Liskov Substitution Principle (LSP)

    • Interface Segregation Principle (ISP)

    • Dependency Inversion Principle (DIP)

Lets dive in onto each of them,

  1. Single Responsibility Principle

"There should never be more than one reason for a class to change." In other words, every class should have only one responsibility.

  • We don’t want objects that know too much and have unrelated behavior. These classes are harder to maintain.

    • For example, if we have a class that we change a lot, and for different reasons, then this class should be broken down into more classes, each handling a single concern. Surely, if an error occurs, it will be easier to find.

  • When writing a class according to the SRP principle, we have to think about the problem domain, business needs, and application architecture. It is very subjective, which makes implementing this principle harder then it seems.

  • How does this principle help us write better software? A few benefits are as follows,

    • Testing: Will have fewer test cases.

    • Lower coupling: Will have fewer dependencies.

    • Organization: Smaller, well-organized classes are easier to search than monolithic ones.

    • Classes will adhere to one functionality. Their methods and data will be concerned with one clear purpose. This means high cohesion, as well as robustness, which together reduce errors.

      • One of the tools that can help achieve high cohesion in methods is LCOM. Essentially, LCOM measures the connection between class components and their relation to one another.

  1. Open Closed Principle

Software entities should be open for extensions, closed for modifications.

  • Programs that conform to the open-closed principle are changed by adding new code, rather than changing existing code. They dont experience cascade of changes exhibited by non-conforming programs.

  • Exception to this principle is when fixing bugs in existing code.

  • Due to this principle, loose coupling is achieved which leads to easy maintenance of applications.

  1. Liskov Substitution Principle

If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.

  • Simple put by Uncle Bob,

    Subtypes must be substitutable for their base types.

  • A subtype doesn't automatically become substitutable for its supertype. To be substitutable, the subtype must behave like its supertype.

  • An object's behavior is the contract that its clients can rely on.

  • Subtyping in Java requires the base class's properties and methods are available in the subclass.

    • However, behavioral subtyping means that not only does a subtype provide all of the methods in the supertype, but it must adhere to the behavioral specification of the supertype.

    • This ensures that any assumptions made by the clients about the supertype behavior are met by the subtype.

    • This is the additional constraint that the Liskov Substitution Principle brings to object-oriented design.

  • The following rules help us to create well-behaved subtypes.

    1. Signature Rule -> Methods Argument types

      • The overridden subtype method argument types can be identical or wider than the supertype method argument types.

    2. Signature Rule -> Return types

      • The return type of the overridden subtype method can be narrower than the return type of the supertype method.

      • This is called covariance of return types. Covariance indicates when a subtype is accepted in place of a supertype.

    3. Signature Rule -> Exceptions

      • The subtype method can throw fewer or narrower (but not any additional or broader) exceptions than the supertype method.

    4. Properties Rule -> Class Invariants

      • A class invariant is an assertion concerning object properties that must be true for all valid states of the object.

      • All subtype methods (inherited and new) must maintain or strengthen the supertype's class invariants.

    5. Properties Rule -> History Constraints

      • All subclass methods (inherited or new) shouldn't allow state changes that the base class didn't allow.

    6. Methods Rule -> Preconditions

      • A precondition should be satisfied before a method can be executed.

      • A subtype can weaken (but not strengthen) the precondition for a method it overrides.

    7. Methods Rule -> Postconditions

      • A postcondition is a condition that should be met after a method is executed.

      • The subtype can strengthen (but not weaken) the postcondition for a method it overrides.

  • The Liskov Substitution Principle helps us model good inheritance hierarchies. It helps us prevent model hierarchies that don't conform to the Open/Closed principle.

  • Any inheritance model that adheres to the Liskov Substitution Principle will implicitly follow the Open/Closed principle.

  1. Interface Segregation Principle

  • Interface Segregation simply means that we should break larger interfaces into smaller one. Thus ensuring that implementing classes need not implement unwanted methods.

  • This principle was first defined by Robert C. Martin as,

    “Clients should not be forced to depend upon interfaces that they do not use“.

  • The goal of this principle is to reduce the side effects of using larger interfaces by breaking application interfaces into smaller ones.

  • Precise application design and correct abstraction is the key behind the Interface Segregation Principle.

  • In case we’re dealing with polluted legacy interfaces that we cannot modify, the adapter design pattern can come in handy.

  • Adhering to this principle helps to avoid bloated interfaces with multiple responsibilities.

  • This eventually helps us to follow the Single Responsibility Principle as well.

  1. Dependency Inversion Principle

"Depend upon abstractions, [not] concretions."

  • As per Robert Martin (Uncle Bob),

    High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.

    • So, it's clear that at the core, the DIP is about inverting the classic dependency between high-level and low-level. components by abstracting away the interaction between them.

    • In traditional software development, high-level components depend on low-level ones. Thus, it's hard to reuse the high-level components.

  • Note that DIP is neither Dependency Injection nor Inversion of Control.

  • Inversion of Control (IoC)

    • IoC is a pattern in which the control of the flow of an application is reversed.

    • With traditional programming methodologies, our custom code has the control of the flow of an application. Conversely, with IoC, the control is transferred to an external framework or container (eg: Spring Framework).

    • The framework is an extendable codebase, which defines hook points for plugging in our own code.

    • In turn, the framework calls back our code through one or more specialized subclasses, using interfaces' implementations, and via annotations.

  • Dependency Injection (DI)

    • DI is about making software components to explicitly declare their dependencies or collaborators through their APIs, instead of acquiring them by themselves.

    • Without DI, software components are tightly coupled to each other. Hence, they're hard to reuse, replace, mock and test, which results in rigid designs.

    • With DI, the responsibility of providing the component dependencies and wiring object graphs is transferred from the components to the underlying injection framework.

  • DI is about wiring, IoC is about direction, and DIP is about shape [of the object upon which the code depends].

  • Interestingly, this principle is only achievable provided that OCP and LSP are followed.



  • References:

A detailed explanation can be found .

More about it can be found .

More about it can be read .

More about this principle can be read

A good read about this can be found

Dependency Inversion, Inversion of Control and Dependency Injection all work well together and can be understood as the following quote from Martin Fowler's ,

Refer article which talks about how DI and IoC work together.

Read more about this principle .

If you still wonder, if SOLID is still relevant, read .

here
here
here
here
here
article
this
here
this
Baeldung
Wikipedia
Clean coder
Martin Fowler blogs
paper