안녕하세요. 우아한 테크 코스2기로 활동한 김일호입니다.
이번에는 1주차 미션이었던 로또를 공부하며 고민하였던 내용 중 원시값 포장에 대해서 얘기 해보려고해요.

이번 미션을 통하여 고민했던 내용들을 남겨보도록 하겠습니다.

https://github.com/lkimilhol/java-lotto 에서 소스 코드를 확인 하실 수 있습니다.

1. 왜?


이번 미션에서 느꼈던 점 첫 번째 입니다 :)

바로 원시값의 포장인데요. 우리는 왜 원시값을 포장해야 할까요?
다음 코드를 보도록 하겠습니다.

int money = 100;

우리는 이 코드를 보고 money라는 변수에 100이라는 값이 담긴 것을 알 수 있습니다. 변수명을 보니 money, 즉 돈이 100이라는 것이군요!

우리는 이 돈을 더 할 수도 있습니다.

int money = 100;
money = money + 100;

money는 200이 되겠군요. 그렇다면 한번 값을 빼볼까요?

int money = 100;
money = money - 100; // 0
money = money - 100; // -100

초기 값으로 100이 대입 된 money라고 하는 변수에 100이라는 값을 뺐습니다. 그렇다면 money의 값은 0이 됩니다. 그럼 여기서 다시 100을 빼면 -100이 되고 money의 값은 -100이 됩니다.

우리는 여기서 한가지 고민을 해볼 수 있습니다.

바로 돈은 음수가 될 수 있을까?

2. 예외처리를 추가하자!


마이너스 통장... 이라는 개념도 있겠지만 우리가 만드는 로또 프로그램에서는 음수 값을 가지는 돈은 존재 할 수 없다라고 규칙을 추가해봅시다.

int money = 100;

if (money - 100 >= 0) {
	money = money - 100;
}

이렇게 작성하면 우리가 원하는 대로 음수 값을 가지게 되지 않을거에요. 그렇다면 우리는 프로그램 내에서 money라는 변수가 사용 되는 부분을 체크하고 이 값을 차감 할때는 매번 체크를 해 주어야 할까요?

그렇다면 정말 많은 부분에서 위의 코드는 중복이 될 거 같아요. 이 부분은 제 포스팅을 읽으시는 분들이라면 다들 공감 하실 거 같아요.

또 어떤 문제가 있을까요? 개발자가 실수로 음수값을 체크하는 로직을 넣어두지 않았다면 어떤 문제가 발생할까요? 우리는 money라고 하는 돈의 개념을 코드 안에서 안전 하게 사용 할 수 있을까요?

우리는 이런 고민을 할 때 원시값을 포장 하면 됩니다!

3. 값을 포장하자!


원시값 포장은 객체지향 생활체조 원칙에 나와있는 규칙 중 하나에요.

모든 원시값과 문자열을 포장하라

라는 구문이죠. 그렇다면 원시값 포장이라는 개념을 한번 코드로 보도록 하겠습니다. 우리가 사용했던 money 변수를 다음과 같이 표현해보죠.

public class Money {
    private final int amount;

    public Money(int amount) {
        checkNegative(amount);
        this.amount = amount;
    }

    public int amount() {
        return amount;
    }

    private void checkNegative(int amount) {
        if (amount < 0) {
            throw new IllegalArgumentException(ErrorMessage.MONEY_CANNOT_BE_NEGATIVE);
        }
    }
}

Money라고 하는 클래스입니다. 생성자로 amount라고 하는 값을 받네요. 인자가 있는 생성자가 하나 있어서 new Money()로 객체를 생성 할 수 없을거에요.

이 코드의 장점은 무엇일까요?

Money라고 하는 객체를 생성할때 음수값을 체크해주고 있어요. 때문에 우리는 Money 객체는 양수임을 보장 할 수가 있습니다. 생성 자체가 되지 않으니 맞겠죠?

따라서 돈을 표현 할 때 우리는 Money 클래스의 객체를 선언한다면 코드 내의 돈이라고 하는 개념은 절대 음수가 될 수 없을거에요. 이렇게 안전하게 코드를 작성 할 수 있습니다. 이렇게 되면 개발자가 실수 할 여지가 줄어들겠군요. 중복 코드도 없을테구요.

우리는 테스트 케이스를 작성하여 테스트가 통과 되는지 보고, 안전하게 Money 클래스 객체를 사용하면 됩니다! 기능이 추가 된다면 테스트 케이스를 작성해서 올바른 동작이 되는지 보고 우리가 개발하는 코드에 기능을 추가해도 좋겠네요.

위의 코드에는 금액을 차감하는 로직이 없네요. 한번 개발을 해보도록 하겠습니다.

테스트 케이스를 작성했어요. 실제 코드는 구현되지 않았으니 실패를 하겠네요.
코드를 작성하였습니다.

테스트 케이스를 실행합니다!

정상적으로 작동하네요. int 변수로 선언했던 위의 코드를 바꿔볼까요?

Money money = new Money(100);
Money result = money.sub(new Money(100));

System.out.println(result.amount());

의도한 결과가 나오는 것을 확인 할 수 있습니다!

  1. 마치며

이처럼 원시값을 포장하는 것은 우리의 실수를 줄이고 코드의 중복 또한 제거 된다고 생각하는데요. 생각나시는 장점이 있으시다면 코멘트를 남겨주세요. 함께 얘기해보면 좋겠네요 :)

여기까지 우아한 테크 캠프 프로2기 첫 번째 미션인 로또 미션을 하며 고민했던 내용 중 원시값 포장에 대하여 정리해보았습니다. 감사합니다!

PS. 원시값 포장을 하고 차감 로직을 구현 하였을 때 내부의 값을 수정하지 않고 새로 new Money로 return 하는것을 볼 수 있어요. 이는 Money를 불변 객체로 만들기 위함이고 자세한 내용을 포스팅을 작성해 보겠습니다 :)

profile
백엔드 개발자

0개의 댓글