이 글은 필자의 이전 블로그인 https://velog.io/@beomdrive/NEXTSTEP-ATDD-1에서 객체지향 생활 체조 내용을 따로 분리한 후, 요약 및 추가 보완하였습니다.
객체지향 생활체조
NEXTSTEP ATDD에서는 과정을 시작하기 전, 객체지향 생활 체조 원칙이라는 개념과 함께 9가지의 원칙을 소개해준다.
강의에서는 따로 말해주지는 않지만 강의 자료에 아래와 같이 간략하게만 적혀있다.
규칙 1: 한 메서드에 오직 한 단계의 들여쓰기(indent)만 한다.
규칙 2: else 예약어를 쓰지 않는다.
규칙 3: 모든 원시값과 문자열을 포장한다.
규칙 4: 한 줄에 점을 하나만 찍는다.
규칙 5: 줄여쓰지 않는다(축약 금지).
규칙 6: 모든 엔티티를 작게 유지한다.
규칙 7: 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
규칙 8: 일급 콜렉션을 쓴다.
규칙 9: 게터/세터/프로퍼티를 쓰지 않는다.
이번 글에서는 간략하게 소개되어 있는 9가지의 원칙을 추가로 공부해보면서, 어디선가 한번쯤 들어본 파편화된 기억들을 제대로 정리해보려고 한다.
※ 머릿속을 정리하는 용도이니 아래부터는 제 자신과 얘기하는 대화체로 작성해봅니다.
1. 한 메서드에 오직 한 단계의 들여쓰기(indent)만 한다.
- 중첩 if 문을 지양한다 → 가독성 감소
- 메서드는 한가지의 일을 매우 잘하게끔 설계해야 하는데, 중첩문이 여러개일 경우(2단계 이상의 indent) 한가지 일만 하지 않을 확률이 높다고 생각함
- private 메서드는 추상화 레벨을 적절하게 맞춰서 잘 활용하는 것이 중요함
- 단, private 메서드가 너무 많이 생성된다면 해당 객체가 가지고 있는 책임이 단일 책임을 위배되지는 않는지 다시 한번 확인해볼 필요가 있음
2. else 예약어를 쓰지 않는다.
- else를 사용하면 위에 있는 모든 if 조건문을 일일히 타고 내려가면서 눈으로 확인해야됨
- early return 방식을 사용하면 좋을 듯 함
3. 모든 원시값과 문자열을 포장(Wrapping)한다.
- 단순히 리터럴 값만으로는 아무런 의미를 표현할 수 없다 (오직 변수명으로만 표현 가능)
- 객체로 포장한다면 상태를 객체 스스로 관리(유효성 검사 등)할 수 있고, 왜 사용하는지 보다 명확하게 전달 가능
- https://tecoble.techcourse.co.kr/post/2020-05-29-wrap-primitive-type/
- 관련 내용에서 더욱 심화 학습을 원하면 -> 일급 컬렉션(아래 8번 항목 참고)
4. 한 줄에 점을 하나만 찍는다.
.get.get 금지
- 디미터 법칙 : 멀리 떨어져 있는 낯선 객체에 메시지를 보내는 설계를 피하라
- 자기 자신의 메서드와 자기가 관리하고 있는 멤버 변수의 메서드까지만 호출해야함
- 객체 자신의 메서드들
- 메서드의 파라미터로 넘어온 객체들의 메서드들
- 메서드 내부에서 생성, 초기화된 객체의 메서드들
- 인스턴스 변수로 가지고 있는 객체가 소유한 메서드들
- 즉 한 다리 건넌 객체의 메서드를 호출하는 것은 디미터 법칙에 위배된다
- 자기 자신의 메서드와 자기가 관리하고 있는 멤버 변수의 메서드까지만 호출해야함
public class Member {
private Gender gender; // 인스턴스 변수 (4번)
public void addMember(Member member) { // 자기 자신 메서드 (1번)
// ....
}
public void updateMember(Age age) {
age.get(); // 2. 메서드의 파라미터로 넘겨받은 객체의 메서드 사용 (O)
}
public void Demeter_법칙을_잘지키기() {
addMember(new Member()); // 1. 객체 자기 자신의 메서드 사용 (O)
Name name = new Name("ALEX");
name.getFullName(); // 3. 메서드 내부에서 생성 및 초기화한 객체의 메서드 사용 (O)
gender.get(); // 4. 인스턴스 변수로 가지고 있는 객체가 소유한 메서드 사용 (O)
}
}
- 묻지 말고 시켜라 (Tell, Don’t Ask) : 객체의 상태는 객체 내부의 행위를 통해서만 변경해야 한다
- 직접 가져와서 조건식으로 판단하지말고 객체에게 직접 판단하라고 명령을 지시해야한다
- 캡슐화를 통해 객체는 자료를 숨기고 함수를 공개
5. 줄여쓰지 않는다. (축약 금지)
의도가 분명하게 이름을 짓자
- 변수명을 축약하면 한번에 알아보기가 힘들다 → 가독성 감소
- 문맥상 중복되는 단어는 자제하자 → 가독성 감소
- 클래스명에 이미 있는 내용을 변수에 또 쓰지 말자
(ex. Person 클래스의 getPersonName() → Person 클래스의 getName())
- 클래스명에 이미 있는 내용을 변수에 또 쓰지 말자
- 메서드명이 너무 길어서 축약할 경우, 메서드의 역할이 여러 개인지 먼저 확인하자
6. 모든 엔티티를 작게 유지한다.
- 50줄 이상 되는 클래스와 파일이 10개 이상인 패키지는 지양하라
- 즉 50줄 이상 되는 클래스는 한 가지 이상의 일을 할 확률이 높다
- 만약 클래스를 작게 작성하기가 애매할 경우(ex. 같이 있어야 되는 동작의 묶음이 있을 때)는 패키지를 최대한 활용한다
- 따라서 패키지 또한 클래스처럼 응집력 있고 단일한 목표가 있어야 한다
이 부분은 논란이 많은 내용이지만, 따로 찾아본 결과 OOP를 처음 연습할 때는 기준을 명확하고 구체적으로 잡야한다고 박재성님이 얘기하셨다. 따라서 그냥 수치적으로 기준을 50줄과 10개로 잡았지만 이를 맹신하기보다는 하나의 기준을 잡고 의식적인 연습을 해보라는 의도인것 같았다.
- [우아한테크세미나] TDD 리팩토링 by 자바지기 박재성님
7. 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
대부분의 클래스가 인스턴스 변수 하나만으로 일을 하는 것이 마땅하다. 몇몇 경우에만 두개의 변수가 필요할 때가 있다
- 마틴 파울러
- 인스턴스 변수가 많아질수록 클래스의 응집도는 감소
- 해당 법칙을 실현하려면 기존 하나의 객체에 매우 세부 객체들로 쪼개야 할 것 같음

8. 일급 컬렉션을 쓴다.
- 일급 컬렉션 : Collection을 Wrapping하면서, Wrapping한 Collection 외 다른 멤버 변수는 없는 객체
- 즉 오직 하나의 컬렉션을 상태로 가지고, 그 상태만을 위한 행위들을 제공하는 커스텀 자료구조
- 컬렉션의 불변을 보장하기 위해, 컬렉션의 값을 변경할 수 있는 메서드(Setter)가 없는 컬렉션을 만들자
- final 키워드는 불변을 만들어주는 것이 아닌 재할당만 금지
- 따라서 getter를 통해 내부 컬렉션을 그대로 반환하면 외부에서 값 변경이 가능하므로 getter도 지양하는 것이 좋아보임
- 값을 추가,수정,삭제는 필요한 기능만 메서드를 따로 만들어서 제공하는 것이 좋을 듯 함
- 내부적으로 validate 작업도 필요
- 만약 전체 컬렉션을 조회한다면 새로운 컬렉션을 생성해서 값을 담아 반환하는 것이 안전함 (얕은 복사 방지)
- 이로써 하나의 컬렉션 값이 일급 컬렉션 객체를 통해 상태와 행위를 한 곳으로 관리하는 효과를 가지게 된다
- 참고자료
9. 게터/세터/프로퍼티를 쓰지 않는다.
- 묻지 말고, 시켜라 (Tell, Don’t Ask) 원칙
- 객체에게 책임이 있는 작업은 객체에게 직접 시켜야 한다
- 객체의 자율성을 보장하며, 객체는 능동적으로 행동할 수 있도록 설계해야 한다
- 하지만 getter에 경우에는 예외적으로 Presentation 계층에서는 외부에 메시지를 전달해야 하므로 getter가 필요하다
- 따라서 getter는 정말 필요할 때만 사용하되, 무분별한 남발은 불필요한 객체 내부 구현의 노출로 이어진다
→ 응집도 하락 & 캡슐화 위반
- 따라서 getter는 정말 필요할 때만 사용하되, 무분별한 남발은 불필요한 객체 내부 구현의 노출로 이어진다
'멘토링 > NEXTSTEP ATDD' 카테고리의 다른 글
| 깊이 있는 6주간의 기록 대방출 (0) | 2024.07.22 |
|---|---|
| 테스트 방탄복을 입고, 리팩터링 전쟁으로 (0) | 2024.07.22 |
| 테스트와 인증(Auth)의 만남 (0) | 2024.07.22 |
| 테스트에 대한 고민 종결 (0) | 2024.07.21 |
| 인수 테스트 핥아보기 (0) | 2024.07.21 |