태그 보관물: patterns-and-practices

patterns-and-practices

다른 함수에서만 사용되는 함수를 해당 함수 내에 배치해야합니까? 쓰고 있습니다. 기본

특히, 나는 JavaScript로 쓰고 있습니다.

기본 함수가 함수 A라고 가정 해 봅시다. 함수 A가 함수 B를 여러 번 호출하지만 함수 B가 다른 곳에서는 사용되지 않는다면 함수 B를 함수 A 내에 두어야합니까?

좋은 습관입니까? 아니면 여전히 기능 B를 기능 A와 동일한 범위에 두어야합니까?



답변

나는 일반적으로 JavaScript에서 중첩 함수를 선호합니다.

  • JavaScript에서 함수의 가시성을 제한하는 유일한 방법은 다른 함수 안에 중첩시키는 것입니다.
  • 헬퍼 함수는 개인용 구현 세부 사항입니다. 같은 범위에 두는 것은 클래스의 개인 함수를 공개하는 것과 유사합니다.
  • 더 일반적으로 사용되는 것으로 판명되면 도우미가 현재 해당 기능 중 하나만 사용하고 있다고 확신 할 수 있기 때문에 쉽게 이동할 수 있습니다. 즉, 코드를보다 응집력있게 만듭니다.
  • 함수 시그니처와 구현을 덜 장황하게 만드는 매개 변수를 종종 제거 할 수 있습니다. 변수를 전역으로 만드는 것과는 다릅니다. 개인 메서드에서 클래스 멤버를 사용하는 것과 비슷합니다.
  • 충돌에 대해 걱정하지 않고 헬퍼 기능에 더 나은 이름을 제공 할 수 있습니다.
  • 도우미 기능을 쉽게 찾을 수 있습니다. 예, 도움을 줄 수있는 도구가 있습니다. 여전히 눈을 화면 위로 조금 올리는 것이 더 쉽습니다.
  • 코드는 자연스럽게 일종의 추상화 트리를 형성합니다. 루트에서 몇 가지 일반적인 기능은 몇 가지 구현 세부 사항으로 나뉩니다. 함수 접기 / 접기 기능이있는 편집기를 사용하는 경우 중첩을 사용하면 동일한 추상화 수준에서 밀접하게 관련된 함수의 계층 구조가 생성됩니다. 따라서 필요한 수준에서 코드를 쉽게 연구하고 세부 사항을 숨길 수 있습니다.

나는 대부분의 프로그래머들이 C / C ++ / Java 전통에서 자랐거나 다른 누군가에 의해 가르쳐 졌다는 사실에서 많은 반대가 생각된다. 중첩 함수는 프로그래밍을 배우면서 많이 노출되지 않았기 때문에 자연스럽게 보이지 않습니다. 그렇다고해서 유용하지 않다는 의미는 아닙니다.


답변

여러 가지 이유로 글로벌 범위에 배치해야합니다.

  • 헬퍼 함수를 ​​호출자에 중첩 시키면 호출자의 길이가 증가합니다. 함수 길이는 거의 항상 음의 지표입니다. 짧은 기능은 이해, 암기, 디버그 및 유지 관리가 더 쉽습니다.

  • 도우미 함수의 이름이 알기 쉬운 경우 근처의 정의를 볼 필요없이 해당 이름을 읽는 것으로 충분합니다. 당신이 경우에 호출자가 너무 많이하고있다, 또는 동시에 추상화 너무 많은 수준에 작동하고 있는지 다음, 호출자의 기능을 이해하기 위해 도우미 정의를 볼 필요가있다.

  • 헬퍼를 전역 적으로 사용할 수있게하면 다른 함수가 일반적으로 유용 할 경우이를 호출 할 수 있습니다. 도우미를 사용할 수 없으면 잘라내어 붙여 넣거나 잊어 버린 후 다시 구현하거나, 다른 기능을 이전보다 길게 만들려고합니다.

  • 도우미 함수를 중첩하면 선언하지 않고 호출자의 범위에서 변수를 사용하려는 유혹이 증가하여 도우미의 입력과 출력이 무엇인지 명확하지 않게됩니다. 함수가 작동하는 데이터와 그 영향을 명확하게 나타내지 않으면 일반적으로 불명확 한 책임의 징조입니다. 도우미 엉덩이를 독립형 함수로 선언하면 실제로 수행하는 작업 만 알 수 있습니다.

편집하다

그것은 내가 생각했던 것보다 더 논란의 여지가있는 질문으로 판명되었습니다. 명확히하기 위해 :

JavaScript에서 큰 파일 확장 기능은 언어가 다른 범위 제한 메커니즘을 제공하지 않기 때문에 클래스의 역할을 수행하는 경우가 많습니다. 분명히 도우미 기능은 외부가 아닌 그러한 준 클래스 내부에 있어야 합니다.

그리고 서브 루틴이 경우에 것을 쉽게 재사용 전제에 대한 포인트 않습니다 가 더 널리 사용, 당신은 완전히 장소의 그것을 밖으로 이동하고 적절한 장소, 예를 들어, 문자열 유틸리티 라이브러리 또는 글로벌 구성 레지스트리에 넣어하고자합니다. 만약 당신이 그런 코드를 주문하고 싶지 않다면 ,보다 “고질적 인”언어 로 된 일반적인 Method Object 를 사용하는 것처럼 서브 루틴을 중첩시킬 수도 있습니다.


답변

두 함수를 클로저 내에 배치하는 세 번째 경로를 제안하겠습니다. 다음과 같습니다.

var functionA = (function(){
    function functionB() {
        // do stuff...
    }

    function functionA() {
        // do stuff...
        functionB();
        // do stuff...
    }

    return functionA;
})();

우리는 두 함수의 선언을 IIFE 에 래핑하여 클로저를 만듭니다 . IIFE의 반환 값은 공용 함수이며 함수 이름의 변수에 저장됩니다. 퍼블릭 함수는 마치 전역 함수로 선언 된 것과 똑같은 방식으로 호출 할 수 있습니다 functionA(). 반환 값 은 함수 에 대한 호출이 아니라 함수이므로 끝 부분에 구문 분석이 없습니다.

이렇게 두 함수를 래핑하면 functionB이제 완전히 비공개이며 클로저 외부에서 액세스 할 수 없지만에만 표시됩니다 functionA. 그것은 글로벌 네임 스페이스를 어수선하게하지 않는, 그리고 정의의 혼란을하지 않습니다 functionA.


답변

함수 A 내에서 함수 B를 정의하면 함수 B가 A의 내부 변수에 액세스 할 수 있습니다.

따라서 함수 A 내에 정의 된 함수 B는 B가 A의 지역 변수를 사용하거나 변경하고 있다는 인상 (또는 적어도 가능성)을 제공합니다. A 외부에서 B를 정의하는 동안 B는 그렇지 않다는 것이 분명해집니다.

따라서 코드의 명확성을 위해 B가 A의 로컬 변수에 액세스해야하는 경우에만 A 내에서 B를 정의합니다. B가 A와 독립적 인 명확한 목적을 가지고 있다면 A 외부에서 분명히 정의합니다.


답변

그렇지 않으면 외부 함수를 호출 할 때마다 중첩 된 함수가 다시 작성되므로 중첩해서는 안됩니다.


답변

함수 B는 다른 곳에서 사용되지 않기 때문에 함수 A 내에서 함수로 만들 수도 있습니다. 그것이 함수의 유일한 이유이기 때문입니다.


답변