이번엔 널리 알려져서 누구나 다 알고 있을법한 (하지만 의외로 안지키는 사람도 많은) 방법을 소개한다.
Problems & Constraints
- 메서드를 오버로딩 해야한다.
- 입력 인자의 타입은 동일하며 그 유무만이 다르다.
e.g.> doSomething(a, b) and doSomething(a, b, c)
Solution
가장 많은 인자를 받는 메서드를 Master Method 로 정하고, 다른 메서드에서는 부족한 인자를 default 값으로 채워 Master Method 를 호출한다. 생성자(constructor) 구현 시에도 동일한 규칙이 적용된다.
Examples
int read(byte[] buf)
{ .. // tens of lines
}
int read(byte[] buf, int offset, int length)
{ .. // tens of lines
}
위에서 첫 번째 메서드는 두 번째 메서드의 특수한 형태로, offset 을 0으로, length 를 buf 의 size 로 해서 호출한 것과 완벽히 동일하게 동작한다. 따라서 첫 번빼 메서드는 아래와 같이 구현할 수 있다.
int read(byte[] buf)
{ return read(buf, 0, buf.size); // redirect to Master Method with appropriate parameters
}
Notes
Master Method 는 코드 중복 최소화 외에도, 오버로딩된 메서드들을 가지고 있는 클래스를 상속할 때 개발자 실수를 최소화 시킬 수 있다는 장점도 있다. 예를 들어, 오버로딩된 메서드 a, b, c 를 정의하고 있는 클래스 A 가 있다. 이 때 이를 상속한 클래스 B 에서 기능을 약간 변경하고자 할 때, Master Method 가 없다면 메서드 a’, b’, c’ 를 잊지 말고 모두 정의해줘야 한다. 실수로 무엇 하나를 빼먹었다면 의도치 않은 동작을 하게될 것이고, 그 원인을 찾기는 쉽지 않을 것이다. 하지만 만약 a 가 Master Method 였다면, a’ 만 재정의하면 문제를 미연에 예방할 수 있다. 따라서 Master Method 를 정하고, 어느 메서드가 Master 인지 명시하는 것이 좋다.
또, C++ 의 경우 Google 은 default parameter 를 흉내낼 목적으로는 사용하지 말기를 권고한다[4]. 그 단점을 아래와 같이 기술하고 있으니 참조하기 바란다.
One reason to minimize function overloading is that overloading can make it hard to tell which function is being called at a particular call site. Another one is that most people are confused by the semantics of inheritance if a deriving class overrides only some of the variants of a function. Moreover, reading client code of a library may become unnecessarily hard because of all the reasons against default function parameters.
If you want to overload a function, consider qualifying the name with some information about the arguments, e.g., AppendString(), AppendInt() rather than just Append().
References
- 권장 리팩터링 순서Recommended Sequence for Refactoring (wegra.org)
- 중복 제거: God Method (wegra.org)
- 중복 제거: Convert & Redirect (wegra.org)
- Google C++ Style Guide : Function Overloading (Google)