신속하고 순수한 함수

3123 단어 swiftfunctional
저는 2016년부터 2020년까지 Salesforce Events iOS 팀에서 일했습니다. 이 기간 동안 기능적 반응 원칙을 사용하여 코드베이스를 개선했습니다. 저에게 가장 눈에 띄는 이점은 다음과 같습니다.
  • 충돌률은 100회 발사당 1회에서 40,000회당 1회로 떨어졌습니다.
  • 버그 비율이 감소하고 버그 해결 시간이 감소했습니다.
  • 개발 속도 증가.

  • 순수 함수란 무엇입니까?


  • 주어진 입력 집합에 대해 항상 동일한 값을 반환하는 경우 함수는 순수합니다.
  • 순수 함수는 부작용이 없습니다.

  • 부작용은 다음과 같습니다. 함수의 입력 매개변수 집합 외부에 있는 상태를 읽거나 씁니다.

    다음은 불순한 함수의 고안된 예입니다.

    //not pure
    //has side effects
    //doesn't always return same values for input
    struct Adder {
        var sum: Int = 0
        var left: Int = 0
        var right: Int = 0
    
        func add () {
            self.sum = self.left + self.right
        }
    }
    


    그리고 위의 두 가지 기준을 충족하는 순수한 예입니다. 주어진 입력에 대해 동일한 출력을 반환합니다. 부작용이 없습니다.

    func pureAdd (left: Int, right: Int) → Int {
        return left + right
    }
    


    테스트당 비용



    주어진 입력 세트가 올바른 출력을 생성한다고 주장하는 테스트를 작성하는 것은 테스트가 얻을 수 있는 만큼 간단합니다. 조롱 또는 상태 초기화가 필요하지 않습니다.

    위의 예제 함수가 주어지면 pureAdd 테스트를 간단하게 수행할 수 있습니다.

    assertEqual(pureAdd(1, 99), 100)
    assertEqual(pureAdd(1, 0), 1)
    assertEqual(pureAdd(2, 2), 4)
    


    순수하지 않은 예제는 어설션당 더 많은 설정이 필요합니다.

    let adder = Adder()
    adder.left = 1
    adder.right = 0
    adder.add()
    assertEqual(adder.sum, 1)
    


    일반적으로 함수에 부작용이 많을수록 테스트당 비용이 높아집니다.

    순수 함수의 유효성 테스트



    단위 테스트의 목표는 테스트 중인 함수가 입력 공간에 대해 올바른 출력을 생성함을 증명하는 것입니다.

    isTrue(input: Bool) -> Bool 함수의 경우 입력 공간에는 true와 false의 두 가지 가능성이 있습니다. 따라서 정확성을 증명하려면 두 가지 주장이 필요합니다.

    assertEqual(isTrue(true), true)
    assertEqual(isTrue(false), false)
    


    두 번째 Bool 매개변수를 추가하면 입력 공간이 두 배가 되고 정확성을 증명하는 데 필요한 단정문의 수가 두 배가 됩니다.

    assertEqual(areTrue(true, true), true)
    assertEqual(areTrue(true, false), false)
    assertEqual(areTrue(false, false), false)
    assertEqual(areTrue(false, true), false)
    


    순수 함수의 경우 정확성을 증명하는 데 필요한 어설션의 수는 입력 공간의 곱입니다. 이것은 입력 공간을 제한하면 모든 입력에 대해 올바른 출력을 증명하기 위한 테스트 노력을 줄이는 데 도움이 된다는 것을 의미합니다.

    입력 공간을 줄이려면 가능한 값의 개별 개수가 있는 입력 매개변수를 사용하는 것이 좋습니다. 예를 들어 열거형에는 한정된 값 집합이 있는 반면 문자열에는 무한한 수의 가능한 값이 있으므로 가능한 경우 열거형과 문자열을 사용하는 것이 좋습니다.

    순수하지 않은 함수의 유효성 테스트



    비순수 함수의 경우 입력 공간에 대한 올바른 출력을 증명하는 것이 몇 가지 이유로 훨씬 더 어렵습니다.
  • 비순수 함수에 대한 입력에는 개체 및 전역 상태가 포함될 수 있습니다.
  • 이 확장된 입력 공간은 정확성을 증명하는 데 필요한 주장의 수를 증가시킵니다.
  • 위에서 볼 수 있듯이 테스트당 스캐폴딩 비용은 종종 이러한 기능에 대해 더 높습니다.
  • 함수가 완료되기 전에 공유 상태가 외부적으로 변경될 수 있습니다.

  • 필요한 노력이 증가함에 따라 이러한 기능에 대한 정확성을 증명하는 것이 어려울 수 있으며 대신 코드 적용 범위를 대상으로 합니다.

    적용 범위는 함수에 일정 수준의 단위 테스트가 있는지 확인하는 데 도움이 되는 좋은 메트릭이지만 코드 적용 범위가 함수의 정확성을 보장하는 것과 동일하다고 생각하지 않습니다.

    마무리 생각



    읽어 주셔서 감사합니다. 이 게시물은 순수한 함수가 테스트와 관련하여 우리에게 어떻게 도움이 되는지에 초점을 맞췄습니다. 그러나 탐색할 가치가 있는 동시성, 반응성 및 구성과 같은 기능적 프로그래밍 및 Swift에서 얻을 수 있는 더 많은 이점이 있습니다.

    좋은 웹페이지 즐겨찾기