DTO로서 Map은 무척이나 유용하다.

오늘 EP2 코드리뷰중 격정적인 토론 끝난 후에 곰곰히 생각을 하다가 끝날 때쯔음에 Map으로 해야만 좋은 인터페이스를 발견을 하고야 말았다. 비즈니스 로직이나 Policy가 없는 단순한 값의 전달 객체에서는 필요한 데이터만 Map에 담아서 전달하는 것이 더 좋은 방법이 될수 있다는 것을 알았다.

구현에 의한 계약, 인터페이스에 의한 계약 등등의 이야기는 많이 들어봤을 것이다. 하지만, String에 의한 계약은 들어 본적이 없다. 컨벤션을 의미하는 것도 아니다. 내가 그냥 생각이 나서 적은 말이다.
CPDD이후 한번 더 유행을 시켜볼까? ㅎㅎㅎ

우리는 자주 name : value pair로 파라미터를 보낼 경우가 많이 있다. 대표적으로는 어떤 작업을 실행하고, HTTP를 이용해서 remote서비스에 심플하게 async를 처리할 때 많이 사용하는 방법이다. 여기서 name은 remote와의 계약이 되는 것이다. 즉, 파라미터 이름이라는 string타입에 글자에 대한 계약이다.

다음과 같은 스타일이겠지. 연동 스펙으로 파라미터명을 정의한다.
http://remote.ologist.co.kr/action?logNo=xxx&data=xxx...........


난 2가지 인터페이스를 제공하는 클래스를 만들었다.

1. Map을 이용한 인터페이스
executeRequest(Map param)

샘플코드)
Map<String, Object> param = new HashMap<String, Object>();
param.put("logNo" , vo.gertLogNo() );
param.put("data" , vo.getData() );
executeRequest(param);

2. Param이라는 markup인터페이스를 만들어서 파라미터로 넘어 갈수 있는 클래스라고 명시적으로 표시를 한다. Param인터페이스를 구현한 클래스만이 객체의 프로퍼티 이름으로 자동으로 name=value쌍으로 만들어서 외부에 제공을 한다.
executeRequest(Param paramVO)

샘플코드) DataParam implements Param이라고 가정하면,
DataParam paramVO = new DataParam();
paramVO.setLogNo(xxxx);
paramVO.setData(xxxx);
executeRequest(paramVO);

뭐..크게 달라보이지는 않는다. 난 상수도 아닌 string형태로 코드상에 존재하는 이름들을 별로 좋아하지 않는다.
POJO형태의 엔티티나 VO를 그냥 넘겨서 set이나 put을 하는 비용을 나름 줄이려고 하였다.

그래서, 난 후자쪽으로 개발을 주로 할려고 했다. 근데 여기서 커다란 오류가 하나 있다. 

다른 개발자나 시간이 지난 다음에 refactoring을 통해서 프러퍼티를 수정을 한다면 프러퍼티 이름이 바뀐다면, 내부에서는 문제가 없지만, 외부에 나갈 때 잘못된 파라미터로 나가게 되어서 예기치 않는 동작이 발생을 한다.
명시적으로 Implements Param이라고 되어 있으면 refactoring을 안 하겠지라는 생각을 처음에 했었지만, 이내 잘못된 생각임을 깨달았다.

아래와 같이 다른 의견도 있었지만,

excuteRequest(Object vo)

Param을 Object로 수정한다.
이 부분은 더 골때린다. 나조차도 그 객체가 파라미터 클래스로 쓰이는지 모른다. VO를 보고도 지맘대로 그 프러퍼티들이 파라미터로 사용되는지도 모른체 refactoring을 하려 할 것이다. 직렬화 할때의 transient처럼 annotation으로 풀수 있는 문제이긴 하지만, 내부적으로 사용하는 VO의 모든 특성들을 넘기는 문제도 발생을 한다.

executeRequest(Map param)

그래서, Map형태로만 넘길 수 있게 인터페이스를 제공하는 것이 안전한다. name이 string 형태로 되어 있으므로 VO의 rename refactoring에서 자유로울수 있고, 원하는 내용만 Data Transfer할수 있다.

DTO로서 Map을 사용할 때 2가지 장점
1. 원하는 데이터만 쉽게 담아서 보낼수 있다.
2. name이 String형태로 소스코드에 하드코딩되므로, VO를 rename refactoring을 하여도 remote에 전달하는 파라미터명(API상에 키값이 될것이다.)은 영향을 받지 않는다.
ex) map.put("name" , value);

아까는 Param을 Object로 바꾸겠다는 이야기를 했는데, 아예 Map형태로만 받도록 수정을 해야겠다.

공통으로 사용하는 인터페이스를 작성할 때에 고려할 사항이 많은데 코드의 라이프싸이클도 무척이나 중요하고, 수정이 되는 문제 등등을 고려하면 원천적으로 문제가 될만한 인터페이스나 코드를 가능한 줄이는 것이 좋을 것이다.

String형태의 하드코딩된 값들도 아름다울수 있다는 것을 깨달았다. 늦기전에 내일 바로 소스에 반영을 해야겠다.
Posted by ologist

블로그 이미지
ologist

공지사항

Yesterday191
Today134
Total34,706

달력

 « |  » 2012.02
      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      

최근에 받은 트랙백

글 보관함