Eternity's Chit-Chat

aeternum.egloos.com



유연한 설계를 위한 패턴과 원리 - 3.리팩토링을 통한 진보 1부 Supple Design

사전 설계의 맹점

현재의 환율 설계에는 가지 문제점이 존재한다. 시점에 KRW USD간에는 하나의 환율 정보만 존재해야 한다. 우리가 작성한 코드에서도 그럴까? 다음의 테스트 코드를 살펴보자.

 

ChangeBoothTest.java

@Test

public void shouldExistUniqueExchangeRate() {

  ChangeBooth changeBooth = new ChangeBooth();

  changeBooth.addExchangeRate(Money.USD, Money.KRW, 1027);

  changeBooth.addExchangeRate(Money.USD, Money.KRW, 1035);

  assertEquals(1, changeBooth.getExchangeRateSize());

}

 

환율의 전체 개수를 반환하는 getExchangeRateSize() 메소드를 추가하고 테스트를 실행하자.

 

ChangeBooth.java

int getExchangeRateSize() {

  return rates.size();

}

 

빨간 막대다. 코드를 살펴보니 ExchangeRate equals() hashCode()에서 기준 통화와 대상 통화뿐만 아니라 비율도 함께 비교하기 때문에 서로 다른 객체로 판단한다는 것을 있다. 그렇다면 equals() hashCode()에서 기준 통화와 대상 통화만을 비교하도록 수정하면 테스트를 통과하지 않을까? 물론 비교 로직에서 비율을 제거하면 테스트를 통과시킬 수는 있다. 그러나 환율은 기준 통화, 대상 통화, 비율의 가지 값이 모두 같을 경우에만 동일하다고 있다. , 기준 통화와 대상 통화만으로 환율의 동일성을 판단하는 것은 도메인 내의 환율 개념과 상반된다.

 

문제의 원인은 환율이라는 도메인 개념을 이해하고 있다는 사실에 기인한다. 환율은 동일성의 대상이 아니다. KRW USD 간의 환율이 1270원인 경우와 KRW USD 간의 환율이 1250 경우를 비교하는 것은 의미가 없다. KRW USD 간의 환율은 하나만 존재해야 하기 때문이다. 만약 어느 시점에 KRW USD 간에 개의 환율 정보가 존재한다면 도메인과 연관된 개념적 무결성이 깨지게 된다. 통화의 개념에 있어 중요한 것은 동일성이 아니라 유일성이다.

 

도메인의 개념을 명확하게 반영하기 위해서는 환율의 유일성에 초점을 맞추어야 한다. 어느 시점의 통화 간에는 단지 하나의 환율 정보만 존재해야 한다. 환율이란 기준 통화, 대상 통화, 비율로 이루어진 의미 단위가 아니라 단지 시간에 따른 기준 통화와 대상 통화 간의 비율 변화를 의미한다.

 

도메인의 개념과 코드 사이의 의미적 거리가 멀어지면 멀어질수록 사소하지만 미묘한 버그가 발생할 가능성 또한 높아진다. 테스트를 통과시키기 위해 비교 로직에서 비율을 제거하는 것보다는 도메인 개념을 코드 내에 명확하게 표현함으로써 도메인과 코드 간의 거리를 좁히는 것이 적절한 방법이다.

 

결국 ExchangeRate 사용해서 환율 정보를 표현한 것은 과도한 설계였으며 도메인 요구사항을 명확하게 표현하지 못한다는 결론을 내렸다. 필요한 것은 기준 통화와 대상 통화 쌍에 대해 유일하게 하나의 환율을 유지할 있는 설계이다. 리팩토링 타임이다.

 

ChangeBooth 클래스가 ExchangeRate 클래스를 효과적으로 캡슐화하고 있으므로 ExchangeRate 관련된 구조를 수정한다고 해서 클라이언트에 영향을 미치지는 않을 것이다. 시간에 따른 기준 통화와 대상 통화 간의 비율 변화라는 환율의 의미를 코드 상에 명시적으로 표현하기 위해잠깐, 우리가 아직 시간에 관련된 GENERIC SUBDOMAIN 다루지 않았던가? 일단 지금 당장은 시간이라는 개념이 제외된 환율 개념을 다루도록 하고 나중에 리팩토링을 통해 시간 개념을 추가하도록 하자.