본문 바로가기

Java

[Java] enum을 사용해 분기문을 없애보자.

웹 사이트에서 "정렬" 이라던가 파라메터에 따른 "로그"등을 남길 때 if문이 많이 사용 됩니다.
일반적으로 처음 사이트를 구축시
파라메터를 정해 놓습니다.
정렬에 대한 파라메터..

처음에는 각 파라메터와 그 파라메터가 뜻하는 것들을 주석으로 잘 달아 놓습니다.
그리고 이것을 처리하는 클래스는 일반적으로 아래와 같은 모양을 갖게 되는 경우가 많습니다.


이제 사이트가 만들어지고 , 다른 개발자들에 의해서 유지보수가 되고
요구사항으로 정렬조건등이 늘어나게 되면서
처음 달아놨던 주석은 엉망이 되고, QueryBuilder의 if문은 요구사항이 생길 때 마다 늘어나게 됩니다.
그나마 Builder 클래스를 로직이 필요한 곳에서 모두 공통으로 사용하고 있다면 상황은 좋은 편이겠지만
혹시라도 위 로직이 여기저기 퍼져있다면, 정렬 조건이 하나 추가 될 때마다 손대야 하는 클래스도 많아지고
if를 통한 분기문이 길어지면서 수정 시 오류를 일으킬 확률도 커지고...
보기도 안 좋아집니다.

그리고, 파라메터를 set하는 부분에서도 파라메터의 타입이 String이기 때문에
사실 P,N 등 개발자가 처음 설계 했을 때 의도했던 문자가 아닌 "POP", "NEW"등 어떤 String이 들어가도
이 소스는 에러를 일으키지 않습니다. 다만, 정상적으로 작동을 하지 않을 뿐이지요..

때문에 이런 정렬 타입이 추가 될 때마다 어딘가에 정리를 해야하고
유지보수 하는 사람은 이 정리 된 문서가 있어야 각각의 파라메터가 뜻하는 것을 알 수가 있습니다.

주석이라도 최신화가 되어 있다면 조금 낫겠지만
사실 그렇게 되기는 많이 어렵죠.


이미 제가 있는 이곳에도 저런 코드가 있어서..
이번에 enum을 활용해서 위 코드를 정리해보았습니다.

일단 enum 클래스를 정의 합니다.


이런식이 되겠죠.. 일단 골격만 잡았습니다.
그리고 RequestDomain 클래스에서 이 enum을 사용하도록 해야 합니다.


일단 이렇게 해봤는데..
레거시에서는 이미 파라메터를 String으로 Setting해주고 있습니다.
이 부분들을 모두 찾아 다니면서 SortCodeEnum 타입으로 set해주도록 수정하면 좋겠지만
현실적으로 어려운 일입니다. 그래서, 기존의 레거시를 최대한 활용하는 쪽으로 방향을 잡았습니다.


enum 클래스를 수정하여 생성자에서 코드의 뜻을 받아주도록 하였습니다.
그리고 그 코드의 로그를 받아 낼 수 있는 getter 메서드 (getCodeName)를 만들었습니다.
또한, 각 enum의 타입들이 쿼리를 가지고 그것을 리턴 할 수 있도록 getSortQuery 메서드를 정의 하여
각 enum 타입에서 오버라이드 하고 있습니다.

그럼 이것을 RequestDomain 클래스에서는 어떻게 사용할까요.


기존의 코드들이 이미 String으로 된 파라메터를 사용하고 있기 때문에
valueOf 메서드를 활용하여 그 파라메터를 가지고 SortCodeEnum 을 생성하여 그에 따른
CodeName과 SortQuery를 받아오고 있습니다.

이것을 QueryBuilder 클래스에 적용하면 아래와 같이 됩니다.

이렇게 enum으로 수정 할 때 제가 생각하는 장점은 이렇습니다.

1. 소스 그 자체가 최신화 된 정보를 가지고 있습니다.
 - 저는 프로그램을 개발하면서 가장 중요하다고 생각하는 것이 코드가 읽기 쉽게 작성되어야 한다. 라는 것 입니다.
   이 방식은 enum 클래스 그 자체가 항상 최신화가 되면서, 그 자체로 자기가 가지고 있는 뜻을 모두 보여주고 있습니다.
   특별히 주석을 보지 않아도, 문서를 만들지 않아도 유지보수를 하는 사람의 입장에서는 큰 문제는 없을 것 입니다.
2. 과도한 분기문을 줄여, 소스를 간단하게 만들 수 있습니다.
3. 정렬조건 추가나 수정등의 요구사항에 간단하게 대처 할 수 있습니다.
4. 위 예제에서는 sortCode 를 String으로 set 해주고 있지만, 만약 code 자체를 set 할 때도 SortCodeEnum 타입으로
set 할 수 있게 해준다면, 사용하는 입장에서는 그만큼 오류를 일으킬 확률이 줄어듭니다. 정해진 타입만 파라메터로
넘겨줄 수 있기 때문이죠.

위 코드에서 주의 할 부분이 있습니다.
enum의 valueOf 메서드를 사용하고 있는데..
만약 valueOf메서드의 파라메터인 sortCode가 SortCodeEnum 클래스에 정의되어 있지 않는다면
위 소스는 exception을 발생시킵니다. 따라서, 이에 따른 방어코드가 필요합니다.

위에서는 RequestDomain에 SortCodeEnum이 들어갔지만..
그냥 QueryBuilder 쪽에서 SortCodeEnum을 생성하여 처리하는 방법도 있을 것 입니다.
exception에 대한 대처는 후자가 더 유용 할 것 같네요.

그리고 enum 타입으로 생성되는 객체들은 싱글턴입니다.