Goal
- OOP(객체 지향 프로그래밍)의 설계 원칙 ‘SOLID’중 ‘S’를 이해한다.
- python 예제를 통해 SRP를 이해한다.
SRP 의 유래
Robert C. Martin의 저서 ‘Agile Software Development, Principles, Partterns, and Practices’에서 쓰였다.
SRP 의 뜻
각각의 모든 클래스는 하나의 책임만을 가져야 한다.
- 하나의 책임?
- 각 클래스마다 해야하는 일이 하나라는 의미.
- 변경하려는 이유.
- 어떤 클래스나 모듈은 변경하려는 이유가 단 하나여야 한다.
SRP 을 지켜야하는 이유
- SRP를 지키면 프로그램 변화에 맞추어 코드를 쉽게 변경할 수 있다.
- 코드를 쉽게 바꿀 수 있다면 사용자(users)들의 입맛에 맞춰줄 수 있다.
- 서로 다른 이유로 코드를 변경했다면 각자의 자체적인 솔루션으로 인해 코드를 다시 짜야하는 경우가 생길 수 있다.
SRP를 쉽게 접근하고 생각하는 방법
코딩하다 보면 클래스에 얼만큼의 책임을 가져야 할지 어떤 역할을 부여해야 할지 의문이 드는 경우가 많이 발생한다. 예를 들어 회사 관련 프로그램을 만든다고 해보자. 작은 회사에서 개인이 여러 역할을 수행할 수도 있고 큰 회사에서 하나의 역할을 많은 사람이 수행할 수도 있다. 두 경우가 있기에(따지면 더 많을 수 있으나 여기서는 두 가지로 제한하겠다) 각 클래스에 어떤 역할을 주어야 하는가? 어떻게 그 역할을 찾아야 하는가? 등등의 의문들이 생긴다. 이런 의문들을 알맞게 해결해 각 클래스에 해당하는 적절한 역할을 부여하는 건 굉장히 어렵다.
이를 위해 Robert C. Martin이 방법을 제시했다. 바로 책임을 하나의 특정 actor 역할을 하는 함수의 집합체로 생각하라이다. (So a responsibility is a family of functions that serves one particular actor)
클래식한 예를 보자.
class Book():
def get_title(self):
print("A great book")
def get_author(self):
print("Shin")
def turn_page(self):
# 다음 페이지로 넘기는 함수
pass
def print_current_page(self):
print("현재 페이지를 출력합니다.")
위 코드에서 Book
이라는 클래스는 알맞아 보인다. Book
이라는 클래스가 책의 타이틀, 저자, 페이지 넘기기 그리고 현재 페이지 출력까지 제공하고 있기 때문이다. 하지만 이 코드에는 문제가 있다. Book
클래스에 너무 많은 역할을 부여했기 때문이다. Book
을 실행해주는 actor가 있다고 생각해보자. 현재 이 actor의 역할은 독자 역할과 독자에게 콘텐츠(print_current_page
)를 제공하는 사서 역할을 하고 있다. 즉. 하나의 actor가 하나의 역할을 하는 것이 아니라 사실은 두 개의 역할을 하는 것이다. 따라서 이 코드는 actor의 역할을 적절히 나누지 못했으니 SRP원칙에 반하고 있다. 하나의 책임만 지니는 코드로 바꾸어야 한다.
class Book():
def get_title(self):
print("SRP란 무엇인가?")
def get_author(self):
print("Shin")
def turn_page(self):
# 다음 페이지로 넘기는 함수
pass
def get_current_page(self):
print("현재 페이지: {}".format(page))
class Printer():
@abstractmethod
def print_current_page(self)
pass
class TextPrinter(Printer):
def print_current_page(self)
print("현재 페이지를 출력합니다.")
class PythonPrinter(Printer):
def print_current_page(self):
print("현재 파이썬 코드를 출력합니다.")
actor의 프린터 역할을 Printer
클래스에 전달함으로써 하나의 클래스에 하나의 책임만 지니게 되었다.
정리
SRP는 코드를 작성할 때 항상 고려해야 한다. 만약 SRP를 지키지 않아 서로 다른 이유로 클래스나 모듈이 변경되기 시작한다면 주저하지 말고 SRP를 지키는 코드로 바꾸도록 한다. 그래야 나중에 일이 발생하더라도 쉽게 대처할 수 있다.