순수한 미학적 이유로 중첩 함수를 작성 하시겠습니까?


16

나는 항상 다른 프로그래머들이 순수한 미적 기능을 만드는 아이디어에 대해 어떻게 생각하는지 궁금했습니다.

데이터 덩어리를 처리하는 함수가 있다고 가정 해보십시오 Function ProcessBigData. 내가 그 데이터에 대해서만 유효, 여러 공정 단계를 필요 말 : Step1, Step2, Step3.

소스 코드에서 가장 많이 보는 일반적인 접근 방식은 다음과 같이 주석을 작성하는 것입니다.

Function ProcessBigData:
    # Does Step1
    Step1..
    Step1..

    #Does Step2
    Step2..
    Step2..

내가 일반적으로하지만 동료 동료가 그러한 코딩 스타일이 없기 때문에 항상 잘못 느낀 것은 다음과 같습니다.

Function ProcessBigData:
    Function Step1:
        Step1..
        Step1..

    Function Step2:
        Step2..
        Step2..

    Step1() -> Step2()

JavascriptPython 에서 이러한 스타일에 대한 결점이 있는지 주로 걱정합니다.

내가 보지 못한 대안이 있습니까?


3
파이썬에 대해서는 아무 말도 할 수 없지만 Javascript의 경우 중첩 함수에 대한 성능 비용이 있습니다. 대부분의 JavaScript 엔진은 연결된 목록과 유사한 구조를 사용하여 변수 범위를 나타냅니다. 따라서 추가 기능 계층을 추가하면 변수를 해결할 때 엔진이 더 길거나 큰 데이터 구조를 검색 할 수 있습니다. 반면에, 모든 악의 근원은 물론 조기 최적화입니다. :)
Marco

답변:


4

생각보다 이상하지 않습니다. 예를 들어, 표준 ML에서는 도우미 기능의 범위를 제한하는 것이 일반적입니다. 물론 SML에는 다음과 같은 구문이 있습니다.

local
    fun recursion_helper (iteration_variable, accumulator) =
        ... (* implementation goes here *)
in
    fun recursive_function (arg) = recursion_helper(arg, 0);
end

1) 작은 함수가 프로그램에 대한 추론을 용이하게하고 2)이 함수가 해당 범위 밖에서 사용되지 않는다는 것을 독자에게 신호한다는 점을 감안할 때이 좋은 스타일을 고려할 것입니다.

외부 함수가 호출 될 때마다 내부 함수를 만드는 데 약간의 오버 헤드가있을 수 있다고 생각합니다 (JS 또는 Python이이를 최적화하는지 여부는 알 수 없음). 그러나 조기 최적화에 대해 어떻게 말하는지 알고 있습니다.


11

일반적으로 가능할 때마다이 작업을 수행하는 것이 좋지만 이러한 종류의 작업은 "단계"가 아니라 하위 작업으로 생각 합니다.

이 특정 책임을 가지며, 입력 정의 (들), 출력 (들) (생각해 하위 작업을 수행 할 수있는 작업의 특정 단위 인 은 "S" 에서 SOLID ). 서브 태스크는 재사용 할 필요가 없습니다. 어떤 사람들은 "다른 것으로부터 이것을 호출 할 필요가 없으므로 왜 이것을 함수로 작성해야합니까?"라고 생각하는 경향이 있습니다. 그러나 그것은 잘못된 것입니다.

또한 장점과 클래스의 다른 함수에 비해 중첩 함수 (클로저)에 어떻게 적용되는지 설명하려고합니다. 일반적으로 말하자면, 특별히 필요하지 않은 경우 클로저를 사용하지 않는 것이 좋습니다 (많은 용도가 있지만 코드를 논리적 청크로 분리하는 것은 그중 하나가 아닙니다).

가독성.

200 줄 이상의 절차 코드 (함수 본문)는 읽기가 어렵습니다. 2-20 개의 라인 기능을 쉽게 읽을 수 있습니다. 코드는 인간을위한 것입니다.

중첩 여부에 관계없이 부모 범위에서 많은 변수를 사용하지 않는 한 대부분의 가독성을 얻습니다.이 경우 읽기가 어려울 수 있습니다.

변수 범위 제한

다른 기능을 사용하면 변수 범위를 제한하고 특히 필요한 것을 전달해야합니다.

이전의 "단계"에서 일종의 상태 변수가 필요한 경우 실제로 해당 값을 얻기 위해 먼저 작성하고 실행해야하는 다른 하위 작업이 있다는 것을 알 수 있기 때문에 이것은 종종 구조 코드를 더 잘 만듭니다. 다시 말해, 결합 된 코드 덩어리를 작성하기가 더 어려워집니다.

중첩 함수를 사용하면 중첩 함수 (클로저) 내부에서 상위 범위의 변수에 액세스 할 수 있습니다. 이 기능은 매우 유용 할 수 있지만, 함수 실행이 작성된 방식으로 실행되지 않을 수 있으므로 미묘하고 찾기 어려운 버그로 이어질 수 있습니다. 부모 범위에서 변수를 수정하는 경우 훨씬 더 그렇습니다 (일반적으로 나쁜 생각).

단위 테스트

함수 (또는 클래스)로 구현 된 각 하위 작업은 테스트 가능한 독립 실행 형 코드입니다. 단위 테스트TDD 의 이점은 다른 곳에 잘 정리되어 있습니다.

중첩 함수 / 클로저를 사용하면 단위 테스트가 허용되지 않습니다. 나에게 이것은 거래 차단기이며 폐쇄가 필요하지 않은 한 다른 기능을 사용해야하는 이유입니다.

팀 작업 / 하향식 디자인

하위 작업은 필요한 경우 독립적으로 다른 사람이 작성할 수 있습니다.

혼자서도 주요 기능을 구축하는 동안 아직 존재하지 않는 일부 하위 작업을 호출하기 위해 코드를 작성할 때 유용 할 수 있으며, 필요한 결과를 얻을 수 있다는 것을 알고 난 후에 만 ​​하위 작업을 실제로 구현하는 것에 대해 걱정할 수 있습니다. 의미있는 방법. 이를 하향식 설계 / 프로그래밍이라고도합니다.

코드 재사용

좋아, 그래서 이전에 말한 것에도 불구하고 때로는 때로는 다른 작업을 위해 하위 작업을 재사용 해야하는 이유가되기도합니다. 나는 "아키텍처 우주 비행사"-주의를 옹호하는 것이 아니라 느슨하게 결합 된 코드를 작성함으로써 나중에 재사용함으로써 이익을 얻을 수 있다는 것입니다.

종종 재사용은 완벽하게 예상되는 일부 리팩토링을 의미하지만, 입력 매개 변수를 작은 독립형 함수로 리팩토링하는 것이 작성된 후 200 개월 이상의 라인 함수에서 추출하는 것보다 훨씬 쉽습니다.

중첩 된 함수를 사용하는 경우 다시 사용하는 것은 일반적으로 별도의 함수로 리팩토링하는 문제이므로 중첩 된 방법이 아니라고 주장합니다.


2
이것들은 일반적으로 함수를 사용하는 데 유효한 몇 가지 요점이지만, NESTED 함수가 좋은 아이디어라고 생각하면 대답을 얻지 못했습니다. 아니면 업스트림 범위에서 기능을 사용합니까?
Slytael

미안하지만, 그 부분을 해결하는 것을 잊어 버린 다른 이점에 푹 빠져있었습니다. :) 수정되었습니다.
gregmac
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.