Чистый код. Создание, анализ и рефакторинг — страница 48 из 94

        errorCode = ArgsException.ErrorCode.MISSING_DOUBLE;

        throw new ArgsException();

      } catch (NumberFormatException e) {

        errorParameter = parameter;

        errorCode = ArgsException.ErrorCode.INVALID_DOUBLE;

        throw new ArgsException();

      }

    }


    public Object get() {

      return doubleValue;

    }

  }

}

Хорошо — теперь Args выдает единственное исключение ArgsException. Выделение ArgsException в отдельный модуль приведет к тому, что большой объем вспомогательного кода обработки ошибок переместится из модуля Args в этот модуль. Это наиболее естественное и очевидное место для размещения этого кода, вдобавок перемещение поможет очистить перерабатываемый модуль Args.

Итак, нам удалось полностью отделить код исключений и ошибок от модуля Args (листинги 14.13–14.16). Для решения этой задачи понадобилось примерно 30 промежуточных шагов, и после каждого шага проверялось прохождение всех тестов.


Листинг 14.13. ArgsTest.java

package com.objectmentor.utilities.args;


import junit.framework.TestCase;


public class ArgsTest extends TestCase {

  public void testCreateWithNoSchemaOrArguments() throws Exception {

    Args args = new Args("", new String[0]);

    assertEquals(0, args.cardinality());

  }


  public void testWithNoSchemaButWithOneArgument() throws Exception {

    try {

      new Args("", new String[]{"-x"});

      fail();

    } catch (ArgsException e) {

      assertEquals(ArgsException.ErrorCode.UNEXPECTED_ARGUMENT,

                   e.getErrorCode());

      assertEquals('x', e.getErrorArgumentId());

    }

  }


  public void testWithNoSchemaButWithMultipleArguments() throws Exception {

    try {

      new Args("", new String[]{"-x", "-y"});

      fail();

    } catch (ArgsException e) {

      assertEquals(ArgsException.ErrorCode.UNEXPECTED_ARGUMENT,

                   e.getErrorCode());

      assertEquals('x', e.getErrorArgumentId());

    }


  }


  public void testNonLetterSchema() throws Exception {

    try {

      new Args("*", new String[]{});

      fail("Args constructor should have thrown exception");

    } catch (ArgsException e) {

      assertEquals(ArgsException.ErrorCode.INVALID_ARGUMENT_NAME,

                   e.getErrorCode());

      assertEquals('*', e.getErrorArgumentId());

    }

  }


  public void testInvalidArgumentFormat() throws Exception {

    try {

      new Args("f~", new String[]{});

      fail("Args constructor should have throws exception");

    } catch (ArgsException e) {

      assertEquals(ArgsException.ErrorCode.INVALID_FORMAT, e.getErrorCode());

      assertEquals('f', e.getErrorArgumentId());

    }

  }


  public void testSimpleBooleanPresent() throws Exception {

    Args args = new Args("x", new String[]{"-x"});

    assertEquals(1, args.cardinality());

    assertEquals(true, args.getBoolean('x'));

  }


  public void testSimpleStringPresent() throws Exception {

    Args args = new Args("x*", new String[]{"-x", "param"});

    assertEquals(1, args.cardinality());

    assertTrue(args.has('x'));

    assertEquals("param", args.getString('x'));

  }


  public void testMissingStringArgument() throws Exception {

    try {

      new Args("x*", new String[]{"-x"});

      fail();

    } catch (ArgsException e) {

      assertEquals(ArgsException.ErrorCode.MISSING_STRING, e.getErrorCode());

      assertEquals('x', e.getErrorArgumentId());

    }

  }


  public void testSpacesInFormat() throws Exception {

    Args args = new Args("x, y", new String[]{"-xy"});

    assertEquals(2, args.cardinality());

    assertTrue(args.has('x'));

    assertTrue(args.has('y'));

  }


  public void testSimpleIntPresent() throws Exception {

    Args args = new Args("x#", new String[]{"-x", "42"});

    assertEquals(1, args.cardinality());

    assertTrue(args.has('x'));

    assertEquals(42, args.getInt('x'));

  }

  public void testInvalidInteger() throws Exception {

    try {

      new Args("x#", new String[]{"-x", "Forty two"});

      fail();

    } catch (ArgsException e) {

      assertEquals(ArgsException.ErrorCode.INVALID_INTEGER, e.getErrorCode());

      assertEquals('x', e.getErrorArgumentId());

      assertEquals("Forty two", e.getErrorParameter());

    }

  }


Листинг 14.13 (продолжение)

  public void testMissingInteger() throws Exception {

    try {

      new Args("x#", new String[]{"-x"});

      fail();

    } catch (ArgsException e) {

      assertEquals(ArgsException.ErrorCode.MISSING_INTEGER, e.getErrorCode());

      assertEquals('x', e.getErrorArgumentId());

    }

  }


  public void testSimpleDoublePresent() throws Exception {

    Args args = new Args("x##", new String[]{"-x", "42.3"});

    assertEquals(1, args.cardinality());

    assertTrue(args.has('x'));

    assertEquals(42.3, args.getDouble('x'), .001);

  }


  public void testInvalidDouble() throws Exception {

    try {

      new Args("x##", new String[]{"-x", "Forty two"});

      fail();

    } catch (ArgsException e) {