[코드리뷰 스터디 - 🚗 자동차 경주] 원시값 포장

Hyunjoon Choi·2023년 9월 27일
0

코드리뷰 스터디

목록 보기
3/5
post-thumbnail

원시값 포장 적용 이전

자동차 경주 게임을 개발하며, 다음과 같은 상황에서 원시값 포장에 대해 적용하면 좋을 것 같다는 리뷰를 받았다.

public class Car {

    // 상수 등 기타 필드
    
    private final String name;
    
    private Car(String name) {
        this.name = name;
        // 이후 로직..
    }
    
    // 정적 팩터리 메서드 등 기타 다른 메서드들..
    
    public boolean hasName(String name) {
        return name.equals(this.name);
    }
    
    public String getName() {
        return this.name;
    }
}

위 코드에서 원시값 포장을 어떻게 적용할 수 있을까?

📦 원시값 포장이란

원시값 포장은, 원시 타입의 값의미 있는 객체로 포장하는 것을 뜻한다. 객체지향 생활체조 원칙에도 모든 원시값과 문자열을 포장(wrap)한다는 규칙이 있다.

그렇다면 원시 타입은 무엇이고, 의미 있는 객체로 포장하는 것이 무엇인지 각각 알아보자.

원시 타입

위키백과에서 원시 타입을 찾아보면, 다음과 같이 기술되어 있다.

원시 자료형(primitive data type)은 컴퓨터 과학에서 프로그래밍 언어가 제공하는 자료형 중 하나다. 원시형은 또한 내장형이나 기본형으로도 불린다.
언어와 그 구현에 따라서, 원시형은 메모리 상에 일대일로 대응되는 개체(Object)를 가질 수도 있다.

일반적으로 원시형은 다음과 같다.

  • 문자 (character, char);
  • 다양한 산술 정밀도를 갖는 정수 (integer, int, short, long, byte);
  • 부동소수점수 (float, double, real, double precision);
  • 다양한 정밀도와 프로그래머가 지정 가능한 크기를 갖는 고정소수점수 (fixed).
  • 불린 '참(true)'과 '거짓(false)' 값을 갖는다.
  • 참조 (포인터 또는 핸들로 불림), 다른 개체(Object)의 메모리상 주소를 참조하는 값.

즉, 위의 예시에서는 String 형태인 name이 원시값 포장이 가능한 예시가 될 수 있다.

의미 있는 객체로 포장

그러면 이제 이 name을 의미 있는 객체로 포장해보자.

클래스 이름 컨벤션

보통 자바 코드를 보면, int를 클래스로 만들 때 Integer, long을 클래스로 만들 때 Long으로 쓰는 등 첫 문자를 대문자로 표현한다. 이 규칙에 맞추어, name을 Name으로 포장하겠다.

생성된 Name 클래스

public class Name {

    private final String name;

    private Name(String name) {
        this.name = name;
    }

    public static Name from(String name) {
        return new Name(name);
    }

    public boolean isYourName(String name) {
        return name.equals(this.name);
    }

    public String getName() {
        return this.name;
    }
}

기존에 작성했던 Car 코드는 다음과 같이 변경된다.

public class Car {

    // 상수 등 기타 필드
    
    private final Name name;
    
    private Car(String name) {
        this.name = Name.from(name);
        // 이후 로직..
    }
    
    // 정적 팩터리 메서드 등 기타 다른 메서드들..
    
    public boolean hasName(String testName) {
        return this.name.isYourName(testName);
    }
    
    public String getName() {
        return name.getName();
    }
}

이렇게 원시값을 포장하면 어떤 점이 좋은 것일까?

원시값 포장의 장점

객체에게 자율성을 제공할 수 있다.

객체 공동체에 속한 객체들은 공동의 목표를 달성하기 위해 협력에 참여하지만 스스로의 결정과 판단에 따라 행동하는 자율적인 존재다. - 객체지향의 사실과 오해, 32p

원시값 포장을 활용하면 해당 객체에게 자율성을 제공할 수 있다. 기존에는 name이 Car에 종속되어 이름이 주어진 이름과 같은지 비교할 때도 Car에서 이루어졌지만, Name 클래스를 만들고 isYourName 메서드를 만듦으로써 Name에게 자율성을 제공하였다고 할 수 있다.

적절한 책임 부여가 가능하며, 유지보수성을 높일 수 있다.

시스템의 기능은 더 작은 규모의 책임으로 분할되고 각 책임은 책임을 수행할 적절한 객체에게 할당된다. 객체가 책임을 수행하는 도중에 스스로 처리할 수 없는 정보나 기능이 필요할 경우 적절한 객체를 찾아 필요한 작업을 요청한다. - 객체지향의 사실과 오해, 132p

또한 Car 객체에 부여되어있는 책임을 분할함으로써 더 완성도 있는 객체지향적 코드를 짤 수 있다. 예시로 자동차 경주 미션에서는 다음과 같은 조건이 있었다.

자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.

만약 원시값 포장을 만들지 않았다면, 이런 부가적인 기능들이 생길 때 마다 Car에게 직접 할당해줘야 한다.

더불어, 만약 name이 여러 클래스에서 사용된다면 어떨까? name이 사용되는 모든 클래스들에 다 들어가서 일일히 기능들을 작성해야 할 것이다.

따라서 원시값 포장은 적절한 객체에게 적절한 책임을 부여할 수 있도록 해 주며, 유지보수성 또한 높여줄 수 있다는 장점이 있다.

부족하거나 보완할 점이 있다면 댓글 부탁드립니다 😃

profile
개발을 좋아하는 워커홀릭

2개의 댓글

comment-user-thumbnail
2023년 9월 27일

크 👍

1개의 답글