Skip to content

2023091323572727 GO SOLID

Single Responsibility Principle

A piece of code should have only one reason to change.

The code that has SRP has the fewest reason to change.

  • Every package should has single responsibility and high cohesion
  • Low coupling between packages
  • Don't use package names like: common, utils, private e.t.c. Package should have 1 responsibility with name that reflect this responsibility.

Opened/Closed Principle

A piece of code should be open for extension and closed to modification. - compose simple types into more complex ones using embedding.

Example: Go’s types, while being open for extension, are closed for modification.

Code example from 2

package main

type Cat struct {
        Name string
}

func (c Cat) Legs() int { return 4 }

func (c Cat) PrintLegs() {
        fmt.Printf("I have %d legs\n", c.Legs())
}

type OctoCat struct {
        Cat
}

func (o OctoCat) Legs() int { return 5 }

func main() {
        var octo OctoCat
        fmt.Println(octo.Legs()) // 5
        octo.PrintLegs()         // I have 4 legs
}
Cat has no knowledge of the type it has been embedded into, so its method set cannot be altered by embedding.

Liskov Substitution Principle

Two types are substitutable if they exhibit behaviour such that the caller is unable to tell the difference.

  • express the dependencies between your packages in terms of interfaces, not concrete types
  • use small interfaces , prevailing idiom is an interface contains only a single method

Interface Segregation Principle

Clients should not be forced to depend on methods they do not use.

  • Require only what you need. For example, use io.Writer instead of io.ReadWriteCloser if you need to do only write operations.

Dependency Inversion Principle

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. 1

  • import graph must be acyclic
  • push the responsibility for the specifics, as high as possible up the import graph, to your main package or top level handler, leaving the lower level code to deal with abstractions–interfaces.

References

  1. https://www.amazon.co.uk/dp/0135974445/
  2. https://dave.cheney.net/2016/08/20/solid-go-design