본문 바로가기

ComputerScience/DesignPattern

[SOLID] SRP: The Single-Responsibility Principle


* 이 글은 Agile Software Development, Principles, Patterns, and Practices - Robert Martin 책 내용을 번역 및 요약하여 작성하였습니다.

SRP: The Single-Responsibility Principle

왜 책임을 별도의 클래스로 분리하는 것이 중요한가요? 각 책임은 변경의 축이기 때문입니다.

요구 사항이 변경되면 그 변경은 클래스 간의 책임 변경을 통해 나타날 것입니다. 하나의 클래스가 두 개 이상의 책임을 가정하면 해당 클래스가 변경해야 하는 이유가 두 개 이상 발생할 것입니다.

하나의 클래스가 두 개 이상의 책임을 갖는 경우, 이러한 책임들은 서로 결합됩니다. 이때 한 책임에 대한 변경 사항은 클래스가 다른 책임을 충족하는 능력을 저해하거나 방해할 수 있습니다. 이러한 종류의 결합은 변경 시 예상치 못한 방식으로 깨지는 민감한 디자인을 유발합니다.

What Is a Responsibility?

SRP(Single Responsibility Principle)의 맥락에서 책임(responsibility)을 "변경의 이유(reason for change)"로 정의합니다. 

한 클래스에 대해 두 개 이상의 클래스를 변경하려는 동기가 있다면 그 클래스는 두 개 이상의 책임을 갖고 있는 것입니다. 

 

예를 들어 아래 코드 예제(Listing 8-1)에서의 Modem 인터페이스를 보면, 이 인터페이스는 크게 문제가 없어 보입니다. 이 인터페이스가 선언하는 네 가지 함수는 모뎀이 수행해야 하는 기능들의 함수들입니다.

그러나 여기에서 두 가지 책임이 나타납니다.

첫 번째 책임은 연결 관리이고, 두 번째는 데이터 통신입니다.

dial 및 hangup 함수는 모뎀의 연결을 관리하고, send 및 recv 함수는 데이터를 통신합니다.

 

응용 프로그램이 연결 함수의 시그니처에 영향을 미치는 방식으로 변경된다면, 설계는 강성(Rigidity)을 띄고 있습니다.

send와 recv를 호출하는 클래스들은 예상하는 것보다 빈번하게 다시 컴파일하고 재배포해야 할 것입니다.

 

두 가지 책임은 아래 Figure 8-3에 나와 있는 것처럼 분리되어야 합니다. 이렇게 하면 클라이언트 응용 프로그램이 두 가지 책임을 결합하지 않도록 유지됩니다.

그러나 반대로 응용 프로그램이 두 가지 책임을 서로 다른 시점에 변경시키지 않는 방식, 즉 동시에 변경시키는 방식으로 구현을 한다면 이들을 분리할 필요가 없습니다. 오히려 이들을 분리하는 것은 불필요한 복잡성을 만들 수 있습니다.

 

앞에서 말했듯이 책임은 변경 축이며 이는 변경 사항이 실제로 발생할 때만 변경 축입니다. 즉, 어떠한 증상이 없는 경우에는 SRP 또는 다른 원칙을 적용하는 것이 현명하지 않습니다.

Separating Coupled Responsibilities

ModemImplementation class

ModemImplementation 클래스에는 두 가지 책임을 모두 결합시켰습니다. 이것은 바람직하지 않지만 필요할 수 있습니다.

하드웨어나 운영 체제의 세부 사항과 관련된 이유로 결합하려고 하지 않으려는 경우가 종종 있습니다.

그러나 인터페이스를 분리함으로써 응용 프로그램의 나머지 부분에서는 이 개념을 분리했습니다.

 

ModemImplementation 클래스의 주목할 점은 모든 종속성이 외부로 향한다는 것입니다.

어떤 클래스도 이 ModemImplementation 클래스를 의존할 필요가 없습니다. 메인 함수를 제외하고는 이 클래스가 존재하는 사실을 알 필요가 없습니다. 따라서 ModemImplementation이 외부로 노출되어 응용 프로그램의 나머지 부분을 간섭할 일이 없습니다.

Persistence

아래는 SRP(Single Responsibility Principle)의 일반적인 위반 사례를 보여줍니다.

Employee 클래스에는 업무 규칙(CalculatePay)과 지속성 제어(Store)가 포함되어 있습니다. 이 두 가지 책임은 혼합되어서는 안 됩니다. 업무 규칙은 자주 변경되며, 지속성(Persistence)은 그렇게 자주 변경되지 않을 수 있지만 완전히 다른 이유로 변경될 수 있습니다. 업무 규칙을 지속성 하위 시스템(Persistence Subsystem)에 바인딩하면 문제가 발생할 가능성이 있습니다.

Conclusion

SRP(단일 책임 원칙)은 가장 간단한 원칙 중 하나이지만 올바르게 적용하기 가장 어려운 것 중 하나입니다. 책임을 결합하는 것은 우리가 자연스럽게 하는 일입니다. 그리고 이러한 책임을 찾아내고 서로 분리하는 것이 소프트웨어 디자인의 핵심입니다. 실제로 다룰 다른 원칙들은 어떤 방식으로든 이 문제로 돌아옵니다.