Go에서 간단한 자체 문서화 유형 만들기

8414 단어 programminggo
Go에는 풍부한 유형 시스템이 있으며 이를 활용하여 주석이나 문서와 같은 것을 사용하지 않고 코드로 자신을 더 잘 표현할 수 있습니다.

예를 들어 다음 복합 유형을 고려하십시오.

type member struct {
    id   string
    img  string
    desc string
}


여기에 세 개의 필드가 있는 구조체인 member 이 있습니다.
  • 세 필드 모두 유형 문자열이 있지만 대부분 다른 형식을 예상합니다.
  • 임의의 문자열을 모든 필드에 할당할 수 있습니다(실수로 하기 매우 쉽습니다).
  • id 구조체를 만들기 전에 둘 이상의 위치에서 수신 데이터의 유효성을 검사해야 할 수 있습니다.

  • 그 코드 조각은 원시적 집착으로 알려진 코드 "냄새"의 전형적인 예입니다. 코드 냄새는 소프트웨어 부패의 추상적 징후 또는 증상이며 원시적 집착은 그 중 하나입니다. 작은 응용 프로그램이나 간단한 명령줄 도구인 struct def 그런 것은 괜찮지만 더 큰 프로그램(수만 줄의 코드를 생각해 보십시오)에서는 실제 문제가 됩니다.

    의도를 더 잘 표현하는 데 도움이 되는 유형을 추가할 수 있습니다.

    type member struct {
        id   uuidStr
        img  urlStr
        desc text150
    }
    
    type (
      uuidStr string
      urlStr  string
      text150 string
    )
    


    세 가지 새로운 유형을 정의했습니다. img , descmember 모두 기본 유형으로 uuidStr 을 가지며 urlStr struct 필드는 더 잘 사용하는 문자열 형식을 설명합니다.

    우리는 이것을 더 발전시켜 제작자 기능을 만들 수 있습니다.

    func makeUuidStr(rawId string) (uuidStr, error) {
      if !canBeUUID(rawId) {
          return "", fmt.Errorf("\"%s\" is not a valid UUID string", rawId)
      }
    
      return uuidStr(rawId), nil
    }
    
    func makeUrlStr(rawURL string) (urlStr, error) {
      if !canBeURL(rawURL) {
          return "", fmt.Errorf("\"%s\" is not a valid URL", rawURL)
      }
    
      return urlStr(rawURL), nil
    }
    
    func makeText150(rawText string) (text150, error) {
      if len(rawText) > 150 {
        return "", fmt.Errorf("\"%s\" is over 150 bytes long!", rawText[:25])
      }
    
      return text150(rawText), nil
    }
    


    이러한 함수의 도움으로 구성원에 대한 생성자를 작성할 수 있습니다.

    func createMember(rawId, rawImgURL, rawDesc string) (member, error) {
      id, idErr := makeUuidStr(rawId)
      img, imgErr := makeUrlStr(rawImgURL)
      desc, descErr := makeText150(rawDesc)
    
      if idErr != nil {
        return member{}, idErr
      } else if imgErr != nil {
        return member{}, imgErr
      } else if descErr != nil {
        return member{}, descErr
      }
    
      return member{id, img, desc}, nil
    }
    


    이것은 많은 작업처럼 보일 수 있지만 기본적으로 구성 시간에 데이터가 유효성 검사되었는지 확인했습니다. 필드를 업데이트하지 않는 한 이후에 유효성 검사를 수행할 필요가 없습니다. 멤버는 항상 고려해야 할 사항이 있다고 말하는 유효한 상태:
  • 프리미티브 대신 사용자 정의 유형을 사용하려는 경우 생성자를 사용해야 하며 유효성 검사를 우회하는 빠르고 더러운 방법으로 유형 캐스팅 또는 유형이 지정되지 않은 상수를 사용하지 않아야 합니다.
  • 원시적인 집착을 고치기 위해 전통적으로 클래스(UUID 클래스, URL 클래스, 텍스트 클래스 등이 있음)를 사용할 것입니다. , 문자열 값을 래핑 해제하는 하나 이상의 메서드를 사용하면 설계가 복잡해지지만 버그에 대한 보호 기능이 향상됩니다. 예를 들어 text150을 슬라이싱하거나 인덱싱하거나 두 개의 string 값을 함께 연결할 수도 있습니다.
  • 좋은 웹페이지 즐겨찾기