기능적으로 프로그램 설계 #1: 핵심 개념 및 볼링 예
나는 함수식 프로그래밍을 믿고 공헌하고 싶다.
함수식 프로그래밍이 도대체 무엇인지 이야기하는 내용이 많지만, 나는 여전히 많은 초기 채택자들이 명령식이나 대상 프로그램에 적합한 사고 과정을 이용하여 프로그램을 설계하는 것을 보았다.
그래서 예민하지 않은 사람이 되기 어렵다.
그래서 이 일련의 문장에서 나는 함수 모델로 프로그램 뒤의 사고 과정을 작성하는 것을 토론할 것이다.너는 어디서부터 시작했니?주요 전략은 무엇입니까?무엇이 문제 해결 모델입니까?
NDC 컨퍼런스에서 나온 이 사진이 진실이라고 생각하지만, 도움이 되지 않는다고 본다.
우리 그것을 분해합시다.
핵심 개념
기능적 사고의 핵심 사상은 성명적 코드다.
성명성 코드는 무엇입니까?잘 물었습니다.
이것은 함수의 수학 정의이다
In mathematics, a function[note 1] is a binary relation between two sets that associates every element of the first set to exactly one element of the second set. Typical examples are functions from integers to integers, or from the real numbers to real numbers.
기본적으로 함수는 입력과 출력 사이의 정적 매핑이다.함수는 어떻게 결과를 얻느냐에 무관심하다.가능한 모든 사례에 대해 당신은 백만 위안이 있을 수 있습니다.이것은 여전히 함수다.
그래서 함수식 프로그래밍에서 우리는
Problem(inputs) => answer
본문에서 우리는 bowling kata를 예로 사용할 것이다.그래서 우리가 말하고 싶은 것은 함수가 하나 있다.
Bowling(game) => score
이렇게요컨대 이것은 함수식 프로그래밍이다.우리는 이 기능을 실현할 수 있도록 설계가 하나 있다.
잠깐만...
그럼, 이 함수에서 모든 논리를 쓴다는 뜻입니까?우리는 최종적으로 1000줄의 코드를 얻을 수 있습니까?이게 정말 이해가 안 돼요?
이제 우리는 튼튼한 부분으로 들어간다.어떻게 시스템을 붕괴시킵니까?
문제를 해명하다
명령식과 대상을 향한 범례에서 우리는 많은 모델, 계발식과 표준적인 사고 과정을 통해 문제를 분해한다.
예를 들어 가장 기본적인 대상 프로그래밍은 하위 시스템을 정의하는 것이다.그 다음에 우리는 이 대상에 대해 실행할 수 있는 동작을 정의한 다음에 그것을 한데 연결시킨다.
많은 디자인 모델과 전략이 이 점을 실현할 수 있다.그럼에도 불구하고 대상을 대상으로 하는 기본 구조 블록과 사고 과정은 비교적 작은 대상을 정의하고 그것들을 협동하여 일하게 하는 것이다.
그러나 우리는 어떻게 함수식 프로그래밍 모델에서 시스템을 분해합니까?
우선, 우리는 impure part of a system와 순수 부품 사이에 경계를 세워야 한다.이것은 오늘의 초점이 아닐 것이다.우리는 시스템의 순수한 부분을 어떻게 분해하는지에만 관심을 기울일 것이다.
그래.우리는 어떻게 해야만 그것을 분해할 수 있습니까?
답은 같다: 더 많은 함수를 써라!!
기다리다이것은 도움이 되지 않는다.어떤 기능입니까?더 많은 기능이 모든 문제를 해결하는 방법입니까?
자...
네, 더 밝힐게요.거래는 이렇습니다.
Let say you try to write a function between problem -> solution. If it is hard to write a function problem -> solution, then we just need to figure out any C that is easier to write a function problem -> C and C -> solution. Then, we write two easy functions
이것이 바로'더 많은 함수를 작성하라'는 뜻이다.
생각하는 과정은 간단한 것 같지만 이해하기 어렵다.
이 시리즈에서 나는 함수 모드에서 어떻게 프로그램을 설계하는지 설명할 것이다. 몇몇 프로그래밍kata를 해결하는 것부터 시작할 것이다.
볼링 탑
함수bowling kata의 목적은 함수를 작성하는 것이다.
getScore(game) -> score
단지 첫눈에 이 함수가 상당히 길고 복잡할 것이라는 것을 나는 알았다.나는 그것을 뜯기로 결정했다.
이 질문을 사용하십시오: 무엇이 이런 데이터입니까?
그래서 나는
만약 내가 모든 볼링 프레임의 득점을 한다면, 나는 그것을 합쳐서 게임 득점을 만들 수 있다.
그래서 나는 매 경기의 점수를 중간 데이터로 선택했다.
const solution = (game) => somethingICannotFigureOut(game)
// Become
const solution = (game) => sum(frameScores(game)))
나는 sum
가 실현하기 쉽다는 것을 알고 frameScores
가 더욱 쉽게 실현될 것이라고 생각한다.지금 나에게 남겨진 것은 실시
frameScores
다.그러나 우리가 시작하기 전에 일치를 유지하기 위해 나는 게임의 데이터 구조를 분명히 할 것이다.
export type NumberScore = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
export type StrikeFrame = [10, null]
export type ScoreFrame = [NumberScore, NumberScore]
export type NormalFrame = StrikeFrame | ScoreFrame
export type LastFrame = [NumberScore, NumberScore, NumberScore | null]
export type NextFrames = Frame[]
export type Frame = NormalFrame | LastFrame
export type Game = [
NormalFrame,
NormalFrame,
NormalFrame,
NormalFrame,
NormalFrame,
NormalFrame,
NormalFrame,
NormalFrame,
NormalFrame,
LastFrame
]
이것은 데이터의 형상이다.하나의 게임은 9개의 노멀프레임과 1개의 라스트프레임으로 구성된 원조다.내가 실현하려고 시도했을 때
frameScores
, 나는 한꺼번에 실현하기 어렵다는 것을 발견했다.나는 아무것도 생각하지 못했다.그래서 좀 더 세분화하기로 했습니다.
A
frameScores
는 매 프레임의 점수이기 때문에 나는 매 프레임의 점수를 계산하는 방법이 필요하다.어떻게 해야 합니까?이곳의 규칙과 논리는 무엇입니까?
각 프레임에서 투수는 최대 두 번 모든 핀을 쓰러뜨리려고 시도한다.기본적으로 프레임 점수를 계산하는 방법은 네 가지가 있습니다.
frameScore
.제가 뭘 할 수 있을까요?같은 질문을 반복합니다. 이런 데이터는 무엇입니까?
나는 A가 하나의 이유라는 것을 발견했다
만약 내가 이 모든 데이터를 가지고 있다면, 나는 이렇게 쉽게 실현할 수 있다
frameScore
// Given frame and nextRolls
switch (getFrameType(frame)) {
case FrameType.LastFrame:
return frame[0] + frame[1] + (frame[2] || 0)
case FrameType.Score:
return frame[0] + frame[1]
case FrameType.Spare:
return frame[0] + frame[1] + nextRolls[0]
case FrameType.Strike: {
return frame[0] + nextRolls[0] + nextRolls[1]
}
}
지금 나는 그것의 실현이 이미 충분히 간단하다고 생각한다. 그래서 나는 여기서 나의 붕괴를 끝냈다.거래가 성립되었다!!나는 프로그램 설계를 하나 가지고 있다.
생각을 되돌아보도록 하겠습니다.
BowlingScore(game) => score
를 원하지만, 나는 그것이 너무 쓰기 어렵다고 생각한다.Something(game) => A
와Another(A) => score
를 제시했습니다.A는 각 프레임의 분수입니다.Something(game) => A
와AnotherThing(A) => frameScore
를 제시했습니다.이것은 프레임 자체와 다음 두 개의 볼륨으로 구성된 데이터 집합이다.gameScore = game |> break_into_frame_and_two_rolls
|> Map(frameScore) |> sum
내가 이 모든 것을 실현하려고 시도했을 때, 나는 모든 것이 충분히 간단하고, 작성하고 추리할 수 있다는 것을 발견했다.결과를 보고 싶으세요?TypeScript의 구현을 찾을 수 있습니다here.Scala에서 구현here을 찾을 수 있습니다.
결론
내가 쓴 바와 같이 순수 함수 영역에서 함수 프로그래밍 디자인의 사고 과정은 다음과 같이 간단하게 표현할 수 있다.
Let say you try to write a function between problem -> solution. If it is hard to write a function between problem -> solution, then we just need to figure out any C that is easier to write a function between problem -> C and C -> solution. Then we simply write two easy functions
이렇게이것은 매우 간단하지만 매우 효과적인 문제를 사고하는 방식이다.
나는 예를 들어 이 문제를 반복해서 물어본 결과, 그리고 내가 최종적으로 어떤 프로젝트를 얻었는지 보여 주었다.
이 질문을 반복하면 어떤 프로그램 설계가 나올지 흥미롭다.이것은 간단하면서도 유력한 문제다.다음 글에서 더 많은 내용을 보여 드리겠습니다.
나는 너희들이 왜 함수식 프로그래밍 디자인이'더 많은 함수를 작성할 수 있다!!'처럼 간단한지 이제 이해하기를 바란다.😄
읽어주셔서 감사합니다!!
TypeScript 전체 구현: https://github.com/chrisza4/functional-bowling-ts
Scala 전체 구현: https://github.com/chrisza4/functional-bowling-scala
몇 가지 관점:
너는 이것이 명령식 프로그래밍과 무엇이 다른지 알고 싶을지도 모른다.
약간의 다른 사고방식을 가질 수 있도록 생각할 필요가 있다.
가장 가능성이 높은 것은 네가 이런 상황에 빠질 것이다.
내가 본 대부분의 실현은 단지 전체 게임 환경을 하나의 대상에 끼워 넣는 것일 뿐이다.
gameScore
와 frameScore
방법은 모두 완전한 게임 상하문을 사용하는데 단지'조금 더'데이터에 접근하기 위해서이다.기능 사고방식에서 함수
frameScore
와 입력을 생각하면 접근이 제한될 수 있다.이런 방법을 사용하여 대상을 대상으로 하는 코드를 작성하는 것은 가능하다.Typescript 구현 라이브러리에서 완성했습니다.가보셔도 됩니다.
주요한 차이는 그것이 만들어낸 코드가 아니다.다른 점은 사유 과정에 있다.당신은 데이터 + 조작을 식별해서 복잡한 논리를 분해하고 대상을 만들 수 있습니까?아니면 해결 방안에 더 가까운 데이터 구조를 식별함으로써 복잡한 논리를 분해하는가?
함수식 사고방식은 함수식 프로그래밍 언어를 사용하지 않아도 도움이 될 수 있습니다.
Reference
이 문제에 관하여(기능적으로 프로그램 설계 #1: 핵심 개념 및 볼링 예), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/chrisza4/design-a-program-in-functional-way-1-core-concept-and-bowling-example-3b8k텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)