}
private boolean isIntArg(ArgumentMarshaler m) {
return m instanceof IntegerArgumentMarshaler;
}
private boolean isStringArg(ArgumentMarshaler m) {
return m instanceof StringArgumentMarshaler;
}
private boolean isBooleanArg(ArgumentMarshaler m) {
return m instanceof BooleanArgumentMarshaler;
}
Причин для существования трех методов isxxxArg не осталось. Я оформил их в виде встроенного кода:
private boolean setArgument(char argChar) throws ArgsException {
ArgumentMarshaler m = marshalers.get(argChar);
if (m instanceof BooleanArgumentMarshaler)
setBooleanArg(argChar);
else if (m instanceof StringArgumentMarshaler)
setStringArg(argChar);
else if (m instanceof IntegerArgumentMarshaler)
setIntArg(argChar);
else
return false;
return true;
}
На следующем шаге я перешел на использование ассоциативного массива marshalers в функциях set, отказываясь от использования трех старых контейнеров. Преобразование началось с Boolean:
private boolean setArgument(char argChar) throws ArgsException {
ArgumentMarshaler m = marshalers.get(argChar);
if (m instanceof BooleanArgumentMarshaler)
setBooleanArg(m);
else if (m instanceof StringArgumentMarshaler)
setStringArg(argChar);
else if (m instanceof IntegerArgumentMarshaler)
setIntArg(argChar);
else
return false;
return true;
}
...
private void setBooleanArg(ArgumentMarshaler m) {
try {
m.set(“true”); // было: booleanArgs.get(argChar).set(«true»);
} catch (ArgsException e) {
}
}
Тесты проходили успешно, и я сделал то же самое для типов String и Integer. Это позволило мне интегрировать часть некрасивого кода обработки исключений в функцию setArgument.
private boolean setArgument(char argChar) throws ArgsException {
ArgumentMarshaler m = marshalers.get(argChar);
try {
if (m instanceof BooleanArgumentMarshaler)
setBooleanArg(m);
else if (m instanceof StringArgumentMarshaler)
setStringArg(m);
else if (m instanceof IntegerArgumentMarshaler)
setIntArg(m);
else
return false;
} catch (ArgsException e) {
valid = false;
errorArgumentId = argChar;
throw e;
}
return true;
}
private void setIntArg(ArgumentMarshaler m) throws ArgsException {
currentArgument++;
String parameter = null;
try {
parameter = args[currentArgument];
m.set(parameter);
} catch (ArrayIndexOutOfBoundsException e) {
errorCode = ErrorCode.MISSING_INTEGER;
throw new ArgsException();
} catch (ArgsException e) {
errorParameter = parameter;
errorCode = ErrorCode.INVALID_INTEGER;
throw e;
}
}
private void setStringArg(ArgumentMarshaler m) throws ArgsException {
currentArgument++;
try {
m.set(args[currentArgument]);
} catch (ArrayIndexOutOfBoundsException e) {
errorCode = ErrorCode.MISSING_STRING;
throw new ArgsException();
}
}
Я вплотную подошел к удалению трех старых объектов Map. Прежде всего было необходимо привести функцию getBoolean:
public boolean getBoolean(char arg) {
Args.ArgumentMarshaler am = booleanArgs.get(arg);
return am != null && (Boolean) am.get();
}
к следующему виду:
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? Дело в том, что наряду с набором модульных тестов у меня был отдельный набор приемочных тестов, написанных для FitNesse. Оказалось, что тесты FitNesse проверяли, что при вызове getBoolean для аргумента с типом, отличным от Boolean, возвращается false. Модульные тесты этого не делали. До этого момента я запускал только модульные тесты[69].
Последнее изменение позволило исключить еще одну точку использования объекта Map для типа Boolean:
private void parseBooleanSchemaElement(char elementId) {
ArgumentMarshaler m = new BooleanArgumentMarshaler();
booleanArgs.put(elementId, m);
marshalers.put(elementId, m);
}
Теперь объект Map для типа Boolean можно было удалить:
public class Args {
...
private Map