이펙티브 자바 아이템 51. 메서드 시그니처를 설계하라
를 읽으며 ‘매개변수는 짧게 유지하라’라는 항목에 대한 공부 중 최범균님의 프로그래밍 왕초식: 왕파라미터X 을 보게 되었다.
내용을 요약하면 ‘여러 메서드에서 파라미터로 같은 클래스 타입으로 선언된 변수를 받는 경우’를 심심치 않게 볼 수 있고, 이같은 방식은 메서드와 필드의 매핑을 기억력에 의존하게 되므로 향후 유지보수하기 어려운 코드를 작성하게 될 수 있어 메서드에 맞는 파라미터를 사용
하는 것을 권장한다는 것이다. 본 포스팅에서는 해당 유튜브 강의를 들으며 배운점과 느낀점을 간단히 정리해본다.
여기서 말하는 ‘왕 파라미터’ 란 여러 메서드에서 파라미터로 사용되는 몸집이 큰 파라미터(일종의 ’GOD클래스’)를 말한다. 아래 예시를 보면 이해하기가 더 쉬울 것이다.
public class Data {
private Long id;
...
// Getter, Setter
}
// 한 파라미터 타입(Data)을 여러 메서드에서 공유하는 구조
public void update(Data data) {
Some some = getSome(data); // Data 파라미터 사용
data.setKey(some.getKey());
int ret = otherDao.update(data); // Data 파라미터 사용
if (ret == 1) {
data.setReg(new Date());
anyDao.insert(data); // Data 파라미터 사용
}
}
Data 타입은 getSome(), otherDto.update(), anyDao.insert() 등 여러 메서드에서 파라미터로 쓰이는 ‘왕 파라미터’ 이다. 이 때 anyDao.insert() 메서드에 ‘ip’ 라는 값이 필요하다면 어떻게 할까? 단순히 Data 클래스에 ip 필드를 추가해줌으로써 해결할 수 있다.
public class Data {
private Long id;
...
private String ip; // 파라미터로 사용하는 Data 클래스에 추가 값을 위한 필드 'ip' 추가
// Getter, Setter
}
public void update(Data data) {
Some some = getSome(data);
data.setKey(some.getKey());
int ret = otherDao.update(data);
if (ret == 1) {
data.setReg(new Date());
data.setIp(some.getIp()); // anyDao.insert()에서 필요한 'ip' 값 세팅
anyDao.insert(data);
}
}
파라미터로 사용하는 클래스에 새롭게 필요한 필드만 추가(private String ip;
)해주었다. 또한 메서드에서도 필요한 필드의 값을 세팅하기 위한 코드만 추가(data.setIp(some.getIp());
)하면 되므로 전체 코드 작성량도 줄어드는 것처럼 보인다. 즉 이와 같은 한 ‘파라미터 타입을 여러 메서드에서 공유하는 구조’는 편하고 좋아보인다.
(이미지 출처: https://www.youtube.com/watch?v=MIYwej-VodE)
그러나 이 방식은 치명적인 단점이 있다. 사람인 이상, 어느 메서드에서 Data 클래스의 어느 필드값을 사용할지 모두 기억할 수 없기 때문이다.
즉, ‘파라미터 타입을 여러 메서드에서 공유하는 구조’ 를 사용하게 되면
당장은 위와같은 방식이 쉽고 편리하지만, 향후 유지보수성을 떨어뜨리는 결과를 초래한다.
다행히, 메서드에 맞는 파라미터를 사용
함으로써 이같은 문제를 해결할 수 있다.
(이미지 출처: https://www.youtube.com/watch?v=MIYwej-VodE)
‘한 파라미터 타입을 여러 메서드에서 공유하는 구조’ 대신 메서드에 맞는 파라미터(타입)를 사용
하자.
update() 메서드의 파라미터 타입으로 UpdateReq 을, otherDao.update()의 파라미터 타입으로 OtherUpdate를, anyDao.insert()의 파라미터 타입으로 AnyData를 사용했다.
이렇게 함으로써, 각 메서드에서 어떤 값을 사용하는지 알기 쉬워졌다.
즉, 메서드에 맞는 파라미터(타입)를 사용
하면
메서드에 맞게 새로운 파라미터 타입을 정의하는데 인색하지 말아야한다.
아래 두 가지 핵심 원칙을 지키며 개발함으로써 (시간을 포함한)개발 비용을 현저히 낮출 수 있다.
이전까지는 메서드에서 어떤 클래스의 어느 필드를 사용할 것인지는 해당 메서드를 뜯어보면 알 수 있는 것 아닌가라고 생각했었다. 그렇지만 내부 코드를 들여다봐야하는 것은 그 자체로 개발 생산성을 떨어뜨린다. 또한 메서드를 사용할 때 메서드 시그니처만 보고도 해당 메서드가 어떻게 동작할 지를 유추할 수 있어야 한다는 점에서 메서드에 맞는 파라미터(타입)를 사용
하는 것이 향후 유지보수성을 높이는 방법 중 하나임을 알 수 있었다. 이렇게 프로그래밍 초식을 하나씩 쌓아가다 보면 필자도 언젠가 보기 좋고 쓰기도 좋은 코드를 작성할 수 있게 되지 않을까라고 기대하며 이만 본 포스팅을 마친다.