비동기식 ADT 소개
If you do not know what an ADT is, read the previous post — https://blog.hyper.io/understanding-adts/
aprevious post에서 ADT나 대수 데이터 형식을 논의했습니다. 이 유형들은 유사한 용기의 안전한 환경에서 데이터 흐름 파이프 프로세스를 만들 수 있도록 합니다.
TL;DR; Async ADTs wrap functions so you can separate side effects from business logic or actions from calculations, resulting in highly maintainable and testable code.
이 댓글 누구 거예요?
제가 뭘 배울 수 있을까요?
Rather watch than read, checkout this video:
왜 비동기식 ADT입니까?청결 건축
비동기적인 ADT를 깊이 연구하기 전에 깨끗한 코드와 깨끗한 체계 구조를 이야기합시다.고도로 유지보수 가능하고 확장 가능하며 신뢰할 수 있는 소프트웨어를 만들기 위해서 우리는 업무 논리와 실현 세부 사항을 분리하고 조작과 계산을 분리해야 한다.
Clean Architecture is hard!
인터페이스와 제어 반전을 사용하거나 주입에 의존하면 업무 논리와 세부 사항을 분리하는 데 도움을 줄 수 있지만 우리는 여전히 조작이나 부작용 기능의 도전에 직면해 있다.
우리는 어떻게 업무 논리를 순기능으로 분리하고 부작용 기능과 분리합니까?
Flux architecture는 이 점을 실현하는 데 도움이 되는 모델이지만 샘플 파일이 필요하고 적합하지 않다. 왜냐하면 통량은 종종 단독 함수에서 논리를 전파하여 하나의 흐름을 완성하기 시작하기 때문이다.예를 들어, 복원기, 동작 작성자 및 선택기 등이 있습니다.
다른 하나는 ADT입니다. ADT는 용기 내의 값을 관리하는 것입니다. 이 값이 함수라면 어떻게 됩니까?
비동기식 ADT 소개
비동기 ADT는 부작용 함수를 함수에 포장하고 용기의 값으로 간주하여 부작용 함수를 순수 함수와 분리한다.ADT는 용기 대상입니다. ADT에 현식 방법을 사용하지 않은 상태에서 빈 값이나 돌변이 일어나지 않도록 값을 관리할 수 있습니다.
ADT는 매핑 및 체인 함수로 구성됨
map 방법은 개발자로 하여금 함수를 적용할 수 있게 한다. 이 함수는 용기 내의 현재 값을 입력 매개 변수로 받아들인 다음에 함수로 되돌아오는 출력으로 용기 내의 값을 대체한다.
[1].map(v => 2) // -> [2]
ADT는 값 1을 포함하고 맵 함수를 호출하여 값 2를 되돌려줍니다. ADT는 현재 값 2를 포함합니다.chain 방법은 개발자가 함수를 적용할 수 있도록 합니다. 이 함수는 용기의 현재 값을 입력으로 받아들인 다음에 함수가 되돌아오는 출력으로 전체 용기를 대체합니다. 이 함수는 같은ADT 형식이어야 합니다.(예에서 flatMap은 chain)
[2].flatMap(v => [4]) // -> [4]
ADTs contains values for pipeline like flow for logic processing, functions are values, so we can take advantage of the ADT pattern to pass functions around.
함수는 값이다
과거에Javascript에 대해 알고 있다면 함수는 값입니다. 함수는 매개 변수로 다른 함수에 전달될 수도 있고 출력으로 함수에서 되돌아올 수도 있습니다.
우리는 숫자나 문자열을 값으로 사용하지 않고 함수를 값으로 사용합니까?
ADT 파이프는 맵과 chain을 사용하여 이 함수를 조작할 수 있지만, 호출 함수가 이 함수의 실행을 촉발할 때까지 이 함수를 실제적으로 실행하지 않습니다. fork 방법은 이 함수를 호출할 수 없습니다.
const fn = (rejected, resolved) => resolved('Hello')
const fork = [fn].map(fn => (rejected, resolved) =>
resolved(fn(e => e, r => r + ' World' ))
)
.pop()
fork(e => e, r => console.log(r))
이 예에서 우리는 두 개의 매개 변수를 포함하는 함수를 만들었는데, 첫 번째 매개 변수는 거부라고 하고, 일원 함수이며, 두 번째 매개 변수는 해석된 함수라고 하고, 일원 함수이다./**
* @param {function} rejected - unary function for rejected Asyncs
* @param {function} resolved - unary function for resolved Asyncs
*/
function (rejected, resolved) {
return value
}
비동기 함수는 호출할 때 모든 값을 되돌려줍니다. 이 예에서 되돌려주는 값은 문자열Hello입니다.이 함수를 컨테이너에 값으로 넣습니다.용기의 모든 값과 같이, 우리는 용기에서 맵이나chain을 실행할 수 있습니다.
맵이 실행될 때 매개 변수로 제공된 값은 비동기 함수이고 다른 함수로 되돌아옵니다. 이 함수는 용기 대체 값으로 제공된 비동기 함수의 서명과 같습니다.
이 호출 흐름에서 비동기 함수를 조합하는 것은 모든 함수가 이전 함수를 호출한 결과입니다. 조합처럼 fork 방법을 호출할 때, 마지막 값이 확정될 때까지 모든 이전 조합의 함수를 방출하고, 첫 번째 파라미터에서 거부 결과를 되돌려주거나, 두 번째 파라미터에서 해석 결과를 되돌려줍니다.
This lazy call flow is super confusing and would be a chore to write by hand.
함수를 값으로 되돌릴 때, 파이프를 만듭니다. 그 중 한 함수가 다른 함수를 호출하고, 그 함수의 결과는 다른 함수에 호출됩니다. 그러나 포크 방법이 실행될 때까지 이 함수를 호출하지 않습니다. 이것은 포크를 호출하기 전에 부작용을 실행하지 않기 때문입니다.
우리가 전달하는 것은 순수함수이기 때문에 포크 함수를 호출하기 전에 부작용을 실행하지 않고 부작용이 없는 업무 논리(순수함수)를 만들 수 있습니다.삽입된 부작용 함수는 포크 호출에서 응용 프로그램의 가장자리에서 실행됩니다.
Using the array starts to show how this working, but we can do better, we can create an ADT called a Async.
Async는 비동기 함수를 컨테이너에 포장하여 순수 함수 처리를 위한 ADT의 일종이다
Async는 샘플 함수 포장을 처리하고 개발자가 실제 반환값처럼 ADT를 작성할 수 있도록 하며 맵과 chain 방법으로 수정할 수 있습니다.
const Async = fork =>
({
fork,
map: fn => Async((rejected, resolved) =>
fork(rejected, v => resolved(fn(v)))
)
})
Async.of = v => Async((rejected, resolved) => resolved(v))
초보자에게 간단한 함수를 제공하기 위해ADT를 만듭니다.Async 방법은 (rejected,resolved) =>any로 서명하는 함수를 받아들인다는 것을 기억하십시오.
이 ADT는 비동기 편지 값을 맵에서 제공한 것처럼 처리하고 맵에서 새 값을 되돌려줍니다.ADT에서 기능 패키지를 관리합니다.예!
Async.of(1)
.map(v => v + 1)
.fork(e => console.log('rej: ', e), r => console.log(r))
// -> 2
잘 됐다!Async ADT의 가장 멋진 결과는 fork 함수를 호출하기 전에는 실제 실행이 일어나지 않는다는 것입니다.(예! 내 비즈니스 논리에는 부작용이 없다!)값을 비동기 함수에 포장하는 것은 ADT에서 이루어지기 때문에 창작 개발자는 비동기 함수가 아닌 실제 값을 관리하는 것처럼 파이프를 만들 수 있다.(부작용 없음)
부작용은요?
promise는 부작용을 포함하는 함수를 만드는 흔한 모드입니다.
const sideEffect = () => Promise.resolve(1)
Async.fromPromise = fn => Async((rejected, resolved) => fn().then(resolved).catch(rejected))
Async.fromPromise(sideEffect)
.map(v => v + 1)
.fork(e => console.log('rej: ', e), r => console.log('res: ' + r))
이 예에서, 우리는 약속에서 비동기적인 ADT를 만들고, 맵을 호출하여 이 약속에서 해석될 값을 실제 처리합니다.반환 값이 비동기 함수로 포장되었습니다.비동기식 ADT는 두 개의 잠재적인 파이프 결과가 있는데 거절당하고 해결된다.파이프에서 거부된 함수를 호출하면 모든 체인 방법은 돌아가고, 포크 방법을 호출할 때 매개 변수 목록의 첫 번째 함수를 호출합니다.해석된 방법만 호출하면, 이 체인은 fork 매개 변수 목록의 두 번째 함수를 호출할 때까지 추적됩니다.
비동기 ADT에 체인 함수를 추가합니다.chain 메서드는 값을 제공하는 함수를 함수의 매개변수로 지정하고 현재 Async를 대체할 새 Async를 반환합니다.
개발자는 해석되거나 거부된 함수 서명을 걱정할 필요가 없습니다. ADT에서 이 값을 추출한 다음 현재 Async를 새로 되돌려줍니다.
const Async = fork =>
({
fork,
map: fn => Async((rejected, resolved) =>
fork(rejected, v => resolved(fn(v))
)),
chain: fn => Async((rejected, resolved) =>
fork(rejected, x => fn(x).fork(rejected, resolved))
)
})
우리는 이 기능을 시범적으로 보여줄 수 있다.Async.of(4)
.chain(v => Async.of(v + 1))
.fork(
e => console.log(`rej: ${e}`),
r => console.log(`res: ${r}`)
)
매우 멋지고 비동기식 ADT를 사용하는 것이 마치 Id ADT를 사용하는 것과 같다.부작용 함수를 걱정할 필요가 없습니다. 이러한 부작용은 우리의 업무 논리 기간에 실행되지 않으며, fork를 호출할 때만 실행됩니다. fork는 인터페이스 층에서 호출되며, 업무 논리 핵심에서 호출되지 않습니다.비동기 ADT를 이용하여 서비스 층 호출을 핵심으로 되돌릴 수 있고 인터페이스에서 핵심 논리 함수를 호출하고 비동기 ADT를 수신할 수 있다.인터페이스가 준비되었을 때, 포크 함수를 사용하여 ADT를 호출할 수 있으며, 이 흐름은 응용 프로그램의 핵심을 깨끗하게 유지하고, 부작용이 응용 프로그램의 가장자리에서 실행되는 것이지 핵심 업무 논리에서 실행되는 것이 아니다.
요약
우리는 대량의 샘플 관리를 추가하지 않고 부작용(조작) 기능을 순수한 업무 논리(계산) 기능에서 어떻게 분리합니까?
정답은 비동기 ADT입니다.
비동기식 ADT는 청결한 체계 구조의 구축 블록이다.비동기식 ADTs를 사용하여 체크 아웃하는 예: https://github.com/hyper63/workshop-api
Reference
이 문제에 관하여(비동기식 ADT 소개), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hyper/introduction-to-async-adt-45a1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)