Closed IAGREEBUT closed 2 months ago
Q.
도우미 메서드 방식을 이용하여 문제점을 해결한 예시를 혹시 들어주실 수 있을까요?
A.
다음과 같은 코드를 봅시다.
class TestClass {
public TestClass(){}
public int add(int a, int b) {
return a + b;
}
public int multiply(int a, int b) {
int res = 0;
for (int i = 0; i < b; i++) {
res += add(a, b);
}
return res;
}
public int pow(int a, int b) {
int res = 0;
if (b == 0 || a == 1) {
return 1;
}
if (b == 1) {
return a;
}
for (int i = 0; i < b - 1; i++) {
res += multiply(a, a);
}
return res;
}
}
class TestSubClass extends TestClass {
@Override
public int add(int a, int b) {
return a + a - b;
}
@Override
public int multiply(int a, int b) {
System.out.println("a : " + a + " b : " + b);
return super.multiply(a, b);
}
public void printMultiplyResult(int a, int b) {
multiply(a, b);
}
public void additionalMultiply(int a, int b, int c) {
multiply(multiply(a, b), c);
}
}
public class HelperMethodTest {
public static void main(String[] args) {
TestClass test = new TestSubClass();
// do something with test...
}
}
- `TestClass`를 상속받은 `TestSubClass`는 `TestClass`에서 구현한 메서드를 사용하여 추가적인 기능들을 덧붙였습니다.
- TestSubClass에서 `multiply()` 메서드를 재정의했는데 내부적으로는 `add()` 메서드를 사용합니다. 그런데 `add()` 메서드도 `TestSubClass`에서 재정의되었으므로 재정의된 `add()` 메서드를 사용하게 됩니다.
- 문제는 재정의된 `add()` 메서드가 곱셈 연산을 정의하는 `multiply()`에 사용되기에 적절하지 않다는 것입니다. 따라서 기대하던 값과는 전혀 다른 결과가 반환되게 됩니다.
- 이를 막기 위해서 재정의 가능한 코드(위 코드에서는 `add()`, `multiply()`, `pow()`가 될 것입니다.)를 사용하는 코드들을 제거하는 방식이 private helper method 입니다.
- 책에서 제시하는 방법을 따라가 봅시다. 먼저 각각의 재정의 가능한 메서드의 본문 코드를 private helper method로 옮긴다 부터 진행해 봅시다.
- helper method는 질문에서 제시한 것 처럼 공통적으로 반복되는 특정 작업을 수행하는데 사용됩니다.
- 위의 코드에서는 `add()`, `multiply()`가 공통적으로 반복되는 작업이 됩니다. 이를 helper method가 처리하도록 만들어주며, 외부에서 접근할 수 없도록 `private` 지정자를 붙여 주는 것입니다.
- 첫 step의 결과는 다음과 같습니다. 재정의 가능한 메서드들의 리턴 값이 없는 것은 의도한 것으로, 다음 step을 위해 비운 것입니다.
``` java
class TestClass {
public TestClass(){}
public int add(int a, int b) {
}
public int multiply(int a, int b) {
}
public int pow(int a, int b) {
}
private int addNumber(int a, int b) {
return a + b;
}
private int multiplyNumber(int a, int b) {
int res = 0;
for (int i = 0; i < b; i++) {
res += add(a, b);
}
return res;
}
private int powNumber(int a, int b) {
int res = 0;
if (b == 0 || a == 1) {
return 1;
}
if (b == 1) {
return a;
}
for (int i = 0; i < b - 1; i++) {
res += multiply(a, a);
}
return res;
}
}
// TestSubClass, HelperMethodTest Code...
다음 step으로 넘어가 봅시다. 다음 step은 이 도우미 메서드를 호출하도록 수정해주는 것입니다.
class TestClass {
public TestClass(){}
public int add(int a, int b) {
return addNumber(a, b);
}
public int multiply(int a, int b) {
return multiplyNumber(a, b);
}
public int pow(int a, int b) {
return powNumber(a, b);
}
// private helper method
}
class TestClass {
public TestClass(){}
public int add(int a, int b) {
return addNumber(a, b);
}
public int multiply(int a, int b) {
return multiplyNumber(a, b);
}
public int pow(int a, int b) {
return powNumber(a, b);
}
private int addNumber(int a, int b) {
return a + b;
}
private int multiplyNumber(int a, int b) {
int res = 0;
for (int i = 0; i < b; i++) {
res += addNumber(a, b); // change method call
}
return res;
}
private int powNumber(int a, int b) {
int res = 0;
if (b == 0 || a == 1) {
return 1;
}
if (b == 1) {
return a;
}
for (int i = 0; i < b - 1; i++) {
res += multiplyNumber(a, a); // change method call
}
return res;
}
}
class TestSubClass extends TestClass {
@Override
public int add(int a, int b) {
return a + a - b;
}
@Override
public int multiply(int a, int b) {
System.out.println("a : " + a + " b : " + b);
return super.multiply(a, b);
}
public void printMultiplyResult(int a, int b) {
multiply(a, b);
}
public void additionalMultiply(int a, int b, int c) {
multiply(multiply(a, b), c);
}
}
public class HelperMethodTest {
public static void main(String[] args) {
TestClass test = new TestSubClass();
// do something with test...
}
}
이 과정을 통해 완벽하게 재정의 가능한 코드를 호출하는 코드가 사라졌습니다.
새로운 기능을 추가하고, 이 기능이 재정의 가능 메서드를 호출해야 하더라도, 해당 기능을 수행하는 helper method가 이미 존재하고 있기 때문에 재정의 가능 메서드를 호출하는 대신 helper method를 호출하게 구현하면 됩니다.
이제 TestClass의 재정의 가능한 메서드들은 다른 메서드를 호출하지 않고 독립적입니다.
클래스의 내부 구현은 일부러 재정의 가능 메서드를 호출하는 상황을 보여주기 위해 비 효율적으로 구현한 것으로 어디까지나 참고만 해주시면 감사하겠습니다.
128page
라는 말이 나오는데 위의 상황에서 도우미 메서드 방식을 이용하여 문제점을 해결한 예시를 혹시 들어주실 수 있을까요?)
<추가> java의 helper method에 대해 구글링 해봤는데 이 게시글밖에 나오지 않아 가져왔습니다. https://teamtreehouse.com/community/what-exactly-is-a-helper-method
도우미 메서드는 여러 클래스들에서 공통적으로 반복되는 특정 작업을 수행하는데 사용됩니다. 이 메서드는 같은 내용의 코드를 서로다른 클래스에서 반복적으로 작성되는 것을 막아줍니다. static 메서드가 그 작업을 "정의"하는 반면에, 도우미 메서드는 과정을 보조하는 역할을 합니다. Integer.parseInt()를 도우미메서드로 생각해볼 수 있습니다. 우리는 이 메서드를 서로 무관한 다양한 클래스들에서 독립적인 작업들에 사용합니다.
헬퍼 메서드는 종종 public static으로 선언해서, 클래스 이름을 이용해 호출할 수 있습니다. (Classname.method() , integer.parseInt()). 아래의 예시로 설명하겠습니다. 여러 클래스에서 사용할 수 있는 헬퍼 메소드들로 구성된 헬퍼 클래스를 생성하였습니다. 테스트라는 클래스를 생성하여 해당 클래스에서 HelperMethods.preMr()라는 메소드를 이용해 사용자의 이름에 Mr를 붙여서 출력할 수 있도록 사용했습니다. 또한, generic을 이용하면 어떠한 프로젝트에서도 사용 가능한 커스텀 라이브러리로 사용될수도 있습니다.