단일 책임 원칙(The Single Responsibility Principle)이란 클래스는 하나의 책임만을 가져야 한다는 원칙이다.
클래스를 구현할 때 한 가지 기능에만 중점을 두어야 한다. 두 가지 이상의 기능이 필요하다면 클래스를 나눠야 한다.
이 원칙에서는 클래스는 기능으로 인해 변경된다. 특정 기능의 작동 방식이 변경돼 클래스를 수정하는 것은 허용되지만 두 가지 이상의 이유(두가지 기능 변경)
때문에 클래스를 수정해야 한다면 클래스는 분할돼야 한다.
단일 책임 원칙의 장점은 다음과 같다.
생각해보면 디자인 패턴에서 제시하는 여러 패턴들은 단일책임 원칙을 매우 잘 지키고 있다고 생각하면 되는데,
대표적으로 생성자 패턴에서의 팩토리패턴을 생각해보자.
팩토리 패턴이라는건, 객체를 찍어낼(인스턴를 만들어낼)팩토리 클래스와 실제로 객체를 찍어낼 틀(클래스)가 각자의 기능이 분리되어있는 형태다.
그래서 유지보수도 쉬워지기도 하는거지..
단일 책임 기능의 원칙을 위반하고, 하나의 클래스에 너무 많은 기능을 떄려박으면, God Class
라고 부르는 정말 모든걸 다하는 신의 클래스를 만들게 된다!
몇몇 사람들은 이 단일책임의 원칙이 오직 객체지향 프로그래밍 패러다임에서만 적용된다고 오해 하기도 하는데,
이 단일책임 원칙은 모든 소프트웨어 개발 패러다임에서 적용된다.
그러니까 함수형 프로그래밍을 하고 있을 지라도 단일 책임 원칙은 꼭 잘 지키라는 의미다!
나 같은 초짜 개발자들이 대표적으로 하는 실수가 이 단일책임 원칙을 위배하는것!
아래와 같은 코드를 생각해보자
def percentage_of_word(search, file):
search = search.lower()
content = open(file, "r").read()
words = content.split()
number_of_words = len(words)
occurrences = 0
for word in words:
if word.lower() == search:
occurrences += 1
return occurrences/number_of_words
위 코드는 인자로 주어진 search 스트링(단어)이 file 이라는 인자로 주어진 파일이 갖고있는 단어중에서
얼마나 많이 겹치는지 퍼센티지를 계산하는 함수이다.
겉으로 보기엔 하나의 기능만 한다고 생각 할 수도 있지만
이렇게 여러 기능을 벌써 하고 있는것이다.
위 코드는 아래와 같이 리팩토링이 가능하다.
def read_localfile(file):
"""파일을 읽는 함수"""
return open(file, "r").read()
def number_of_words(content):
"""파일에 있는 단어의 개수"""
return len(content.split())
def count_word_occurrences(word, content):
"""해당 파일에 얼마나 자주 word가 등장하는지 카운트하는 함수"""
counter = 0
for e in content.split():
if word.lower() == e.lower():
counter += 1
return counter
def percentage_of_word(word, content):
"""전체 단어들 중 word에 해당하는 단어가 얼마의 비율로 나타나는지 계산하는 함수(퍼센티지 계산)"""
total_words = number_of_words(content)
word_occurrences = count_word_occurrences(word, content)
return word_occurrences/total_words
def percentage_of_word_in_localfile(word, file):
"""텍스트 파일에 있는 단어들 중 word에 해당하는 단어가 얼마의 비율로 나타는지 계산하는 함수"""
content = read_localfile(file)
return percentage_of_word(word, content)
분리된 각 함수는 오직 하나의 기능만을 충실하게 수행하도록 변경되었다 !