# 계약이 적힌 두 곳
  /**
   * Accepts a case-insensitive canonical UUID string and returns the canonical 36-character
   * lowercase form; {@code null} input returns {@code null}.
   *
   * @throws IllegalArgumentException on a malformed UUID
   */
  public static String normalize(String input) {
    if (input == null) {
      return null;
    }
    return UUID.fromString(input).toString();
  }
#   README
- `normalize(String)` — **D3**: 대소문자 무관 canonical UUID 입력을 받아 canonical 36자 소문자
  형태로 반환. 형식 오류 UUID 에는 `IllegalArgumentException`. `null` 입력은 `null` 반환.

# 같은 파서를 쓰는 형제 메서드
  public static UUID toUuid(String uuidString) {
    return UUID.fromString(uuidString);
  }

# 명세의 거부 케이스
24:    def "normalize 는 형식이 잘못된 UUID 를 거부한다"() {
25-        when:
26-        UuidCodec.normalize("not-a-uuid")
27-
28-        then:
29-        thrown(IllegalArgumentException)
30-    }
#   명세 전체의 거부 단언 수 : 1

# 같은 저장소의 UUID 스칼라는 그 계약을 코드로 지킨다
      Pattern.compile(
          "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}");

  public static UUID parse(String value) {
    if (value == null || !CANONICAL.matcher(value).matches()) {
      throw new CoercingParseValueException("invalid UUID");
    }
    try {
      return UUID.fromString(value);
#   그 관문을 지나는 곳
    55:  public static UUID parse(String value) {
    72:      return parse(text).toString();
    90:        return parse(text);
    99:        return parse(stringValue.getValue());
