2014년 4월 17일 목요일

객체 지향 설계 원칙 OCP

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


소프트웨어 개체(클래스, 모듈, 함수 등등) 은 확장에 대해 열려 있어야 하고, 변경에 대해서는 닫혀 있어야 한다.
  1. 확장에 대해 열려 있다.
    이것은 모듈의 동작을 확장할 수 있다는 것을 의미한다. 요구사항이 변경이 될 때, 이 변경에 맞게 새로운 동작이나 기능을 추가 할 수 있어야 한다. 즉 모듈이 하는 일이 변경이 가능한다.
  2. 변경에 대해 닫혀 있다.
    어떤 모듈의 동작이나 기능의 확장으로 인해서 그 모듈의 코드에 변경이 일어나는 것은 아니다.

참 아이러니하다. 어떻게 코드의 변경이 없이 모듈의 동작의 확장이 가능하단 말인가? 핵심은 객체지향에 있다. 잘 설계된 추상화된 모듈은 이것이 가능하다. 예를 들어, 화가가 자신이 선택한 재료로 그림을 그리듯이 이러한 기능이 담고 있는 애플리케이션을 (포토샵이나 페이터와 같은...) 만든다고 상상해보자. 먼저 화가라는 객체를 추상화가 필요하다. 그리고 이 객체의 주요 동작은 그리는 것이다. 아래 두 가지 방법의 설계를 살펴보자.

그림 1 - OCP가 고려되지 않은 설계

그림 1의 설계에서는 볼펜을 사용하는 화가, 연필을 사용하는 화가를 각각 클래스로 구현하였다. 클라이언트가 BallpenPainter 클래스를 사용하다가, 볼펜이 아닌 다른 느낌의 그리는 기능이 필요하게 되었다. 이럴 경우 클라이언트는 BallpenPainter 대신에 PencilPainter 클래스를 사용해야 하고, BallpenPainter 을 호출하는 코드의 변경이 필요하다. 만약 이 클래스가 상속이 되어 있거나 다른 곳에서 사용이 되고 있다면 연쇄적인 변경이 필요하다. 이러한 문제가 발생하는 근본적인 원인은 클라이언트가 BallpenPainter 나 PencilPainter 와 같은 구체화된 클래스에 의존하기 때문이다.


그림 2 - Client 가 사용하는 코드는 변하지 않는다.

그림 2의 설계에서는 클라이언트는 추상클래스에 대해서만 알고 있으며, 추상 클래스의 draw() 메서드만 호출한다. 그리는 동작의 변경은 이 추상클래스를 상속하는 구체클래스가 사용하는 전략에 따라 달라진다. 클라이언트 입장에서는 기능이 확장되어도 여전히 추상클래스의 draw() 메서드를 이용하는 것이고, 코드의 변경은 일어나지 않는다. 전략 패턴뿐만 아니라 템플릿 메서드 패턴이나 데코레이터 패턴 등의 여러 객체지향 디자인 패턴들을 활용하여 상황에 맞게 설계하면 된다.

 참고자료

  • Agile Software Development,Principles, Patterns, and Practices (Robert C. Martin)
  • Head First Design Patterns(에릭 프리먼, 엘리자베스 프리먼, 케이시 시에라 버트 베이츠)
  • GoF 의 디자인 패턴(에릭 감마, 리처드 헬름, 랄프 존슨, 존 블리시디스)
  • 토비의 스프링 3.1(이일민) 


댓글 없음:

댓글 쓰기