SRP?
SRP(Single Responsibility Principle) : 단일 책임의 원칙
클래스를 설계할 때 하나의 책임만을 수행하는데에 집중되어 있어야 한다는 원칙!
무슨말인지 모르시겠죠..?
현실세계를 예를 들자면, 학생(Student)이라는 객체가 있다고 가정해봅시다.
학생(Student)는 대학생이라서 수강신청을 해야되는데, 학생이 스스로 수강과목(Course)를 고르는 행동이 존재하겠죠?
학생(Student)이 과목(Course)을 고르는 행위는 수강신청과정에서의 학생 이라는 SRP를 준수하는 행위입니다.
하지만,
학생(Student)이 수강과목(CourseName)을 변경한다는 행위를 가정해볼까요?
학생은 수강과목 리스트를 돌면서 바꾸고 싶은 과목이 있다면, 해당 수강과목을 바꾸는 행위를 하게 되겠죠.
이러한 행위를 다양한 방법으로 구현이 가능한대요.
- 과목(Course)의 이름(Name)을 바꾸는 방식
- 과목(Course)을 삭제하고 다시 추가하는 방식
위 방법중 어떤게 SRP를 위반하는 행위일까요?
한번 Code를 살펴봅시다!
구현 예제
우선, 과목(Course)라는 객체를 만들어보겠습니다!
package solid.srp;
public class Course {
private String name;
public Course(final String name) {
this.name = name;
}
public String getName() {
return name;
}
void setName(final String name) {
this.name = name;
}
}
과목(Course)라는 객체는 수강과목의 이름을 저장하고 조회하는 기능을 가지고 있습니다.
다음은, 학생(Student)라는 객체를 만들게요!
package solid.srp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Student {
private List<Course> courses;
public Student() {
courses = new ArrayList<>();
}
public void chooseCourse(final Course course) {
courses.add(course);
}
public void modifyCourse(final Course course, final String courseName) {
courses.stream()
.filter(schoolCourse -> schoolCourse.equals(course))
.forEach(schoolCourse -> schoolCourse.setName(courseName));
}
public void modifyCourse(final Course course, final Course modifidedCourse) {
courses.remove(course);
courses.add(modifidedCourse);
}
public List<Course> getCourses() {
return Collections.unmodifiableList(courses);
}
}
학생이라는 객체는 다음과 같은 기능이 있습니다
- 과목을 수강(addCourse)하는 기능
- 수강과목 리스트를 변경(modifyCourse)하는 기능
- 수강과목 조회(getCourses)하는 기능
저는 여기서 2가지 방법의 modifyCourse 메서드를 구현하였는데요
- 수강과목의 리스트를 순회하면서 이름을 변경(setName)하는 기능
- 수강과목을 삭제(remove)하고 새로운 수강과목을 삽입(add)하는 기능
구현하였으니 테스트하겠습니다!
package solid.srp;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class StudentTest {
@Test
void 학생이_과목을_올바르게_변경하는지_테스트_1번_케이스() {
/* Given */
Student student = new Student();
Course math = new Course("math");
Course english = new Course("english");
Course computer = new Course("computer");
List<Course> courses = Arrays.asList(math, computer);
/* When */
student.chooseCourse(math);
student.chooseCourse(english);
student.modifyCourse(english, "computer");
/* Then */
assertThat(student.getCourses()).isEqualTo(courses);
assertThat(english.getName()).isEqualTo("english");
}
@Test
void 학생이_과목을_올바르게_변경하는지_테스트_2번_케이스() {
/* Given */
Student student = new Student();
Course math = new Course("math");
Course english = new Course("english");
Course computer = new Course("computer");
List<Course> courses = Arrays.asList(math, computer);
/* When */
student.chooseCourse(math);
student.chooseCourse(english);
student.modifyCourse(english, computer);
/* Then */
assertThat(student.getCourses()).isEqualTo(courses);
assertThat(english.getName()).isEqualTo("english");
}
}
수강과목(Course) 객체를 생성하고, 리스트에 추가한뒤 변경하는 메서드를 실시합니다!
그리고, 내가 예상한 리스트와 결과가 올바른지 테스트하고, 과목객체가 그대로 있는지 테스트하는 코드입니다!
수행결과는?
1번 테스트케이스가 실패하게됩니다.
why?
학생이 수강과목의 이름을 변경할 때, 수강과목 객체를 변화시켰기 때문이죠.
다시말해서, 학생한테 책임이 한가지 더 부여하게 되는겁니다!
과목에 대한 책임을 가지게 되는거죠! -> 이게 바로 SRP를 위반하는 Code입니다
public void modifyCourse(final Course course, final String courseName) {
courses.stream()
.filter(schoolCourse -> schoolCourse.equals(course))
.forEach(schoolCourse -> schoolCourse.setName(courseName));
}
SRP위반 코드
public void modifyCourse(final Course course, final Course modifidedCourse) {
courses.remove(course);
courses.add(modifidedCourse);
}
SRP준수 코드
Why SRP?
- SRP를 준수해야하는 가장 기본적인 이유는, Domain 로직이 복잡해질수록 이해관계가 서로 엉키게 됩니다.
- 의존관계가 많아질수록 Class에 대한 부담이 커지게 되는데, 이는 유지보수의 어려움 혹은 버그 발생률이 증가하게 됩니다
그러니까, 우리 모두 Clean Coder가 되자구요~ㅎㅎ
참고
단일 책임 원칙
'Developer > Kotlin & Java' 카테고리의 다른 글
SOLID - LSP(Liskov Substitution Principle)이란? 리스코프 치환 원칙 (0) | 2019.11.22 |
---|---|
SOLID - OCP(Open Closed Principle) : 개방 폐쇄 원칙 (0) | 2019.11.17 |
[자바] 리플렉션 - Reflection (0) | 2019.04.11 |
[자바] 동기화 처리 - Synchronized 와 Asynchronized (2) | 2019.04.10 |
JVM에 대해 파해쳐보자 (0) | 2019.04.05 |