--SRP (single responsibility principle) --OCP (Open and Closed Principles) --LSP (Liskov Substitution Principle) --ISP (Principle of interface separation) --DIP (Principle of Dependency Reversal)
It is an acronym for.
The reason for applying SOLID is
――Resistant to change --Easy to understand --Available in many software systems
Can be mentioned. From the following, I will touch on the explanation of each principle and the code.
The principle that there should be no multiple reasons when changing a module, class, function, etc. The reason is to prevent the following events from occurring
--Merges and conflicts occur when multiple people modify one source file --The changes are affected by unexpected things
One interface has multiple responsibilities for managing employees, storing employee data.
type EmployeeWorkManage interface {
calculatePay()
reportHours()
saveEmployee()
}
Create separate interfaces for managing employees and storing employee data so that each has one responsibility.
type EmployeeWorkManage interface {
calculatePay()
reportHours()
}
type EmployeeDataManage interface {
saveEmployee()
}
The principle that it must be open for software extensions and closed for modifications That way you can scale your system unaffected by changes.
By creating an interface called Animal and creating a Dog type or Cat type method depending on it, you can execute the bark method without worrying about the Dog type or Cat type in the main process. Also, if you want to create a new Bird, you only need to add it by making it dependent on the Animal interface.
package main
import(
"fmt"
)
type Animal interface {
bark()
eat()
}
type Dog struct {}
type Cat struct {}
func (d Dog) bark(){
fmt.Println("Bow-wow")
}
func (d Dog) eat(){
fmt.Println("Bakubaku")
}
func (c Cat) bark(){
fmt.Println("Meow")
}
func (c Cat) eat(){
fmt.Println("Mushamsha")
}
func main(){
dog := Dog{}
cat := Cat{}
animals := []Animal{dog, cat}
for _, animal := range animals {
animal.bark()
}
}
S type object: o1 T-type object: o2 The principle that S is a derivative of T if, at some point, the behavior of P does not change when using o1 instead of o2 for program P defined using T.
Since Go has no inheritance, it does not violate the Liskov Substitution Principle and is not conscious (?)
The principle of not forcing you to rely on unnecessary interfaces Group only relevant interfaces and lose the dependency of unused methods.
If you try to create a humanoid from the Animal Interface as shown below, you will have to describe the fly method that you do not use.
type AnimalInterface interface {
fly()
run()
swim()
}
Separate the interface from Bird Interface for birds and Human Interface for humans. By doing so, you don't have to write unnecessary methods.
type BirdInterface interface {
fly()
}
type HumanInterface interface {
run()
swim()
}
type Bird struct {}
type Human struct{}
func (b Bird) fly(){
fmt.Println("Fly! !!")
}
func (h Human) run(){
fmt.Println("I'll run ~")
}
func (h Human) swim(){
fmt.Println("Swimming~")
}
func main(){
bird := Bird{}
human := Human{}
bird.fly()
human.run()
}
The principle of not relying on concrete modules that are frequently changed (modules in which the implementation of a function is written) Avoid reliance on modifiable concreteness and rely on a stable abstract interface. Use the Abstract Factory pattern to refer to the abstract interface.
By relying on the Abstract Factory, the dependency destination becomes an image as shown in the figure, and the user's data can be acquired without worrying about either DB or text.
package main
import(
"fmt"
)
type User struct {
id int
name string
}
type AbstractFactory interface {
getData() User
}
type DbManage struct {}
func (db DbManage) getData() User {
return User{1, "DB TARO"}
}
type TextManage struct {}
func (text TextManage) getData() User {
return User{2, "TEXT JIRO"}
}
func getUserData(manageType string) User {
var manageFactry AbstractFactory
switch manageType {
case "DB":
manageFactry = DbManage{}
return manageFactry.getData()
case "TEXT":
manageFactry = TextManage{}
return manageFactry.getData()
default:
return User{3, "Anonymous"}
}
}
func main(){
user := getUserData("DB")
fmt.Println(user.id, user.name)
}
https://labs.septeni.co.jp/entry/2017/02/21/164127 https://maroyaka.hateblo.jp/entry/2017/05/22/165355 https://qiita.com/shunp/items/646c86bb3cc149f7cff9 https://golangvedu.wordpress.com/2017/01/31/golang-design-pattern-abstract-factory-and-factory-method/
Somehow, I feel like I understand the SOLID principle. If you have any questions or suggestions, we would appreciate it if you could write them in the comments.
Recommended Posts