dev

SOLID

coldmonster 2022. 9. 23. 01:05

SOLID

Single responsability principle

한번에 한가지 기능만 가져야한다. OpenAndWrite()같은 함수는 지양.
기능은 하나씩만 가져야한다. Open과 Write는 분리하자

FileOpenAndWrite() (X)
-> FileOpen()
-> FileWrite()

 

Open closed principle

확장은 open 수정은 close

animal클래스를 상속받는 cat클래스 외에 dog 클래스를 추가하여 확장 하는것은 허용.
하지만 이 확장으로 인해 cat, dog을 호출하는 다른 함수들을 수정하지 않아야한다.

Cow클래스 추가로인해 Hello()함수에 Cow클래스를 위한 수정은 없어야한다는 뜻.

위 그림에서는 Cow가 추가되면서 Hello() 함수에 Cow에 대한 처리를 추가해줘야한다.

 

Cat::hello()
    run()
Dog::hello()
    speak()
Cow::hello()
    print(...)

fn Hello(animal)
    animal.hello()

이게 꼭 정답은 아니지만 Hello()함수에 대응하는 동작은 Animal을 상속받는 동물들의 구현에 맡긴다.

 

Liskov substitution principle

class Animal {
    run()
    speak()
}
class Cat : Animal {}
class Fish : Animal {} // 물고기는 run(), speak() 불가..

Animal클래스를 상속받는 Cat클래스는 Animal클래스로 치환되어도 제 기능을 수행할 수 있어야한다.

Fish클래스에 Animal클래스를 상속받아도 제 기능을 할 수 없다.

 


Interface segregation principle

class Machine {
    go()
    stop()
    turn()
}
class Car : Machine {}
class Plane : Machine {
    // 공중에서..
}

인터페이스가 너무 크면 안된다. 사용하지 않는 인터페이스 메소드들이 함께 포함된다.
인터페이스를 더 세부화 하여 사용하지 않는 메소드를 상속받지 않게 한다.

// Machine을 분리해서 
class Vehicle {
    go()
    stop()
    turn()
}
class Flight {
    takeoff()
    land()
}
class Car : Vehicle {}
class Plane : Flight {}

 

Dependency inversion principle

상위클래스에서 하위클래스가 추가됨에따라 하위클래스에 의존하는 형태가 되어선 안된다.

class Animal {
	virtual string run() {return "cong"}
}
class Cat : Animal {
	string run() override {return "cat";}
}
class Dog : Animal {
	string run() override {return "dog";}
}
class Horse : Animal {
	string run() override {return "hor";}
}

 

동물의 run 함수를 호출해야할때 아래처럼 하위클래스를 받아 run함수를 호출하는 것이 아니라

void call(Cat* cat) {
	cat->run();
}

 

상위클래스 Animal을 가지고 데이터 형태에 따라 각각 다른 run의 동작을 호출할 수 있도록 하는것.

void call(Animal* animal) {
	animal->run();
}