산 넘어 산 개발일지

OCP (Open-Closed Principle) (개방-폐쇄 원칙) 본문

Study/용어

OCP (Open-Closed Principle) (개방-폐쇄 원칙)

Mountain96 2021. 2. 10. 16:53

"클래스나 모듈은 확장에는 열려 있어야 하고 수정에는 닫혀있어야 한다."


 

처음에는 이 문장이 이해가 가지 않았다.

확장은 정확히 무엇을 뜻하는 것이고, 수정은 어느 부분을 수정한다는 것인지 모호했다.

가장 간단히 확장과 수정을 구분해보자면,


확장은 클래스나 모듈 외부에서 클래스에 변화를 주는 것이고,

수정은 클래스나 모듈 자체의 코드를 수정함으로써 변화를 주는 것이다.


  클래스나 모듈 외부에서 변화를 준다는 말은, 클래스의 내용 자체는 수정하지 않지만 외부에서 입맛에 따라 변화를 준다는 뜻이다. 이를 가능하게 하기 위해선 클래스에서 외부에서 주는 화요청을 받을 준비가 되어 있어야 한다. 

  다시말해, 클래스에 대한 수정을 지원할 멤버함수, 멤버변수가 있어야 한다는 것이다. 

 

 

컴퓨터와 프린터를 통해 예시를 들어보자.

 

내 컴퓨터에 S사의 프린터를 쓴다고 가정해보자.

class Computer{
    SPrinter printer;

    public void setPrinter(SPrinter printer) {
        this.printer = printer;
    }
}

이 경우 프린터가 S사의 프린터라면 언제든지 교체할 수 있을 것이다.

그러나 만약 H사의 프린터로 교체하고 싶다면??

 

Computer는 S사의 프린터만 입력될 수 있으므로 컴퓨터 자체를 뜯어 고쳐 H사의 프린터를 입력받도록 해야 할 것이다.

class Computer{
    /*
    SPrinter printer;

    public void setPrinter(SPrinter printer) {
        this.printer = printer;
    }
    /*
    HPrinter printer;

    public void setPrinter(HPrinter printer) {
        this.printer = printer;
    }
}

이 경우 프린터를 받기 위해서 Computer라는 클래스 자체를 뜯어고쳤다. 이것이 바로 수정이다.

즉 이 경우는 OCP를 위반한 경우가 된다.

 

그렇다면 Computer가 모든 프린터에 대해서 클래스를 뜯어 고칠 필요 없이 입력받는 방법은 없을까?

이 부분이 바로 확장이다.

 

만약 HPrinter와 SPrinter가 모두 하나의 "프린터"라는 클래스에서 파생된다면 어떨까.

class Computer{
    Printer printer;

    public void setPrinter(Printer printer) {
        this.printer = printer;
    }
}

이 경우 Computer의 사용자는 자신의 입맛에 따라 때로는 HPrinter를, 때로는 SPrinter를 Computer에 세팅할 수 있을 것이다.

 

이렇게 클래스의 코드를 고치지 않고도 클래스에 변화를 줄 수 있는 것이 확장이다.


결론

 

OCP도 어떻게 보면 코드의 재사용성과 관련이 있다는 생각이 들었다. 객체지향 프로그래밍이라는 부분에서 중요한 개념인 것 같고, 클래스 하나를 유연하게 동작할 수 있도록 짜는 것이다. 결국 다른 클래스를 추가로 만들 필요도 없고, 클래스 자체의 확장성도 늘어나게 된다. 

Comments