JAVA/ETC

[객체 지향 설계 5원칙 - SOLID] 1.SRP

자이구 2023. 12. 7. 13:29

Single Responsibility Principle : 단일 책임 원칙

 

 

다음 그림과 같이 남자라고 하는 클래스와 남자 클래스에 의존하는 다양한 클래스가 있다고 하자.

역활과 책임이 너무 많기 때문에 상당한 피로와 고통을 느낄 것이다. 

만약 남자가 직장에 짤려서 출근을 안하게 되어 그 스트레스를 여자친구, 어머니, 소대장에게 영향을 끼칠 수 있다.

따라서 이런 경우에 역활, 책임을 분리하라는 것이 단일 책임 원칙이다. 

 

위의 그림은 남자라는 하나의 클래스가 역활과 책임에 따라 네 개의 클래스로 쪼개진 것을 볼 수있다. 

직장에 짤리더라도 사원만 상처를 입으면 된다. 연인/모자관계 등에는 직장을 잃은 사원으로부터 영향을 받지 않는다.

하나의 클래스에 다수의 역활과 책임이 몰려 있을 때는 모두에게 문제가 생겼지만

클래스를 역활과 책임에 따라 분리해서 각각 하나의 역활과 책임만 갖게 하니 각각에게만 문제가 생겼다. 

 

단일 책임 원칙은 속성, 메서드, 패키지, 모듈, 컴포넌트, 프레임워크 등에도 적용할 수 있는 개념이다. 


속성이 SRP를 지키지 않는 경우

class 사람{
	String 주민등록번호;
	String 군번;
}    
    
사람 박지성 = new 사람();
사람 김연아 = new 사람();
    
김연아.군번 = "76035793"; // 여자가 군번을 갖고 있나??

 

사람형 참조 변수 김연아가 가진 군번 속성에 값을 할당하거나 읽어 오는 코드를 제어할 방법이 없다. 

이 문제나는 코드를 리팩터링해보자.

 

사람 클래스를 남자 클래스와 여자 클래스로 분할하고 남자 클래스에만 군번 속성을 갖게 하면 된다. 

바로 단일 책임 원칙을 적용하는 것이다. 이때 남자 클래스와 여자 클래스에 공통점이 없다면 사람 클래스는 제거하고

공통점이 많다면 사람 클래스를 상위 클래스로 해서 공통점을 사람 클래스에 두고 남자 클래스와 여자 클래스는 사람 클래스를 상속하고 차이점만 각자 구현하면 된다. 


 메서드가 SRP를 지키지 않는 경우

public class 강아지 {
	final static Boolean 숫컷 = true;
	final static Boolean 암컷 = false;
	Boolean 성별;

	void 소변보다() {
		if (this.성별 == 숫컷) {
			// 한쪽 다리를 들고 소변을 본다.
		} else {
			// 뒤다리 두 개로 앉은 자세로 소변을 본다.
		}
	}
}

 

메서드가 단일 책임 원칙을 지키지 않을 경우 나타나는 대표적인 코드가 바로 분기 처리를 위한 if문이다. 

강아지가 암컷이냐 수컷이냐에 따라 메서드에서 분기 처리가 진행되는 것을 볼 수 있다. 

강아지 클래스의 행위가 수컷 강아지의 행위와 암컷 강아지의 행위 모두 하려고 하기에 단일 책임 원칙를 위배하고 있다.

 

따라서 다음과 같이 코드를 리팩터링해보자

public abstract class 강아지 {
	abstract void 소변보다();
}

public class 숫컷강아지 extends 강아지 {
	void 소변보다() {
		// 한쪽 다리를 들고 소변을 본다.
	}
}

public class 암컷강아지 extends 강아지 {
	void 소변보다() {
		// 뒤다리 두 개로 앉은 자세로 소변을 본다.
	}
}

단일 책임 원칙과 객체 지향 4대 특성은 어떻게 결부돼 있을까?

 

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

애플리케이션 경계, 컨텍스트를 정하고 추상화를 통해 클래스들을 선별하고 속성과 메서드를 설계할 때 

반드시 단일 책임 원칙을 고려하는 습관을 들이자. 또한 리팩터링을 통해 코드를 개선할 때도 적용할 수 있는지 고려하자.


정리

  • 단일 책임 원칙은 클래스(객체)는 단 하나의 책임만 가져야 한다는 원칙
    - '책임' 이라는 의미는 하나의 '기능 담당'
    - 하나의 클래스는 하나의 기능 담당하여 하나의 책임을 수행하는데 집중되도록 클래스를 분리, 여러개 설계하라
  • 단일 책임 원칙의 목적은 프로그램의 유지보수성을 높이기 위한 설계 기법  
    - 하나의 클래스에 기능(책임)이 여러개 있다면 기능 변경(수정) 이 일어났을때 수정해야할 코드가 많아짐
    - SRP 원칙을 따름으로써 한 책임의 변경으로부터 다른 책임의 변경으로의 연쇄작용을 극복가능

 

책임의 범위는 딱 정해져있는 것이 아니고, 어떤 프로그램을 개발하느냐, 어플리케이션 경계에 따라 개발자마다 생각 기준이 달라질 수 있다. 따라서 단일 책임 원칙에 100% 해답은 없다.

 

 

 

📖Reference

  • 도서 '스프링 입문을 위한 자바 객체 지향의 원리와 이해'