Posts 객체지향 생활 체조 원칙
Post
Cancel

객체지향 생활 체조 원칙

객체지향 생활 체조 원칙이란?

객체지향 생활 체조 원칙은 ‘The ThoughtWorks Anthology’라는 책에서 제시하는 객체지향 프로그래밍을 구현하기 위한 9가지 원칙이다.

객체지향적 설계와 구현은 이론만 공부한다고 해서 되는 영역이 아니라 연습과 경험의 영역이다.

따라서 객체지향 생활 체조 원칙은 9가지 원칙을 통해 객체지향을 구현하는 구체적인 가이드를 제시한다.

객체지향 뿐만 아니라 클린코드의 느낌도 강하기 때문에 객체지향 생활체조 원칙을 통해 객체지향 프로그래밍 뿐만 아니라 가독성이 높고 유지보수가 쉬운 코드를 작성할 수 있다.

객체지향 생활 체조 원칙 9가지

1. 한 메서드에 오직 한 단계의 들여쓰기만 한다.

한 메서드에 여러 단계으 들여쓰기가 존재한다면, 그 메서드는 여려가지 일을 하고 있을 가능성이 크다.

또한 많은 들여쓰기는 가독성을 저해하며 결국 수정과 유지보수가 어려워진다.

따라서 하나의 메서드가 하는 일을 최소화(메서드 분리)하여 재사용성과 가독성을 높여야 한다.

2. else키워드를 쓰지 않는다.

else는 조건문 중첩을 일으키는 원인이며 결국 가독성을 저해하고 오류를 일으키는 부분이 되기도 한다.(switch-case도 동일한 문제가 있다.)

따라서 아래와 같이 return을 사용하는 것이 좋다.(Early Return패턴이라고도 한다.)

1
2
3
4
5
6
public Boolean isChristmas(int date){
  if (date == 25) {
    return true;
  }
  return false;
}

3. 모든 원시값과 문자열을 포장(Wrapping)한다.

원시값은 변수 이름만으로 그 의미를 파악할 수 있다. 또한 잘못된 값의 할당으로 프로그램의 오류가 발생하기도 한다. 따라서 아래와 같이 원시값을 객체로 선언(Wrapping)하는 것이 좋다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Age{
	private int age;
  
  Age(int age) {
    this.age = validate(age);
  }
  
  private int validate (int age) {
    if (age < 0) {
      throw new IllegalArgumentException("잘못된 값 입니다.");
    }
    return age;
  }
}
1
2
3
4
5
6
7
public class Parson {
  private final Age age;
  
  Parson(int age) {
    this.age = age;
  }
}

4. 코드 한 줄에 점(.)은 하나만 허용한다.

코드 한 줄에 여러 개의 점(.)이 있다는 것은 해당 라인이 다른 객체에 높은 결합도를 가지고 있다는 것을 의미하며 캡슐화가 깨져있을 확률도 매우 높다.

따라서 많은 점(.)을 이용하여 객체의 값에 접근하기보다는 객체 자체가 일을 하도록 코드를 작성하고 다른 객체와 메시지를 주고 받는 형태로 만드는 것이 바람직 하다.

디미터 법칙

낯선 이와 이야기하지 말라(Don’t Talk to Strangers) 또는 최소 지식 원칙(Principle of least knwoledge) 으로도 알려져있는 디미터 법칙은 객체 그래프를 따라 멀리 떨어진 객체에게 메시지를 보내는 설계를 피하라는 것을 의미한다.

자바 스트림과 같이 메서드 체이닝을 사용해야 하는 경우나 DTO와 같이 내부 데이터를 노출하는 역할을 가진 경우는 제외한다.

5. 축약하지 않는다.

과도한 축약은 코드의 가독성을 낮추기 때문에 필드나 메서드의 이름을 지을 때에는 너무 과도하게 축약하지 않는다.

클래스나 메서드의 이름이 너무 길다고 느껴진다면 너무 많은 역할을 하고 있을 가능성이 크다.

따라서 클래스와 메서드를 역할에 따라 분리하고 이름을 분리된 역할에 따라 지어주면 된다.

6. 모든 entity를 작게 유지한다.

50줄이 넘는 클래스와, 파일이 10개 이상인 패키지를 지양하자는 원칙이다.

50줄이 넘는 클래스는 너무 많은 역할을 가지고 있을 가능성이 크며, 가독성도 좋지 않다.

또한 파일이 10개 이상인 패키지는 너무 많은 목적을 가지고 있을 가능성이 크다.

따라서 클래스에 최소한의 역할을 부여하기 위해 클래스는 50줄이 넘지 않도록 작성하고, 클래스들의 응집도를 높이기 위해 패키지의 파일은 10개 이하로 구성하는 것이 좋다.

7. 2개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.

인스턴스 변수를 가진 클래스는 응집도가 떨어진다.

새로운 변수가 필요할 만큼 객체에게 부여된 역할에서 벗어난 다른 일을 하게 될 가능성이 크다.

이 때의 인스턴스 변수에서 일급 컬렉션과 Wrapper클래스는 제외된다.

따라서 인스턴스 변수가 추가되어야할 상황이라면 원시값의 Wrapping이나 일급 컬렉션을 통해 협력 클래스를 구성하거나 역할 분리를 통해 클래스를 나누는 것이 좋다.

8. 일급 컬렉션을 적용한다.

일급 컬렉션이란 아래와 같이 클래스 내부에 컬렉션이외에 다른 변수가 없는 상태를 말하며 컬렉션을 Wrapping한 형태이다.

1
2
3
4
5
6
7
public class Numbers {
  private final List<Integer> number;
  
  public Numbers(List<Integer> number) {
    this.number = number;
  }
}

일급 컬렉션을 통해 원시값의 Wrapping과 마찬가지로 변수에 대한 명확한 표현이 가능해지고, 컬렉션에 필요한 기능을 일급 컬렉션 내부에 구현하여 비즈니스에 종속적인 자료구조를 만들 수 있다.

또한 컬렉션의 재할당을 방지하여 불변성을 보장하고 값과 로직이 한 곳에 존재하여 유지보수에 유리하다.

9. getter/setter/property를 사용하지 않는다.

getter/setter/property의 사용은 객체의 값을 주고 받는 다는 점에서 캡술화를 깨는 원인이다.

또한 객체의 불러낸 값을 통해 동작을 하게되는 기능들은 객체의 외부에서 그 의도가 명확히 전달되지 않을 가능성이 크다.

따라서 객체가 스스로 일을 하게 만들고 값이 아닌 메시지의 전달만을 통해 기능을 구현하여 데이터를 보호하고 객체의 의도만을 드러내는 것이 좋다.

이를 위한 방법으로 객체의 상태를 전달하기 위해 DTO를 사용하거나 객체가 직접 행위를 하도록 코드를 구성하는 것이 좋다.


참고자료 :

catsbi.oopy.io

jamie95.tistory.com/99

This post is licensed under CC BY 4.0 by the author.

커밋 메시지 컨벤션

설치 및 시작