점진적인 개선(3)

인수 고쳐보기

책너두 5기 30일차

로버트 C. 마틴의 클린코드 p. 273~ p.288

내용정리

14. 점진적인 개선

String 인수

HashMap을 변경한 후 parse, set, get 함수를 고쳤다. 각 인수 유형을 처리하는 코드를 ArgumentMarshaler 클래스에 넣고 나서 ArgumentMarshaler 파생 클래스를 만들어 코드를 분리하는 것이 의도였다. 이 후 int 인수 기능을 ArgumentMarshaler로 옮겼다.

모든 논리를 ArgumentMarshaler로 옮긴 뒤 파생 클래스를 만들어 기능을 분산한다.

  1. setBoolean 함수를 BooleanArgumentMarshaler로 옮긴 후 올바로 호출되는지 확인한다.
    • ArgumentMarshaler 클래스에 추상 메서드 set을 만든다.
    • BooleanArgumentMarshaler 클래스에 set 메서드를 구현한다.
    • sertBoolean 호출을 set 호출로 바꾼다.
    • 테스트를 통과하면 ArgumentMarshaler에서 setBoolean 메서드를 제거한다.
  2. get 메서드를 BooleanArgumentMarshaler로 옮긴다.
    • ArgumentMarshaler에서 get을 추상 메서드로 만든 후 BooleanArgumentMarshaler에 구현한다.
    • ArgumentMarshaler에서 getBoolean 함수를 제거한 후 booleanValue를 BooleanArgumentMarshaler로 내려 private 변수로 선언한다.
  3. 같은 방식으로 Strings 인수 유형도 변경한다.
  4. 마지막으로 integer 인수 유형에도 같은 과정을 반복한다.

이제 isBooleanArg를 다음과 같이 변경한다

1
2
3
private boolean isBooleanArg(char argChar) {
    return booleanArgs.containKey(argChar);
}

1
2
3
4
private boolean isBooleanArg(char argChar) {
    ArgumentMarshaler m = marshalers.get(argChar);
    return m instanceof BooleanArgumentMarshaler;
}

위 방식을 isIntArg와 isStringArg에도 적용한다.

1
2
3
4
private boolean isIntArg(char argChar) {
    ArgumentMarshaler m = marshalers.get(argChar);
    return m instanceof IntegerArgumentMarshaler;
}
1
2
3
4
private boolean isStringArg(char argChar) {
    ArgumentMarshaler m = marshalers.get(argChar);
    returnn m instanceof StringArgumentMarshaler;
}

다음으로 marshalers.get을 호출하는 코드를 모두 제거한다. isxxxArg 메서드도 별도로 선언할 필요성이 없어져 인라인 코드로 만든다.

set함수에서 기존 HashMap을 marshalers HashMap으로 교체한다. boolean, String, Interger에 모두 적용한다.

원래 맵 3개를 제거하도록 한다. 먼저 getBoolean 함수를 변경한다.

1
2
3
4
public boolean getBoolean(chart arg) {
    Args.ArgumentMarshaler am = booleanArgs.get(org);
    return am != null && (Boolean) am.get();
}

1
2
3
4
5
6
7
8
9
10
public boolean getBoolean(char arg) {
    Args.ArgumentMarshaler am = marshalers.get(arg);
    boolean b = false;
    	try {
        b = am != null && (Boolean) am.get();
    } catch (ClassCastException e) {
            b = false;
        }
    return b;
}

ClassCastException 을 사용한 이유는 인수 테스트 케이스를 FitNess에서 구현했기 떄문이다. 단위 테스트 집합은 FitNess에서 구현하지 않았다. FitNess 테스트는 boolean이 아닌 인수로 getBoolean을 호출하면 무조건 false로 반환했다.

boolean, String, Integer 맵을 제거한다. parse 메서드 3개를 인라인 코드로 만든다.


읽고나서

어렵다.. 코드의 구성과 언어의 대한 이해가 부족하면 절대 못하겠다. 열심히 공부해야지..