14장은 점진적인 개선 사례를 보여주고 있다. 출발은 좋았지만? 확장성이 부족했던 모듈을 소개로 시작하여 모듈을 개선하고 정리하는 단계를 살펴본다.
들어가며
- 프로그램을 작성하다 보면 종종 명령행 인수의 구문을 분석할 필요가 생긴다. 편리한 유틸리티가 없다면 main 함수로 넘어오는 문자열 배열을 직접 분석하게 된다.
- 여러 가지 좋은 유틸리티가 있지만 내 사정에 딱 맞는 유틸리티가 없다면? 직접 짜겠다고 결심한다. 새로 짤 유틸리티를 여기서 Args라고 부를 예정
- Args는 사용법이 간단하다. Args 생성자에 (입력으로 들어온) 인수 문자열과 형식 문자열을 넘겨 인스턴스를 생성한 후 인스턴스에 인수값을 질의한다.
간단한 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'); executeAppliocation(logging, port, directory); } catch (ArgsException e) { System.out.printf("Argument error: %s\n", e.errorMessage()); } }
- 위 코드는 사용법이 간단하다는 사실이 분명히 드러나고 있다.
String 인수
- String 인수를 추가하는 과정은 boolean 인수와 매우 유사하다
- HashMap을 변경한 후, parse, set, get 함수를 고쳤다. 일단 각 인수 유형을 처리하는 코드를 모두 ArgumentMarshaler 클래스에 넣고 나서 그 파생 클래스를 만들어 코드를 분리할 계획을 세우고 진행함.
- 그러면 프로그램 구조를 조금씩 변경하는 동안에도 시스템의 정상 동작을 유지하기 쉬워지기 때문이다.
모든 논리 ArgumentMarshaler로 옮겼으니 파생 클래스 만들어 기능 분산
- setBoolean 함수를 BooleanArgumentMarshaler로 옮긴 후 올바르게 호출되는지 확인함
- 클래스에 추상메서드 set을 생성
private abstract class ArgumentMarshaler { protected boolean booleanValue = false; private String stringValue; private int integerValue; public void setBoolean(boolean value) { booleanValue = value; } public boolean getBoolean() { return booleanValue; } public void setString(String s) { stringValue = s; } public String getString() { return stringValue == null ? "" : stringValue; } public void setInteger(int i) { integerValue = i; } public int getInteger() { return integerValue; } public abstract void set(String s); }