Robert C. Martin coined the mnomonic acronym SOLID to represent 5 principles of software design. This is the third in my own five-part series exploring my understanding of and experience applying these principles:
This principle is mostly concerned with the potential for voliating invariants when using inheritance to define a heirachy. The example below is in Go, which doesn't really have traditional inheritance, but does support a concept called embedding, which is simliar:
type Rectangle struct {
TopLeft Point
Length int
Width int
}
type Square struct {
Rectangle
}
In this example, the Square
struct embeds the Rectangle
. This is probably because the developer who wrote this code was used to thinking of a square being a special case of rectangle, which can often indicate a good candidate for sub-classing and inheritance. 'Under the hood', there's an actual field on the Square
of type Rectangle
, but you can access the Rectangle
fields (and methods, if any are defined) as if they were defined on the Square
.
func main() {
s := Square{
Rectangle: Rectangle{
TopLeft: Point{0, 0},
Length: 4,
Width: 4,
},
}
fmt.Println(s.Length, s.Width) // Output: 4 4
}
But the embedding of Rectangle to represent a Square is...not good:
func main() {
s := Square{
Rectangle: Rectangle{
TopLeft: Point{0, 0},
Length: 4,
Width: 4,
},
}
s.Length = 5
fmt.Println(s.Length, s.Width) // Output: 5 4
}
Well, that's awkward, a word which here means a violation of LSP.
Next Section: The Interface Segragation Principle
-Michael Whatcott, 12 August 2021