2014년 4월 19일 토요일

객체 지향 설계 원칙 SRP

단일 책임 원칙(Single Responsibility Principle)


하나의 모듈(클래스)은 한가지 책임을 져야 한다. 모듈은 단 한 가지의 변경 이유만을 가져야 한다.

그렇다면 책임이란 무엇인가? 책임을 변경을 위한 이유라고 생각해보자. 모듈 변경을 위한 한 가지 이상의 이유를 생각할 수 있다면, 그 모듈은 한 가지 이상의 책임을 가지고 있는 것으로 생각할 수 있다. 객체 지향의 원칙중에 SRP는 은근히 지켜기 어렵다. 

간단한 예를 들어 살펴보자. 특정 파일에 담겨 있는 내용을 읽어 테이블에 표시를 하는 기능을 개발한다고 생각하자. Displayer  라는 클래스를 만들었고, 이 클래스는 두 가지 메서드를 포함하고 있다.

그림 1 - 두가지 책임을 가지고 있는 Displayer 클래스

  • readContent : 파일로 부터 내용을 읽어온다.
  • displayContent : 화면에(GUI) 표시한다.

이후 기능의 호응이 좋아서 새로운 요구사항이 생겼다.
  • 파일뿐만 아니라 데이터베이스에서 내용을 읽어서 표시해달라는 것이다.
    readContent 메서드의 변경이 필요하다.
  • PC 화면뿐만 아니라 모바일 기기에서도 내용을 보기를 원한다.
    dispalyContent 메서드의 변경이 필요하다.

Displayer 클래스는 내용을 읽어들이는 것과 화면에 표시하는 두 가지 책임을 가지고 있다. 이 책임에 따라 변경이 일어날 가능성은 두 가지가 되는 것이다. 이것을 아래와 같이 바꾸어 보자.

그림 2 - 책임(관심)에 따른 클래스의 분리

  • Reader 클래스 : 특정 데이터 소스로부터 내용을 읽어온다.
  • Displayer 클래스 : 화면에 표시하는 로직만 담당한다. 


Displayer 클래스는 Reader 클래스를 사용한다.(또는 내용을 담고 있는 Content 클래스를 정의하고, 이것을 입력으로 받아서 화면에 표시하게 할 수도 있다.) SRP을 생각하면서 설계를 하다 보면 자연스럽게 객체 지향을 생각하게 된다. 지금의 설계에서는 하나의 클래스가 하나의 책임을 기지고 동작하게 된다. 나중에 변경이 생기게 되는 경우 그 변경에 따라 하나의 클래스만 수정을 하면 된다. 사실, 새로운 요구사항이 생겨 ConcreteDisplayer 에 기능을 추가하는 것보다는 전략패턴을 이용해서 아래와 같이 설계를 해서 사용할 전략(Reader의 구체화된 클래스) 을 선택하게 하는 것이 좋을 것이다. 요지는 모듈간의 의존성을 가능한한 느슨하게 만드는 것이다.


그림 3 - 전략패턴을 이용한 구현


이러한 설계를 확장하면, MVC 패턴과도 비슷하다는 것을 알 수 있다. 책임이나 관심사에 따라 적절하게 모듈(클래스)을 분리하는 것이 단일 책임 원칙의 핵심이다.


단일 책임 원칙의 장점

단일 책임 원칙을 지키려고 하다보면 인터페이스등을 도입하게 되며, 여러 디자인 패턴을 적용해서 설계를 우아하게 만들게 된다. 그러면서 자연스럽게 모듈간의 결합이 느슨해진다. 이것은 어떤 변경이 필요할 때 수정 대상을 명확하게 하는 결과를 가져온다.

참고자료

  • Agile Software Development,Principles, Patterns, and Practices (Robert C. Martin)
  • 토비의 스프링 3.1 (이일민)


댓글 없음:

댓글 쓰기