객체지향 5원칙 SOLID

작성자

선린인터넷고등학교 소프트웨어과 18학번, Unifox 10기 나정휘

단일 책임 원칙 (SRP)

개념

객체는 오직 하나의 책임을 가져야 한다. 다시 말해, 객체는 변경되어야 할 이유가 오직 하나뿐이여야 한다.

예제

예를 들어, 이 원칙에 따르면 스타크래프트에서 유닛과 미니맵에 대한 책임은 서로 분리되어야 한다.

예제 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Unit{
  public:
    Unit();
    ~Unit();
    void move();
    void hold();
    void attack();
    void patrol();
    void stop();
}

class MiniMap{
  public:
    MiniMap();
    ~MiniMap();
    void update();
}

개방-폐쇄의 원칙 (OCP)

개념

확장에 대해서는 개방적이고 수정에 대해서는 폐쇄적이여야 한다. 다시 말해, 기능의 확장은 허용하되 자기 자신을 변경하는 행위는 피해야 한다.

예제

이 원칙에 따라 스타크래프트 유닛의 이동을 구현해보자. 스타크래프트는 A* 알고리즘을 이용해 길을 찾은 뒤 이동을 한다. 그러나 캐리어의 인터셉터는 다른 유닛과는 달리 캐리어의 몸체로 다시 귀환하도록 설계가 되어있다. 이동 메소드를 그대로 두고, 이동 패턴을 나타내는 메소드를 따로 분리해내면 이동 메소드를 수정하지 않고도 여러가지 이동 패턴을 적용시킬 수 있다.

예제 코드

1
2
3
4
5
6
7
8
9
#include <functional>
using namespace std;

//...

void move(function<something> pattern){
  pattern(...);
}

리스코프 치환 법칙 (LSP)

개념

자식 클래스는 언제나 부모 클래스를 대신할 수 있어야 한다. 즉, 부모 클래스가 들어가야 할 자리에 자식 클래스가 들어가도 원하는 결과가 나와야 한다.

예제

스타크래프트에서 플레이어가 직접 조작 가능한 유닛은 모두 왼쪽 마우스로 선택하고 오른쪽 마우스로 이동을 시킨다. 만약 새로운 확장판에 키보드로만 이동 조작이 유닛이 추가된다고 가정하자. 이런 유닛을 처음 접하는 플레이어들은 불편을 호소하며 블리자드에 항의를 할 것이다. 이러한 일은 LSP를 지키지 않아서 발생했다고 볼 수 있다.

인터페이스 분리 법칙 (ISP)

개념

모든 객체는 자신이 사용하지 않는 기능(인터페이스)에 영향을 받지 말아야 한다. 이는 인터페이스를 작게 나누어 해결할 수 있다.

예제

스타크래프트에서 한 유닛은 move, patrol, hold, stop등의 기능을 수행할 수 있다. 그러나 move 기능은 patrol과 다르게 이전의 위치를 기억할 필요가 없다. 또한 hold 상태에서는 move 기능을 절대 수행하지 않는다. 따라서 각각의 기능을 독립된 인터페이스로 구현하여 서로 필요 없는 영향을 미치지 않게 한다.

의존성 역전 법칙 (DIP)

개념

고차원 모듈은 저차원 모듈에 의존하면 안된다. 의역을 하자면, 자신보다 변하기 쉬운 것에 의존하지 말라고 해석할 수 있다.

예제

스타크래프트에서 골리앗은 지대공 미사일의 사거리가 5이지만, 카론 부스터를 업그레이드하면 8이 된다. 골리앗 객체가 미사일 객체를 상속받는 것이 아닌, 미사일 객체가 골리앗 객체를 상속받아야 한다.