The Office Lover
단일 책임 원칙 - single responsibility principle, SRP 본문
단일 책임 원칙 - single responsibility principle, SRP
Michael Gary Scott 2023. 7. 27. 11:23소개
- 객체지향 프로그래밍은 유지보수성과 재사용성으르 높이기 위해 다양한 설계 원칙을 제공합니다.
- 이 중에서도 '단일 책임 원칙'은 클래스나 모듈이 하나의 책임만을 가져야 한다는 원칙으로, 객체지향 개발의 기본이 되는 중요한 원칙입니다.
- 단일 책임 원칙에 대해 알아보고, 어떻게 적용하는지 예시를 살펴보겠습니다.
단일 책임 원칙이란?
- 정의 : 한 클래스는 하나의 책임을 가져야 한다.
- 거대하고 포괄적인 클래스를 설계하는 대신, 작은 단위와 단일 기능을 가진 클래스를 설계해야 합니다.
- 즉, 클래스에 비즈니스와 관련 없는 기능이 두 개 이상 포함되어 있으면 책임이 단일하지 않으므로, 단일 기능을 가진 여러 개의 작은 클래스로 분할되어야 합니다.
단일 책임 원칙의 장점
- 유지보수성과 가독성이 크게 향상됩니다. 클래스가 단일 책임만을 가지기 때문에 해당 책임과 관련된 코드만 수정하면 되기 때문입니다.
- 이로 인해 코드의 변경이 다른 부분에 미치는 영향을 최소화할 수 있습니다. 또한, 코드를 작은 단위로 분리하면 개별 클래스의 크기가 작아져 코드 이해도가 올라갑니다.
- 클래스의 의존성을 줄일 수 있습니다.
단일 책임 원칙(SRP) 적용 방법과 예시
- 단일 책임 원칙을 적용하기 위해서는 먼저 클래스의 역할을 명확히 구분해야 합니다.
- 예를 들어, 사용자 정보를 저장하고 로그인 기능을 처리하는 클래스가 있다고 가정한다면, 이 클래스는 사용자 정보 관리와 로그인 인증 두 가지 책임을 가지고 있습니다. 이를 단일 책임 원칙을 따르도록 리팩터링 하기 위해 두 가지 책임을 각각 다른 클래스로 분리합니다.
- 하나의 클래스는 사용자 정보를 관리하는 책임을 갖고
- 다른 클래스는 로그인 인증 기능을 담당하는 책임을 맡도록 설계합니다.
- 이렇게 함으로써 각 클래스는 자신의 책임에만 집중하게 되며, 코드의 구조가 명확해집니다.
[단일 책임 원칙(SRP) 미적용 클래스]
public class UserManagement {
public void saveUser(User user) {
// 사용자 정보를 저장하는 로직
}
public boolean authenticateUser(String username, String password) {
// 로그인 인증을 처리하는 로직
return false;
}
}
위 코드에서 UserManagement 클래스는 사용자 정보를 저장과 로그인 인증 두 가지 책임을 가지고 있습니다. 단일 책임 원칙을 적용하여 각각의 책임을 분리해 보겠습니다.
[단일 책임 원칙(SRP) 적용 클래스]
public class UserManager {
public void saveUser(User user) {
// 사용자 정보를 저장하는 로직
}
}
public class UserAuthenticator {
public boolean authenticateUser(String username, String password) {
// 로그인 인증을 처리하는 로직
return false;
}
}
위 코드에서 UserManager 클래스는 사용자 정보를 저장하는 책임만 가지고 있도록 수정되었고, UserAuthenticator 클래스는 로그인 인증 기능을 담당하는 책임을 갖도록 분리되었습니다. 이렇게 수정해 주게 되면 각 클래스는 하나의 책임에만 집중하게 되며, 코드의 구조가 명확해졌습니다.
이렇게 단일 책임 원칙을 적용하면 책임이 분리되어 코드의 변경이 최소화되어 유지보수가 용이해집니다.
클래스에 단일 책임의 여부를 판단하는 방법
대부분의 경우 클래스의 메서드가 동일한 유형의 함수로 분류되는지, 아니면 관련 없는 두 개의 함수로 분류되는지를 판별하는 것은 쉽지 않기 때문에, 실제 소프트웨어 개발에서 클래스에 단일 책임이 있는지를 판별하기란 쉬운 일이 아닙니다.
판단 방법에 대해서 다음과 같은 접근 방법을 활용할 수 있습니다.
클래스의 이름 확인
비즈니스적으로 정확하게 지정하기 어렵거나 Manager, Context처럼 일반적인 단어가 아니면 클래스의 이름을 정의하기 어려울 경우, 클래스 책임 정의가 충분히 명확하지 않음을 의미합니다. 클래스의 이름이나 주석이 모호하거나 다양한 책임을 나타내는 경우 단일 책임 원칙을 위반할 수 있다고 볼 수 있습니다.
클래스의 크기 검토
클래스의 크기를 살펴봤을 때, 하나의 클래스가 너무 많은 메서드와 변수를 포함하고 있다면 여러 책임을 가지고 있을 가능성이 높습니다. 너무 많은 코드로 인해 가독성과 유지 보수성에 영향을 미치는 경우 클래스를 작은 단위로 분리하여 각각의 책임을 명확히 할당할 수 있습니다.
클래스 메서드 분석
클래스의 메서드를 검토하여 어떤 작업을 수행하는지 확인합니다. 하나의 메서드가 여러 가지 작업을 처리하거나 private 메서드가 너무 많은 경우 이 private 메서드를 새로운 클래스로 분리하고 더 많은 클래스에서 사용할 수 있도록 public 메서드로 설정하여 코드의 재사용성을 향상할 수 있습니다.
클래스의 의존성 분석
클래스가 다른 클래스와 어떤 관계로 맺어졌는지 분석합니다. 너무 과하게 다른 클래스의 의존하거나 다른 클래스의 데이터를 처리 또는 기능들을 수행한다면 클래스 분할을 고려해야 합니다.
코드리뷰
주변의 동료와의 코드 리뷰를 통해 서로의 의견을 교환하면서 다른 사람들의 의견을 수렴하는 것이 도움이 됩니다. 단일 책임 원칙이 적절하게 적용되었는지 확인하고, 개선할 부분이 있다면 찾아내는 것이 도움이 됩니다.
마무리
- 단일 책임 원칙(SRP)을 위반하면 코드의 복잡성이 증가하고 유지보수가 어려워집니다. 하나의 클래스에 많은 책임을 집어넣으면 코드가 길고 복잡해지며, 변경이 발생할 때마다 다른 책임과 관련 없는 코드까지 영향을 받을 수 있습니다.
- 단일 책임 원칙(SRP)을 따르면 클래스의 응집도가 높아지고, 이를 통해 인터페이스 분리 원칙(Interface Segregation Principle - ISP)과 의존성 역전 원칙(Dependency Inversion Principle - DIP)을 더욱 수월하게 적용할 수 있습니다.
- 개발자들은 단일 책임 원칙(SRP)을 염두에 두고 코드를 설계하고 리팩터링 하여 좀 더 유지보수가 쉬운 코드를 작성하는데 노력해야 합니다.
2023.06.05 - [Design Patterns] - 디자인 패턴 - 팩토리 패턴(factory pattern)
참고서적
- 디자인패턴의 아름다움
'Design Patterns' 카테고리의 다른 글
인터페이스 분리 원칙 - interface segregation principle, ISP (0) | 2023.07.28 |
---|---|
리스코프 치환 원칙 - Liskov Substitution Principle, LSP (0) | 2023.07.27 |
디자인 패턴 - 개방 폐쇄 원칙 (0) | 2023.06.08 |
디자인 패턴 - 팩토리 패턴(factory pattern) (0) | 2023.06.05 |
인터페이스를 이해하는 다양한 방법 (0) | 2023.06.05 |