함수식 프로그래밍과 내가 얻은 것.

나는 5년 넘게 소프트웨어 엔지니어로 일했다. 컴퓨터에 내가 하고 싶은 일을 알려주는 법을 배우기 시작했을 때, 자바스크립트부터 시작해서 함수식 프로그래밍을 발견했다. 나는 가능한 한 이 범례를 많이 사용하려고 노력해 왔다.
그런데 함수식 프로그래밍은 무엇입니까?
Eric Elliott:

Functional programming (often abbreviated FP) is the process of building software by composing pure functions, avoiding shared state, mutable data, and side-effects.


FP는 프로그래밍 패러다임으로서 특정 원칙이나 규칙을 바탕으로 소프트웨어를 구축할 때의 사고방식을 의미한다.만약 당신이 비함수식 프로그래밍 방법으로 소프트웨어를 계속 구축하고 있다면, FP에 적응하는 데 약간의 시간이 필요하지만, 이것은 가치가 있다.
FP는 완전히 불변성, 순수함수, 일반적인 부작용 방지에 관한 것이며 코드를 작성하는 성명적인 방식을 추가했다.
그럼, 우리는 여기서 어떤 생각을 이야기해야 합니까?
  • 순기능과 부작용
  • 불변성
  • 진술식 및 명령식
  • 고급 함수
  • 및 기타 의견

  • 순함수
    순수함수는 하나의 함수로 같은 입력을 주고 항상 같은 출력을 되돌려주며 부작용이 없다.
    const add = (a, b) => a + b;
    
    console.log(add(1, 2) === 3); // true
    
    앞의 예에서 add 함수는 시종일관 같은 매개 변수에 대해 같은 결과를 되돌려준다. 1 + 2 = 3.주어진 특정한 매개 변수에서, 어떤 것이 되돌아올지 예상하고 예측할 수 있으며, 그 범위 밖의 어떤 상태도 바뀌지 않습니다.
    함수가 시간에 따라 변할 수 있는 값/상태에 의존하거나 부작용을 일으킬 때 이 함수pure를 고려하지 않는다.예를 들면 다음과 같습니다.
    // This function depends on a random number, given the same inputs
    // it won't always return the same output, hence NOT PURE.
    function getRandomNumberFromRange(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    
    함수가 순수 함수로 간주될 수 없는 또 다른 상황은 조작 날짜에 의존하고, 이 날짜는 함수의 외부 범위에서 제어할 수 없다는 것이다.
    // This function depends on the current date
    // calling this function several times
    // will return a different result, hence NOT PURE.
    const getCurrentTimestamp = () => Date.now();
    
    // Now, if we look at this version
    // it will return the same output for the same input
    // hence PURE
    const getTimestamp = date => date.getTime();
    
    그런데 부작용은 무엇입니까?
    부작용은 호출된 함수 외부에서 되돌아오는 값이 아닌 응용 프로그램의 상태 변경을 알아볼 수 있습니다.우리 무슨 얘기하는 거야?
  • 데이터베이스 변경
  • 콘솔 또는 파일에 로그인
  • 네트워크를 통해 정보 변경 요청
  • 일부 외부 프로세스 시작
  • 실제 부작용이 있는 함수를 호출
  • 이것은 우리의 모든 코드가 부작용이 있을 수 없다는 것을 의미하는 것입니까?아니오, 이것은 단지 우리가 우리의 부작용 기능과 순수한 기능을 분리할 수 있다는 것을 의미할 뿐입니다. 예를 들어 서로 다른 분야에 대해 추리를 해야 합니다. 왜냐하면 그들은 사실상 서로 보완되기 때문입니다.
    우리는 정보를 순수 함수로 조작하고 결과 값을 데이터베이스에 쓰거나 대기열을 터치하거나 전자메일을 보낼 수 있는 일련의 기능을 가지고 있다.
    이것은 문제없다. 우리가 유지해야 할 심지 모델은 우리가 시스템에 부작용을 추가할 때 이러한 부작용을 포함하는 테스트를 작성해야 한다는 것이다. 예를 들어 이러한 부작용 서비스를 모의하거나 테스트 데이터베이스를 사용해야 한다.이곳의 실제 상황은 부작용이 확실하지 않기 때문에 우리는 그것들이나 그것들 주위의 변수를 조종하여 예상치를 얻어야 한다.

    불변성
    이것은 창설 후 수정할 수 없는 값이나 데이터 구조의 개념을 가리킨다. 이러한 값이나 데이터 구조를 수정하려면 시스템이 당시에 주목했던 정보를 포함하거나 포함하지 않은 값이나 데이터 구조의 사본을 만들어야 한다.
    JavaScript에서는 항상 const 키워드를 사용하여 상수로 저장된 값의 이러한 불변성 동작을 참조하지만 객체 수정을 막지는 않습니다.키워드const는 변수가 재분배될 수 없다는 것을 의미할 뿐 서로 다른 개념이다.
    Object.freeze() 동결 대상을 사용하여 불변성을 실현하는 방법
    예를 살펴보겠습니다.
    const wallet = {
        balance: 100,
        currencySymbol: 'WAX',
    };
    
    const walletReference = wallet;
    
    wallet.balance = 15;
    
    console.log(wallet.balance); // 15
    console.log(walletReference.balance); // 15
    
    수정balance 속성을 통해 월렛 대상에 변이가 생겼다. 월렛 대상은 두 변수(인용) 간의 공유 상태이기 때문에 잔액 변화는 두 변수에 반영될 것이다. 여러 해 동안 많은 시스템에서 번거로웠다.때로는 공유 상태가 예상치 못한 행위와 파괴적인 변화를 초래할 수 있기 때문에 우리는 엔지니어로서 모른다.
    그렇다면 어떤 방법이 상태를 바꾸지 않을 수 있을까?이전의 지갑을 들자.
    const addBalanceToWallet = (balance, wallet) => ({
        ...wallet,
        balance: wallet.balance + balance
    });
    const wallet = Object.freeze({
        balance: 100,
        currencySymbol: 'WAX',
    });
    
    wallet.balance = 1;
    
    console.log(wallet.balance); // 100 -> the value stays unchanged
    
    const walletReference = wallet;
    
    const updatedWallet = addBalanceToWallet(12, wallet);
    
    console.log(wallet.balance); // 100
    console.log(walletReference.balance); // 100
    console.log(updatedWallet.balance); // 112
    
    현재, 이 예에서, 우리는 새로운 지갑을 얻었는데, 원시 대상과 인용이 변하지 않고, 변화가 발생하지 않은 상황에서, 그것은 업데이트될 가치가 있다.그러나 Object.freeze 우리가 원하는 것처럼 진정으로 불변성을 실현하지 못했다. 왜냐하면 그것은 맨 윗부분/첫 번째 층에 있는'동결'대상일 뿐이기 때문에 그 어떠한 다른 대상도 수정할 수 있다는 것을 의미한다.우리는 이러한 대상을 동결하거나 일부 불변성 라이브러리(예를 들어 Immutable.js만 사용)를 통해 이런 상황이 발생하는 것을 방지할 수 있다.
    개인적으로 나는 과거에 공유 상태와 가변 대상을 부정확하게 처리하는 등 여러 가지 문제에 부딪혔다.나는 항상 불변성을 선호하기 때문에 적용되는 상황에서 던전을 사용하고 가능한 한 공유 상태를 피한다.

    진술식과 명령식
    저것들은 무엇입니까?
    성명식과 명령식 프로그래밍 모델은 서로 다른 심지 모델을 바탕으로 응용 프로그램에서 코드 블록을 구축하는 양식이다.FP에서는 항상 명령 모델이 아닌 선언 모델을 선호합니다.

    명령식 사고 패턴
    명령식 방법은 어떻게 일을 하는지 설명하는 데 전념한다. 이것은 프로그램의 흐름 제어에 전념한다는 것을 의미한다.예를 들면 다음과 같습니다.
    const users = [
        {
            name: 'John',
            lastname: 'Due',
        },
        {
            name: 'Some',
            lastname: 'Dude',
        },
    ];
    
    const allLastNames = [];
    
    for (const user of users) {
        allLastNames.push(user.lastname);
    }
    
    console.log(allLastNames); // ['Due', 'Dude']
    

    진술적 사유 패턴
    성명식 방법은 무엇을 해야 하는지 설명하는 데 전념한다. 이것은 프로그램의 데이터 흐름에 전념한다는 것을 의미한다.명령은 어떻게 다른 기능이나 층으로 추상화됩니까?예를 들면 다음과 같습니다.
    // users/utils.js
    export const getLastName = user => user.lastname;
    
    
    // main.js
    import { getLastName } from './users/utils';
    
    const users = [/* Imagine the users as before */];
    
    const allLastNames = users.map(getLastName);
    
    
    // The following will print ['Due', 'Dude']
    // Still the same result, but in a declarative way.
    console.log(allLastNames);
    
    현재, 우리는 사용자로부터 성씨의 세부 사항을 얻는 데 진정으로 관심이 없고, 그들을 얻는 방법에만 관심을 갖는다.
    저는 개인적으로 성명식 방법을 더 좋아합니다. 저에게는 더욱 읽을 만하고, 일반적인 일에 쓰이는 기술적 세부 사항이 아니라 더 많은 업무 영역 논리를 전달합니다.명령식 방법을 더 좋아하는 사람도 있다. 왜냐하면 그들은 그것을 읽는 것이 더 좋고, 의도도 명확하게 표현하기 때문이다. 그러나 성명식 방법에 대해서도 같은 말을 할 수 있기 때문이다.

    고급 함수
    이것은 내가 매우 좋아하는 개념으로 FP를 실행할 때 많은 코드 라이브러리에 사용된다.
    많은 FP 언어에서 함수는 first class citizens입니다.이것은 함수가 하나의 값으로 간주된다는 것을 의미한다. 함수는 매개 변수를 통해 다른 함수에 전달될 수도 있고, 함수에서 되돌아올 수도 있고, 변수에 분배될 수도 있다.
    고급 함수는 함수를 매개 변수로 받아들이거나 함수를 반환값으로 사용하는 함수이다.
    결과를 살펴보겠습니다.
    // We are returning a new function when calling add()
    // this is called `partial application`
    const add = a => b => a + b;
    
    // `add10` is now a function that can be called
    // it will always add 10 to the value passed
    const add10 = add(10);
    
    const numbers = [1, 2, 3, 4, 5, 6];
    
    // Here we pass our add10 function as parameter/argument
    // to the Array.prototype.map method
    console.log(numbers.map(add10));
    
    // Here we pass a whole new function to the
    // Array.prototype.reduce method in order to convert
    // the whole array into a different data type
    // in this case, a number
    const totalSum = numbers.reduce((total, num) => total + num, 0);
    
    console.log(totalSum); // 21
    
    앞의 예시에서, 우리는 함수를 변수에 어떻게 분배하고, 이 함수를 변수로 명명하는지 보았다.다른 함수에 함수를 전달하고 반환함으로써 이 개념이 얼마나 강력하고 얼마나 많은 기능을 수행하는지를 보여줍니다.

  • Partial Application .

  • Currying .

  • Function Composition .
  • 비동기 조작, 이벤트 등의 리셋.
  • 그래서 그것은 정말 강력하다. 만약 당신이 매일 자바스크립트를 사용한다면, 당신은 이 개념을 자주 사용할 것이다. 단지 하나의 그룹을 비추기만 하면 된다.나는 매일 그것을 사용한다. 나는 그것을 정말 좋아한다. 소프트웨어를 구축할 때, 그리고 내가 조합 대상을 필요로 하거나 데이터 파이프를 연결해서 데이터에 대한 N개의 연속 조작을 촉발할 때, 이것은 나에게 큰 도움이 되고, 나의 코드를 크게 간소화시켰다.

    결론
    이것은 단지 내가 함수식 프로그래밍에 관한 개념을 말하고 있을 뿐이지만, 나는 모든 내용을 포함하지 않는다. 단지 사람들이 이런 모델을 시도하도록 격려할 수 있을 것이라고 생각한다.
    이 점은 내가 아무리 강조해도 지나치지 않다. 이런 모델은 대상을 대상으로 프로그래밍하는 것을 대체할 수 없다. 사실상 그들은 상부상조하고 반응식 프로그래밍도 여기에 적용된다.만약 네가 이러한 범례를 한데 묶을 수 있다면, 너는 진정으로 건장한 소프트웨어를 구축할 수 있을 것이다. 이것은 훌륭한 인코딩, 학습, 체험이 될 것이다.
    FP에 마음을 열고 코드와 문제를 다른 방식으로 이해하고 추리할 수 있도록 도와준 지 수년이 지났습니다.설령 이것이 단지 학습 체험일지라도 나는 네가 한번 시도해 보라고 격려한다.후회하지 않을 거예요.
    --
    만약 당신이 더 많은 정보를 알고 싶다면, 나는 당신이 Eric Elliott의 Master the JavaScript Interview seriesComposing Software book 를 읽는 것을 건의합니다.

    좋은 웹페이지 즐겨찾기