본문

SRP(Single Responsibility Principle) : 단일 책임 원칙

반응형

SRP(Single Responsibility Principle) : 단일 책임 원칙


결합도와 응집도

좋은 소프트웨어 설계를 위해서는 결합도(coupling)는 낮추고 응집도(cohesion)는 높이는 것이 바람직하다.

결합도는 모듈(클래스) 간의 상호 의존 정도로서 결합도가 낮으면 모듈 간의 상호 의존성이 줄어들어 객체의 재사용이나 수정, 유지보수가 용이하다.

응집도는 하나의 모듈 내부에 존재하는 구성 요소들의 기능적 관련성으로, 응집도가 높은 모듈은 하나의 책임에 집중하고 독립성이 높아져 재사용이나 기능의 수정, 유지보수가 용이하다.




객체 지향 세계에서 남자는 반드시 군대를 가고, 여자는 절대로 군대를 가지 않는다고 가정해 보자.

Ex 01)

1
2
3
4
5
6
7
8
9
class 사람 {
    String 군번;
    ...
}
 
사람 로미오 = new 사람();
사람 줄리엣 = new 사람();
 
줄리엣.군번 = "1249320";    // 아하?
cs


Ex01을 보면 사람형 참조 변수 줄리엣이 가진 군번 속성에 값을 할당하거나 읽어 오는 코드를 제제할 방법이 없다. 코드에서 향기가 아닌 냄새가 나고 있는 것이다. 위의 소스가 향기가 나도록 리팩터링해보자. 사람 클래스를 남자 클래스와 여자 클래스로 분할하고 남자 클래스에만 군번 속성을 갖게 하면 향기 나는 코드로 변모시킬 수 있다.

바로 단일 책임 원칙을 적용하는 것이다. 이때 남자 클래스와 여자 클래스에 공통점이 없다면 사람 클래스는 제거하면되고, 공통점이 많다면 사람 클래스는 상위 클래스로 해서 공통점을 사람 클래스에 두고 남자 클래스와 여자 클래스는 상속하고 차이점만 각자 구현하면 된다.


Ex 02)

1
2
3
4
5
6
7
8
9
10
11
12
13
class 강아지 {
    final static Boolean 수컷 = true;
    final static Boolean 암컷 = false;
    Boolean 성별;
 
    void 소변보다() {
        if (this.성별 == 수컷) {
            // 한쪽 다리를 들고 소변을 본다.
        } else {
            // 뒷다리 두 개를 굽혀 앉은 자세로 소변을 본다.
        }
    }
}
cs


Ex02를 보면 강아지가 수컷이냐 암컷이냐에 따라 소변보다() 메서드에서 분기 처리가 진행되는 것을 볼 수 있다. 

강아지 클래스의 소변보다() 메서드가 수컷 강아지의 행위와 암컷 강아지의 행위를 모두 구현하려고 하기에 단일 책임(행위) 원칙을 위배하고 있는 것이다. 메서드가 단일 책임 원칙을 지키지 않을 경우 나타나는 대표적인 냄새가 바로 분기 처리를 위한 if문이다

이런 경우 단일 책임 원칙을 적용해 코드를 리팩터링하면 예제03처럼 만들 수 있다.


Ex 03)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract class 강아지 {
    abstract void 소변보다()
}
 
class 수컷강아지 extends 강아지 {
    void 소변보다() {
        // 한쪽 다리를 들고 소변을 본다.
    }
}
 
class 암컷강아지 extends 강아지 {
    void 소변보다() {
        // 뒷다리 두 개를 굽혀 앉은 자세로 소변을 본다.
    }
}
cs


단일 책임 원칙과 가장 관계가 깊은 것은 바로 모델링 과정을 담당하는 추상화임을 알 수 있다.

애플리케이션의 경계를 정하고 추상화를 통해 클래스들을 선별하고 속성과 메서드를 설계할 때
반드시 단일 책임 원칙을 고려하는 습관을 들이자.





- 출처 및 참고자료 : 스프링 입문을 위한 자바객체지향의 원리와 이해(김종민 저)

반응형

공유

댓글