Eternity's Chit-Chat

aeternum.egloos.com



유연한 설계를 위한 패턴과 원리 - 2.의도를 명확하게 3부 Supple Design

필요 없을 지도 몰라

Money 객체를 생성하기 위한 인터페이스를 완료했으므로 환율 계산에 필요한 로직을 생각해 보자. 문제 도메인을 간단하게 만들기 위해 구입, 구매, 송금 시의 환율은 동일한 것으로 가정하고 통화는 매일 한번만 변경된다고 가정한다.

어느 날의 미달러화와 원화 간의 환율이 다음과 같았다.

 

 기준 변환 환율
 미국 USD 대한민국 KRW 1027

 

1USD 1027원으로 환산된다. $1 = \1027이며 값은 USD 환율을 곱한 값이다. 역으로 1027원은 1USD 환산된다. \1027 = $1이며 값은 원화를 환율로 나눈 값이다. USD KRW 간의 환율이 표와 같다고 가정할 경우 다음과 같은 테스트 케이스가 필요하다.

  • $1 원화로 변환할 경우 \1027 얻기

  • \1027 USD 변환할 경우 $1 얻기

지금 상황에서 환율 계산에 관한 테스트를 통과시키기는 쉽지 않을 같다. TODO 목록으로 남겨 두고 작은 단계부터 밟아 나가자. 환율을 변환하기 위해서는 금액을 일정 값으로 곱하거나 나누어야 한다. 앞의 테스트 케이스에 따르면 USD 1027 곱하면 원화가 된다. 역으로 원화를 1027 나누면 USD 된다. , 원화에 1/1027 곱하면 USD 됨을 있다. 따라서 Money 간의 곱셈이 가능하다면 환율을 계산할 있을 것이다. Money 곱셈에 대한 테스트부터 통과시킨 환율 변환 로직을 구현하도록 하자. 금액을 배로 불린다는 의도를 나타낼 있도록 메소드 명으로 times() 선택했다.


MoneyTest.java
@Test
public void times() {

  Money dollar30cent15 = Money.dollars(30.15);

  assertEquals(Money.dollars(98.29), dollar30cent15.times(3.26));

}


30.15USD 3.26 하면 98.29USD 되어야 한다. Money 생성자에 통화의 유효 자릿수를 조정하는 로직이 들어 있기 때문에 앞에서 작성한 valueOf() 메소드를 사용해서 곱셈을 처리할 있다. Money VALUE OBJECT이므로 새로운 객체를 생성한 반환한다는 점에 주목하자. 테스트를 실행시켜 녹색 막대인지 확인한다.


Money.java
public Money times(double factor) {

  return Money.valueOf(getAmount().multiply(BigDecimal.valueOf(factor)),

    currency);

}


앞의 테스트에서는 기본 반올림 모드를 사용하는 경우의 곱셈 연산 결과를 검증했다. 가끔씩은 곱셈 결과에 대한 반올림 결과를 유연하게 처리하고 싶을 때가 있을 것이다. 그러나 핸드폰 과금 시스템의 요구사항을 살펴 보니 환율 변환 시에 기본 반올림 모드 이외에 다른 모드를 사용할 필요는 없을 같다. 따라서 반올림 모드를 매개변수로 취하는 times() 메소드를 오버로딩하지 않을 예정이다. 나중에 정말로 times() 메소드에 반올림 모드가 필요해지면 추가해도 늦지 않다.


“YAGNI(You Aren’t Gonna Need It)”라는 XP 슬로건은 종종 논쟁의 대상이 되곤 한다. YAGNI 지금 당장 기능이 필요하지 않다면 정말 필요해질 때까지 해당 기능을 구현하지 말라는 의미다.

이렇게 하는 번째 이유는 경제적인 때문이다. 만약 내일 필요하게 기능을 위해 작업해야 한다면, 이번 반복 동안에 개발되어야 기능에 쏟을 노력이 손실된다는 것을 의미한다. 릴리즈 계획은 지금 해야 하는 작업에 관한 것이고 미래를 위해 다른 일을 한다는 것은 개발자와 고객간의 합의에 반하는 것이다. … 이런 경제적인 불이익은 우리가 불필요한 것을 추가할 수도 있다는 가능성 때문에 더욱 커진다.

- Martin Fowler, Is Design Dead?

 

GENERIC SUBDOMAIN 대한 투자는 CORE DOMAIN 요구에 의해 주도되어야 한다는 점을 기억하자. 지금 곱셈을 처리하는데 다른 반올림 모드가 필요하지 않다면 프로젝트가 종료하는 순간까지도 필요하지 않을 지도 모른다. 따라서 그것이 정말로 필요할 때까지 해당 기능을 미루는 것이 좋다. 시스템에 요소가 추가된다는 것은 테스트, 문서화, 의사소통 해야 대상이 증가한다는 것을 의미한다. 따라서 시스템 구성 요소를 필요한 만큼만 최소로 유지할 필요가 있다. YAGNI 점을 강조한다.

그러고 보니 덧셈과 뺄셈, 나눗셈도 필요할 같다는 생각이 뇌리를 스친다. 지금 개발해야 할까? 경우 역시 YAGNI 나중으로 미루라고 충고한다. 정말로 필요한 상황이 오면 우리는 때가서 기능을 구현할 것이다. 물론 필요한 상황이란 비즈니스적으로 가치가 있을 때를 의미한다.