14장. 점진적인 개선
결론
그저 돌아만가는 코드만으로는 부족하다
나쁜 코드가 프로젝트에 악영향을 끼친다
코드는 개선할 수 있다 하지만 나중에 개선하기 어렵다
처음부터 깨끗하게 유지하는 것이 효율적이다
점진적인 개선
명령행 인수의 구문을 분석하는 Args 클래스를 만들어보자
public static void main(String[] args) {
try {
Args arg = new Args("l,p#,d*", args);
boolean logging = arg.getBoolean('l');
int port = arg.getInt('p');
String directory = arg.getString('d');
executeApplication(logging, port, directory);
} catch (ArgsException e) {
System.out.printf("Argument error: %s\n", e.errorMessage());
}
}예시
Args 클래스가 하는 일
스키마를 분석
명령행 인수들의 값을 관리
최종
1차 초안
boolean 인수들만 가능하고 map에 저장
명령행 인수 문자열 배열에서 - 로 시작하는 문자열이 어떤 인수 유형인지를 map에서 key로 가지고 있는지로 확인하고 value를 갱신하여 저장
Integer와 String 추가
스키마 분석은 스키마를 타입별로 Map 을 여러 개 만들어 관리
타입이 늘어남에 따라 setArgument가 변하고 is, set, get 메소드가 추가로 필요
ArgumentMarshaler
개선이라는 이름으로 구조를 크게 뒤집지 말자
개선 전과 똑같은 프로그램으로 만드는 건 어렵기 때문이다
단위 테스트와 인수 테스트를 활용한 테스트 주도 개발로 개선하자
인수 유형은 여러 가지이지만 모두 유사한 메소드를 제공하므로 클래스로 추출
ArgumentMarshaler 클래스를 도입하면서 실패하는 테스트를 위한 코드 수정
String과 Integer도 ArgumentMarshaler에게 로직을 옮기고 파생 클래스를 만들어 기능을 분산한다
첫 번째 리팩터링 이후
이제 ArgumentMarshaler를 활용해 인수 유형 마다 존재하고 있던 Map들을 교체하고 관련 메소드를 변경한다
setArgument에서의 유형을 일일이 확이하는 부분을 없애고 싶다
ArgumentMarshaler.set만 호출해도 충분하게 만들고 싶다
그러면 setXXXArg도 각 ArgumentMarshaler의 파생클래스로 내리자
파라미터인 args(String[])와 currentArgument(int) 대신 args를 리스트로 바꾸고 iterator만 전달하자
이젠 새로운 인수 유형 추가하기도 쉬워졌다
parseSchemaElement에서 새로운 인수유형에 대한 판별 코드를 추가하고
새로운 인수 유형에 대한 ArgumentMarshaler 의 구현 클래스를 만들고
getXXX와 새로운 오류 처리 코드만 추가하면 된다
Args 클래스에서 ArgsException과 모든 ArgumentMarshaler 클래스를 빼서 각자 파일로 옮긴다
분할도 이해하기 쉬워지고 유지보수가 쉬워지므로 소프트웨서 설계의 품질을 높인다
Last updated