객체지향 생활체조 원칙은 소트웍스 앤솔러지(ThoughtWorks Anthology) 라는 책에 나오는 원칙이다.
목차
- 한 메서드에 오직 한 단계의 들여쓰기(indent)만 한다.
- else 예약어를 사용하지 않는다.
- 모든 원시 값과 문자열을 포장한다.
- 일급 컬렉션을 쓴다.
- 한 줄에 점을 하나만 찍는다.
- 줄여 쓰지 않는다 ( 축약 금지 )
- 모든 엔티티를 작게 유지한다.
- 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
- Getter / Setter / Property를 쓰지 않는다.
한 줄에 점을 하나만 찍는다.
단순히 한 줄에 점의 개수를 헤아려 줄이라는것이 아닙니다. 점을 찍는 행위는 인스턴스의 접근을 하는 행위로 이는 호출자와 피호출자와의 결합도가 강하게 형성된다는 의미입니다.
이전시간인 일급 컬렉션에서 사용되었던 List<Student> students를 예시로 사용해보겠습니다.
public class Student {
private Name name;
private Age age;
private Score score;
.. Getter
}
Score 객체를 추가로 넣었습니다. 내부에는 int score가 존재합니다.
List<Student> 내에서 가장 점수가 높은 학생을 선발한다고 가정한다면
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
Student student = getTopScoreStudent(students);
}
private Student getTopScoreStudent(List<Student> students) {
Student topStudent = null;
for (Student student : students) {
if (topStudent == null) {
topStudent = student;
continue;
}
if (topStudent.getScore().getScore() < student.getScore().getScore()) {
topStudent = student;
}
}
return topStudent;
}
이렇게 작성될것입니다. 하지만 처음에 언급했듯이 이 클래스와 Score와는 아무런 관계가 없습니다 즉, 불필요한 결합도가 높아졌다는 것을 의미합니다. 만약 Student 객체에 대한 변경이 생긴다면? Score 객체에 대한 변경이 생긴다면? Score 의 멤버변수 타입이 변경된다면? 당연하게도 위에 메서드를 사용하고있는 객체에 변경이 불가피합니다. 그리고 변경과정에서 오류의 가능성도 증가하겠죠.
그럼 어떻게 해야하는지 차근차근 알아봅시다.
먼저 저번시간에 만들었던 것처럼 일급클래스를 적용시켜줍니다.
public class StudentList {
private final List<Student> students;
public Student getTopScoreStudent() {
Student topStudent = null;
for (Student student : students) {
if (topStudent == null) {
topStudent = student;
continue;
}
if (topStudent.getScore().getScore() < student.getScore().getScore()) {
topStudent = student;
}
}
return topStudent;
}
// 나머지 메서드 ...
}
일급 클래스만 적용시켜도 Main 클래스와의 결합도가 낮아졌습니다.
이제 Student 객체로 일을 넘겨보겠습니다.
public class StudentList {
private final List<Student> students;
public Student getTopScoreStudent() {
Student topStudent = null;
for (Student student : students) {
// 생략 ...
topStudent = topStudent.compareScore(student);
}
return topStudent;
}
// 나머지 메서드 ...
}
public class Student {
private Name name;
private Age age;
private Score score;
public Student compareScore(Student student) {
if (score.getScore() < student.getScore().getScore()) {
return student;
}
return this;
}
}
이제 마지막으로 Score 객체에 일을 넘겨보겠습니다.
public class Student {
private Name name;
private Age age;
private Score score;
public Student compareScore(Student student) {
Score compareScore = score.compareScore(student.getScore());
if (this.score == compareScore) { // 같은 주소값을 반환하기 때문에 == 를 사용했습니다.
return this;
}
return student;
}
// 이하 생략 ...
}
public class Score {
private int score;
public Score(int score) {
this.score = score;
}
public Score compareScore(Score arguScore) {
if (score < arguScore.getScore()) {
return arguScore;
}
return this;
}
// 이하 생략 ...
}
기존 코드와 달리 하위 객체의 일을 알 필요가 없어졌고 그저 자신의 일만 하게 되었습니다.
이로써 Main - StudentList - Student - Score 간에 결합도를 완전히 낮췄습니다.
결국 이 한 줄에 한 점을 찍는다는 의미는 자신이 알고있는 객체하고만 상호작용하면 되고 제 3자인 객체하고는 상호작용하지 않음으로써 결합도를 약하게 만들어 종속성을 최소화 시키는것입니다.
'Language > 객체지향' 카테고리의 다른 글
객체지향 생활체조 원칙 7. 모든 엔티티를 작게 유지한다. (0) | 2024.01.21 |
---|---|
객체지향 생활체조 원칙 6. 줄여 쓰지 않는다 (축약 금지) (0) | 2024.01.21 |
객체지향 생활체조 원칙 4. 일급 컬렉션을 사용한다. (0) | 2024.01.16 |
객체지향 생활체조 원칙 3. 모든 원시 값과 문자열을 포장한다. (0) | 2024.01.10 |
객체지향 생활체조 원칙 2. else 예약어를 사용하지 않는다. (0) | 2024.01.02 |