250x250
반응형
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Archives
Today
Total
관리 메뉴

재 현

원시값 포장이란? 본문

Development

원시값 포장이란?

본명은이점례 2023. 11. 2. 20:40
728x90

미션을 진행하면서 원시값 포장을 고려한다면?이라는 리뷰를 받았다.

 

 

그럼 원시값 포장이란 무엇일까?

 

원시값이란 우리가 잘알고 있는 것처럼, 기본 데이터 타입의 값을 가리키는 용어이다. 예를 들면 int, double, float, boolean 값이다. 그렇다면 이걸 포장하는 건 무슨 의미일까?

 

포장(Wrapping)이란 말그래도 감싸는 것이다. 그래서 기존의 함수나 모듈을 수정하지 않고 새로운 동작을 추가하거나 변경할 수 있다.

 

도대체 무슨 말일까?

 

코드를 예시로 들어보자.

 

int number = 0;
Number number = new Number(0);

 

우리는 두 방법을 사용해 생성할 수 있다.

1번은 단순히 int값에 넣는 것이고, 2번은 Number란 클래스로 값을 포장한 것이다.

 

그렇다면 2번 방법을 사용해 얻는 이점이 무엇일까?

 

 

 

 

 

1. 자신의 상태를 객체 스스로 관리한다.

자신의 상태를 객체 스스로 관리한다... 이건 무슨 말일까?

 

public class User {

    private String numbers;

    public User User(String numbers) {
        validateInputNumbers(numbers);
        this.numbers = numbers;
     }

     public void validateInputNumbers(String numbers) {
     }
 
 }

 

이런 코드가 있다고 쳐보자. User 클래스가 input을 받아와서 직접 input에 대한 검증을 하고 있다. 하지만 만약에 numbers 뿐만 아니라 name도 받고 age도 받고 해야 한다면??

 

public class User {

    private int age;
    private String name;
    private String numbers;

    public User User(int age, String name, String numbers) {
    	validateAge(age);
        validateName(name);
        validateInputNumbers(numbers);
        this.numbers = numbers;
     }

     public void validateInputNumbers(String numbers) {
     }
 
 }

 

이런 식으로 추가되는 인스턴스 필드마다 계속해서 validate 함수를 만들어내야 할 것이다. User 클래스가 한 번에 한 가지 일만 해야 하는데, 여러 일을 하게 생겼다. 좋지 않다.

 

그래서 이에 대한 해결책으로 포장을 할 수 있다.

 

public class User {

    private Name name;
    
    public User User(String name) {
    	name = new Name(name);
    }

}

public class Name {

    private String name;

    public Name Name(String name) {
        validateName(name);
        this.name = name;
     }

     public void validateName(String name) {
     }
 
 }

 

이런 식으로 Name이라는 클래스를 만들어 포장한다면? User는 name객체가 스스로 검증할 수 있도록 책임을 나눌 수가 있다. 

 

 

 

2. 자료형에 구애 받지 않는다

 

public class User {

    private int number;
    
    public User User(int number) {
    	this.number = number;
    }

}

 

이런 User 클래스가 있다고 해보자, 처음에 요구사항에 따라서 int형을 받도록 되어 있었다. 근데 요구사항이 double로 바뀐다면 어떻게 할까? 일일이 double로 수정해줘야 할 것이다. 이는 유지보수 하기 어렵다.

 

 

만약에 값을 포장했다면?

 

 

public class Number {

   private int number;
   
   public Number Number(int number) {
       validate(number);
       this.number = number;
   }

   public void validate(int number) {
   }

}

 

처음 Number 클래스는 int형을 받도록 되어 있다. 여기에 double 자료형만 추가하면 된다.

 

public class User {

    private Number number;
    
    public User User(double number) {
    	this.number = new Number(number);
    }

}


public class Number {

   private int number;
   private double doubleNumber;
   
   public Number Number(int number) {
       validate(number);
       this.number = number;
   }
   
   public Number Number(double number) {
       validate(number);
       this.doubleNumber = number;
   }

   public void validate(int number) {
   }
   
   public void validate(double number) {
   }

}

 

User 객체는 Number의 상태에서 몰라도 된다. 바뀐 double 값을 넣어주면 되고, 이에 대한 상태 관리는 Number 클래스가 하면 된다. 즉, 기존의 Number 변수를 없앨 필요가 없다. 기존 Number  클래스를 활용하면 된다. doubleNumber라는 멤버변수를 추가하고, 생성자 오버로딩을 통해 간단히 해결할 수 있다. String 값이 필요하다 해도 마찬가지로 해결이 가능하다.

 

 

3. 유지보수에 도움이 된다.

원시값 포장을 하게 되면 명시적으로 값의 의미를 부여할 수 있게 된다. 이 말이 무슨 말일까?

 

 

public class WinningLotto {
    ...
    private Lotto winningLottoNumbers;
    private int bonusNumber;

    public WinningNumber(Lotto winningLottoNumbers, int bonusNumber) {
        this.winningLottoNumbers = winningLottoNumbers;
        if (isBonusNumberDuplicatedWithWinningNumber(winningLottoNumbers, bonusNumber)) {
            throw new IllegalArgumentException(
                BONUS_CANNOT_BE_DUPLICATE_WITH_WINNING_NUMBER);
        }
        if (bonusNumber < 1 | bonusNumber > 45) {
                throw new RuntimeException();
        }
        this.bonusNumber = bonusNumber;
    }
    ...
}

 

위 클래스를 보면 bonusNumber을 int 자료형으로 두고 있다. 만약에 1~45까지가 아니라 요구사항이 1~10까지로 변한다면? 우리는 WinningLotto 클래스와 Lotto 클래스에 들어가서, 45를 10으로 일일이 수정해야 한다. 하지만 int 자료형을 포장한다면?

 

public class WinningLotto {
    ...
    private Lotto winningLottoNumbers;
    private LottoNumber bonusNumber;
    public WinningNumber(Lotto winningLottoNumbers, LottoNumber bonusNumber) {
        this.winningLottoNumbers = winningLottoNumbers;
        if (isBonusNumberDuplicatedWithWinningNumber(winningLottoNumbers, bonusNumber)) {
            throw new IllegalArgumentException(
                BONUS_CANNOT_BE_DUPLICATE_WITH_WINNING_NUMBER);
        }
        this.bonusNumber = bonusNumber;
    }
    ...
}

 

우리는 WinningLotto 클래스와 Lotto 클래스는 변경할 필요가 없다. 단순히 LottoNumber 클래스에 들어가 변경해 주면 된다. 유연한 변경이 이루어지는 것이다.

 

 

 

 

 

 

 

 

 

참고


https://tecoble.techcourse.co.kr/post/2020-05-29-wrap-primitive-type/

https://velog.io/@kanamycine/Java-%EC%9B%90%EC%8B%9C%EA%B0%92-%ED%8F%AC%EC%9E%A5

https://flight-developer-stroy.tistory.com/46

728x90