단일 책임 원칙은 클래스, 객체 혹은 모듈이 하나의 책임을 가져야 한다는 원칙이다.
그렇다면 책임은 무엇일까?
책임이란 클래스 또는 객체가 하나의 작업이나 기능을 수행해야한다는 원칙이다.
그런데 책임이란 이런 작업이나 기능이보다는 역할이라는 말이 더 적합하다.
비디오 가게 코드를 예시로 보면
import java.util.ArrayList;
import java.util.List;
public class VideoStore {
private List<Video> videos;
public VideoStore() {
videos = new ArrayList<>();
}
public void addVideo(Video video) {
videos.add(video);
}
public void rentVideo(String title) {
for (Video video : videos) {
if (video.getTitle().equalsIgnoreCase(title)) {
video.rent();
return;
}
}
}
public void returnVideo(String title) {
for (Video video : videos) {
if (video.getTitle().equalsIgnoreCase(title)) {
video.returnVideo();
return;
}
}
}
}
VideoStore 클래스는 비디오 가게에 비디오 리스트를 가지고 있고 추가, 대여, 반납 하는 기능이 있다.
VideoStore 클래스는 단일 책임 원칙이 잘 지켜지고 있다. 비디오 가게라는 역할에 맞는 기능들만을 가지고 있기 때문이다.
단일 책임 원칙을 지키게되면 좀 더 객체지향적으로 프로그래밍 할 수 있고, 다음과 같은 장점을 가질 수 있다.
- 높은 응집도
- 유지보수성
- 변경 용이성
import java.util.ArrayList;
import java.util.List;
public class VideoStore {
private List<Video> videos;
private List<User> users;
public VideoStore() {
videos = new ArrayList<>();
}
public void addVideo(Video video) {
videos.add(video);
}
public void rentVideo(String title) {
for (Video video : videos) {
if (video.getTitle().equalsIgnoreCase(title)) {
video.rent();
return;
}
}
}
public void returnVideo(String title) {
for (Video video : videos) {
if (video.getTitle().equalsIgnoreCase(title)) {
video.returnVideo();
return;
}
}
}
public void addUser(User user) {
users.add(user);
}
}
위의 코드는 단일 책임 원칙이 깨진 코드이다.
VideoStore가 비디오만 관리하는 것이 아니라 사용자 정보도 관리하기 때문에 VideoStore는 두 가지 역할을 가지고 있다.
물론 이런 경우에도 기능을 정상적으로 작동할 것이고 문제가 없을 가능성이 크다.
다만 이렇게 단일 책임 원칙이 깨지게 되면, 클래스의 역할 즉 클래스가 해야할 일은 모호해지고, 변경에 대한 복잡도가 증가하게 되어 유지보수성이 떨어진다.
SRP를 지킨 코드
VideoManager
public class VideoManager {
private List<Video> videos = new ArrayList<>();
public void addVideo(Video video) {
videos.add(video);
}
public void rentVideo(String title) {
for (Video video : videos) {
if (video.getTitle().equalsIgnoreCase(title)) {
video.rent();
return;
}
}
}
public void returnVideo(String title) {
for (Video video : videos) {
if (video.getTitle().equalsIgnoreCase(title)) {
video.returnVideo();
return;
}
}
}
}
UserManager
public class UserManager {
private List<User> users = new ArrayList<>();
public void addUser(User user) {
users.add(user);
}
}
VideoStore
public class VideoStore {
private VideoManager videoManager = new VideoManager();
private UserManager userManager = new UserManager();
public void registerVideo(Video video) {
videoManager.addVideo(video);
}
public void registerUser(User user) {
userManager.addUser(user);
}
// business
}
비디오를 관리하고 사용자를 관리하는 것은 각각 VideoManager와 UserManager가 책임을 가지고 있다
그리고 이 Manager들을 활용하여 VideoStore Business 로직을 구현 한다