ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SOLID] 단일 책임 원칙이란 (Single Responsibility Principle, SRP)
    공부 2021. 6. 13. 17:29

    단일 책임 원칙이란 클래스는 단 1개의 책임만 가져야 하며 변경되는 이유도 1개여야 한다는 원칙입니다. 다섯 가지 애자일 원칙(SOLID) 중 1개입니다. 만약 한 클래스에 두 가지 기능을 담당하는 이유 때문에 수정이 된다면 이 클래스는 단일 책임 원칙에 위배되므로 두 클래스로 쪼개야 합니다. 이는 클래스 뿐만 아니라 함수형 프로그래밍에도 적용이 됩니다. 하나의 함수에서 담당하는 기능이 두 개 이상이라면 이 함수는 쪼개는 것이 추후 유지보수에 용이해집니다. 팩토리 패턴은 이러한 원칙을 잘 설명하는 디자인 패턴입니다.

    아래와 같은 코드가 있다고 가정합니다.

    from typing import List
    
    def data_save(data_list: List[str]):
        data = '|'.join(data_list)
        data = data.replace(' ', '')
    
        with open("foo.txt", "w") as f:
            f.write(data)

    이 예제는 SRP를 위배한 코드입니다. 정보를 저장하려는 목적으로 개발된 코드에 전달 받은 리스트 타입의 파라미터를 파이프 라인으로 구분지어 문자열 타입으로 변경하고 해당 문자열에 존재하는 여백을 전부 공백으로 치환합니다. 그 다음 데이터를 파일에 저장하는 로직입니다. 하나의 함수에 아래와 같이 3가지 기능을 처리하고 있습니다.

    • 리스트 타입의 데이터를 구분자(파이프 라인)를 주어 문자열로 치환
    • 해당 문자열의 여백을 공백으로 치환
    • 파일에 저장

    이러한 코드에 만약 값을 치환하는 로직이나 다른 처리를 진행해야 하는 로직이 추가돼야 한다면 데이터 저장이라는 함수 내에 의미가 맞지 않는 코드가 점점 늘어나게 됩니다. 이는 유지보수를 힘들게 만드는 부분이며 다른 개발자가 핵심 로직을 파악하는데 시간을 많이 소요할 수 있습니다. SRP 기법을 적용한다면 아래와 같이 분리를 할 수 있습니다.

    from typing import List
    
    def conv_type_list_to_str(data_list: List[str]) -> str:
        return '|'.join(data_list)
    
    def replace_white_space_to_blank(data: str) -> str:
        return data.replace(' ', '')
    
    def data_save(data_list: List[str]):
        data = conv_type_list_to_str(data_list)
        data = replace_white_space_to_blank(data)
    
        with open("foo.txt", "w") as f:
            f.write(data)

    이렇게 기능 별로 함수를 쪼갠다면 의존성이 적고 결합도가 낮은 설계가 가능해집니다. 처음부터 SRP를 잘 지키면서 설계를 하는게 가장 좋지만 설계 단계에서 이 모든 케이스를 생각하기란 쉽지가 않습니다. 초반에는 적절히 (현실과 타협하면서) 설계를 진행하고 추후 해당 클래스 또는 함수에 서로 다른 이유로 변경이 진행된다면 SRP 기법을 적용하는 것이 좋아 보입니다.

    댓글