Elm에서 불투명 유형 사용하기!

17211 단어 elmwebdev
내가 가입한 지 이미 한참이 되었다.그 동안 나는 다른 사람들이 불투명한 유형을 어떻게 사용하는지 물어보는 것을 보았다.나는 불투명한 유형이 존재하지 않는 많은 코드 기반과 예시를 보았다.
Elm Slack
나는 Elm에서 API 설계를 할 때 불투명 유형이 매우 중요하다고 생각한다. 나는 그것들이 아직 충분하지 않다고 의심한다.본고에서 우리는 불투명 유형이 어떻게 API를 한데 붙이고 코드를 문서화하고 버그가 없도록 하는지 배울 것이다.

흔한 장면


우리는 내가 상당히 흔히 볼 수 있다고 생각하는 장면 예시를 사용할 것이다. 폼은 원격으로 새로운 자원을 만들기 위해 데이터를 검증하고 제출한다.이런 상호작용은 많은 상호작용식 웹 응용 프로그램의 핵심이다.
간단하게 보기 위해서, 우리는 우리가 만들고 싶은 자원이 매우 간단한 문제라고 가정한다. 제목과 본문이 있다.
우선, 우리는 어떠한 불투명한 유형의 코드도 사용하지 않을 것이다.그리고 우리는 점차적으로 그것들을 추가하고 코드가 어떻게 개선되었는지 분석할 것이다.
갑시다!

원어 예


우리는 문제를 제기하고 싶다.이 API로 모듈을 작성했다고 가정합니다Question.
module Question exposing (create)

create : String -> String -> Task Http.Error String
create 함수는 문제 title 와 문제 body 를 받아들이고 Task 를 되돌려줍니다. 이 함수는 적당한 문제를 만들려고 합니다.이 Task 는 실패하고 Http.Error 로 돌아갈 수도 있고, 새로운 문제String를 대표하는 slug 로 돌아갈 수도 있다.
그리고 사용자가 문제를 만들 수 있도록 폼을 만듭니다.우리는 양식을 제출하는 코드에 중점을 두고 필드가 어떻게 업데이트되고 나타나는지 등 관련 없는 세부 사항을 무시할 것이다.
type alias Model =
    { title : String
    , body : String
--  , ...
    }

type Msg
    = Submit
    | QuestionCreated (Result Http.Error String)
--  | ...

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Submit ->
            ( model
            , Question.create model.title model.body
                |> Task.attempt QuestionCreated
            )

        -- ...

view : Model -> Html Msg
view model =
    form
      [ onSubmit Submit ]
      [ titleField model
      , bodyField model
      , submitButton model
      ]
너는 여기에 무슨 문제가 있는지 알아차렸니?어디 보자.우리Submit가 양식을 작성할 때 무슨 일이 일어날까요?우리는 Question.create를 사용하여 문제를 만듭니다.듣기에 괜찮다!하지만 잠깐만...검증은 어디에?!만약 model.title 비어 있다면, 무슨 일이 일어날까요?model.body 너무 길면?은마르코프 모형...네, 괜찮아요.우리는if-then-else 하나만 추가하면 돼요. 그렇죠?
case msg of
    Submit ->
        if Question.titleIsValid model.title && Question.bodyIsValid model.body then
            ( model
            , Question.create model.title model.body
                |> Task.attempt QuestionCreated
            )
        else
            ( model, Cmd.none )

    -- ...
차갑다우리는 여기서 끝난다.새로운 titleIsValidbodyIsValid 함수 처리 검증으로 무효 문제를 만들 수 없습니다.
그런데 이거 좀 불편하지 않아요?create 를 사용할 때마다 입력을 검증하기 위해 titleIsValidbodyIsValid 을 사용해야 합니다.만약 어떤 수요가 변화하고 create 다른 매개 변수가 필요하다면 어떻게 해야 합니까?우리는 if-then-else를 업데이트하는 것을 기억해야 한다.만약 새로운 개발자가 create 형식의 서명을 읽고 아무런 검증 없이 다른 곳에서 사용하기로 결정한다면 어떻게 해야 합니까?취할 수 없다.
마지막으로 API는 오류가 발생하기 쉽습니다.그것은 잘못 사용될 수도 있다.저희가 더 잘할 수 있을까요?만약 우리가 어떤 방식으로 검증과 창설 문제의 개념을 연결시킬 수 있다면 좋지 않겠는가?

불투명 유형의 구조!


계속하기 전에 불투명한 유형이 무엇인지 살펴보겠습니다.

An opaque type is a custom type without exposed constructors.


그래, 하지만 시공사가 폭로되지 않았다면...불투명 유형은 어떻게 사용합니까?응, 구조 함수는 내부에서 접근할 수 있고 사용자 정의 유형을 정의한 모듈에 있다.따라서 불투명 형식의 값을 만드는 방법을 제어하기 위해 함수를 공개할 수 있습니다.
이게 어떻게 된 일인지 보여줘!DellQuestion 모듈로 돌아가기
module Question exposing (create)

create : String -> String -> Task Http.Error String
create의 문제는 매개 변수 형식이 잘못된 필드 값을 받아들인다는 것입니다.예를 들어, "" 은 완전히 유효하지만 유효한 문제 제목은 아닙니다.
우리는 새로운 사용자 정의 형식을 만들 수 있습니다. 가능한 값은 항상 유효한 문제 제목입니까?살펴보겠습니다.
module Question exposing (Title, create, titleFromString)

type Title
    = Title String

titleFromString : String -> Result String Title
titleFromString title =
    if String.length title < 5 then
        Err "the title must not be less than 5 characters long"
    else if String.length title > 100 then
        Err "the title must not be more than 100 characters long"
    else
        Ok (Title title)

-- ...
그렇습니다!여기서 우리는 구조 함수를 공개하지 않고 새로운 사용자 정의 형식 String 을 정의했다.반대로 우리는 Title 함수를 실현했다. 이 함수는 titleFromString 을 받아들이고 검증에 실패했을 때 잘못된 String 함수를 설명하거나 검증에 성공했을 때 String 함수를 되돌렸다.
구축Title의 유일한 방법은 사용Title이다.따라서 만약 우리가 코드 라이브러리 중 어느 곳에나 titleFromString 이 있다면, 우리는 그것이 효과적인 문제 제목이라고 확신할 수 있다.Title 유형은 유효성을 보증한다.
우리가 데이터를 검증할 때마다, 우리는 단지 데이터가 약간의 보증이 있는지 검사할 뿐이다.검증을 실행하고 같은 유형을 사용하는 것은 놓칠 기회입니다!우리는 이 보증을 얻기 위해 불투명한 유형을 사용해야 한다.따라서 우리의 API는 더욱 안전하고 이해하기 쉬워질 것이다.
이와 유사하게 우리는 Title 유형을 정의할 수 있다.그리고 함수Body 를 업데이트할 수 있습니다.
module Question exposing (Body, Title, create, bodyFromString, titleFromString)

-- type Title ...
-- type Body ...

create : Title -> Body -> Task Http.Error String
현재, create 함수는 우리로 하여금 효과적인 제목과 효과적인 본문을 제공하도록 강요한다.우리는 다시는 예전처럼 표를 제출할 수 없다.우리는 createtitleFromString 를 사용해야 합니다.
case msg of
    Submit ->
        case ( Question.titleFromString model.title, Question.bodyFromString model.body ) of
            ( Ok title, Ok body ) ->
                -- Validation succeded
                ( model
                , Question.create title body
                    |> Task.attempt QuestionCreated
                )

            _ ->
                -- Validation failed
                ( model, Cmd.none )

    -- ...
우리의 API는 이 점을 실현하기 위해 어떠한 다른 방법도 제공하지 않았다.우리는 더 이상 검증을 뛰어넘을 수 없다!우리는 심지어 검증을 기억할 필요가 없다.API로 인해 프로세스 중에 오류가 발생했습니다.API가 더 안전합니다.

한층 더 개선하다


우리 아직 안 끝났어!우리가 개선할 수 있는 몇 가지 일이 더 있다.
첫 번째 개선은 중복 검증과 관련이 있다.폼을 제출할 때, 우리는 현재 bodyFromString 함수에서 검증을 실행하고 있지만, update 코드의 폼 필드를 검증하고 싶을 수도 있으며, 실시간으로 오류 메시지가 나타날 수도 있습니다.따라서 viewupdate 모두 사용viewtitleFromString: bodyFromString 성공의 결과에만 관심을 가지고, update 잘못에만 관심을 갖는다.
현재 우리는 viewTitle 유형이 있습니다. 만약에 폼 값이 무효라면 Body 메시지가 자극되지 않고 Submit 중에서 한 번만 검증하고 검증 보증을 view 으로 전파할 수 있습니다.우리는 단지 변경 update 메시지만 필요로 합니다.
type Msg
    = Submit Question.Title Question.Body
    -- |...


case msg of
    Submit title body ->
        ( model
        , Question.create title body
            |> Task.attempt QuestionCreated
        )

    -- ...
청결했어검증에 실패했을 때, 우리는else 자구의 서투른 no 조작에서 벗어났다.
이런 특수한 방법은 Submit에서 형식 검증을 하고 불투명한 유형의 포획 보증을 사용한다. 이것은 내가 작성한 가방 배후의 주요 사상 중의 하나이다. view 표를 조합 가능한 단원으로 간주하여 자유롭게 구축하고 조합하며 다시 사용할 수 있다.나는 곧 쓸 것이다!
두 번째 개선은 매우 간단하다.불투명 유형 composable-form 을 만들 수 있습니다.그리고 composable-form 더 나은 기능으로 보입니다.
create : Title -> Body -> Task Http.Error Slug
현재 사용자가 문제를 편집할 수 있도록 허용해야 한다면 Slug 함수를 작성할 수 있습니다.
edit : Slug -> Title -> Body -> Task Http.Error Slug
깔끔했어우리의 API는 이전에 문제가 생성된 경우에만 편집할 수 있음을 명시합니다.

창조 어쨌든


불투명 유형은 코드를 더욱 안전하게 할 뿐만 아니라 서로 다른 개념을 연결시켜 코드 라이브러리를 이해하기 쉽게 할 수 있다.
내가 코드를 작성할 때, 나는 연습을 하는 것을 좋아한다. 나는 새로운 개발자가 모듈 문서를 읽을 때 특정한 목표가 있을 것이라고 상상해 보았다.만약 Bob이 어떻게 edit 새로운 문제를 제기하는지 알고 싶다면, 우리는 Question 모듈로 이 점을 실현할 것이다.
  • Bob 함수를 찾았습니다.
  • Bob은 만약 그가 createcreate를 제공한다면 create질문을 할 수 있다고 생각한다.
  • Bob은 이것들을 구축할 수 있는 어떤 방법이 있는지 알고 싶다.
  • 밥은 TitleBody를 찾았고, 그들은 임무를 완수한 것 같다.
  • 이 함수들이 되돌아오는 것을 Bob이 알아차렸다String.
  • Bob은 그가 제공한 titleFromString 무효한 상황을 처리해야 한다는 것을 이해한다.
  • 이런 상황에서 개발자는 유형 서명만 보면 bodyFromString API를 명확하게 이해할 수 있다.댓글이 필요 없어요!
    이게 바로 지금!나는 곧 Elm에 관한 글을 더 많이 쓸 것이다.
    불투명한 유형과 폼 검증에 대한 당신의 생각을 듣고 싶으니 논평을 주저하지 마세요!너도 날 찾을 수 있어(
    에서 나는 항상 사람들과 즐겁게 이야기한다.

    좋은 웹페이지 즐겨찾기