매개 변수로 다른 함수에 함수를 전달하는 것은 나쁜 습관입니까?


40

AS3 애플리케이션이 백엔드와 통신하는 방식을 변경하는 과정에 있으며 이전 시스템을 대체하기 위해 REST 시스템을 구현하는 중입니다.

안타깝게도 작업을 시작한 개발자는 현재 장기 병가에 있으며 나에게 넘겨졌습니다. 나는 지난 주 정도 동안 그 일을 해왔고 시스템을 이해하지만 걱정되는 것이 하나 있습니다. 함수에 함수가 많이 전달되는 것 같습니다. 예를 들어 서버를 호출하는 클래스는 프로세스가 완료되고 오류가 처리되었을 때 객체를 호출하고 전달하는 기능을 수행합니다.

그것은 내가 끔찍한 연습이라고 생각하는 "나쁜 느낌"을주고 있으며 그 이유를 생각할 수 있지만 시스템에 재 작업을 제안하기 전에 확인을 원합니다. 누군가이 가능한 문제에 대해 경험이 있는지 궁금합니다.


22
왜 그렇게 느끼 니? 함수형 프로그래밍 경험이 있습니까? (나는 가정하지 않지만 살펴보아야한다)
Phoshi

8
그런 다음이 교훈을 고려하십시오! 학계가 가르치는 것과 실제로 유용한 것은 종종 놀랍게도 거의 중복되지 않습니다. 그런 종류의 교리와 맞지 않는 전 세계의 프로그래밍 기술이 있습니다.
Phoshi

32
함수를 다른 함수에 전달하는 것은 언어가 지원하지 않을 때 사람들이 문제의 함수를 스톱 갭으로 포함하는 것이 단순한 사소한 "객체"를 만드는 데 방해가되는 기본적인 개념입니다.
Doval

36
나의 시대에 우리는이 함수들을 "콜백"함수라고 부릅니다.
Mike

답변:


84

문제가되지 않습니다.

알려진 기술입니다. 이들은 고차 기능 (기능을 매개 변수로 취하는 기능)입니다.

이러한 종류의 함수는 함수형 프로그래밍 의 기본 구성 요소이며 Haskell 과 같은 함수형 언어에서 광범위하게 사용됩니다 .

이러한 기능은 나쁘거나 좋지 않습니다. 개념과 기술을 접한 적이 없다면 처음에는 이해하기 어려울 수 있지만 매우 강력하고 툴 벨트에 유용한 도구입니다.


덕분에 기능 프로그래밍에 대한 실제 경험이 없으므로 자세히 살펴 보겠습니다. 내 작은 지식으로 인해 개인 함수로 무언가를 선언하면 해당 클래스 만 액세스 할 수 있어야하며 객체를 참조하여 공개 클래스 만 호출해야하기 때문에 잘 앉아 있지 않았습니다. 제대로 살펴보고 조금 더 감사하겠습니다.
Elliot Blackburn


8
당신은 사용이 괜찮 후 특정 기능을위한 콜백으로 경우에 당신이 그것을 사용하는 방법을 제어하려면 개인으로 뭔가를 선언 @BlueHat
래칫 괴물은

5
바로 그거죠. 비공개로 표시하면 다른 사람이 언제라도 이름을 사용하여 액세스하고 싶지 않다는 것을 의미합니다. 특정 사용자 가 해당 매개 변수에 대해 문서화하는 방식으로 호출하기를 하기 때문에 다른 사람에게 개인용 함수를 전달하는 것은 절대적으로 좋습니다. 그것은 아마도 :-) 당신과 함께 심하게 앉아 있지 않는 다른 함수에 매개 변수로 개인 필드의 값을 통과 달라진 할 필요는 없다
스티브 Jessop

2
생성자 매개 변수로 함수를 사용하여 구체적인 클래스를 작성하는 경우 tm 을 잘못 수행 할 수 있습니다 .
Gusdor

30

함수형 프로그래밍에만 사용되는 것은 아닙니다. 콜백 이라고도합니다 .

콜백은 다른 코드에 인수로 전달되는 실행 가능한 코드로, 편리한 시간에 인수를 콜백 (실행)해야합니다. 동기식 콜백에서와 같이 즉시 호출되거나 비동기식 콜백에서와 같이 나중에 발생할 수 있습니다.

비동기 코드에 대해 잠시 생각해보십시오. 예를 들어 데이터를 사용자에게 보내는 함수를 전달합니다. 코드가 완료된 경우에만 응답 결과와 함께이 함수를 호출하면 함수가 데이터를 사용자에게 다시 보내는 데 사용합니다. 사고 방식의 변화입니다.

시드 박스에서 Torrent 데이터를 검색하는 라이브러리를 작성했습니다. 비 블로킹 이벤트 루프를 사용하여이 라이브러리를 실행하고 데이터를 가져온 다음 사용자에게 반환합니다 (예 : 웹 소켓 컨텍스트). 이 이벤트 루프에 5 명이 연결되어 있고 다른 사람의 급류 데이터 중단 요청 중 하나가 있다고 가정하십시오. 전체 루프가 차단됩니다. 따라서 비동기 적으로 생각하고 콜백을 사용해야합니다. 루프가 계속 실행되고 "데이터를 사용자에게 다시 제공"하는 기능은 실행이 완료된 후에 만 ​​실행되므로 기다릴 필요가 없습니다. 발사하고 잊어 버리십시오.


1
+1 콜백 용어를 사용합니다. 이 용어는 "고차 함수"보다 훨씬 자주 발생합니다.
Rodney Schuler

OP가 일반적인 고차 함수뿐만 아니라 콜백을 설명하는 것처럼 보였기 때문에이 답변이 마음에 듭니다. "예를 들어 서버를 호출하는 클래스는 객체를 호출하고 전달하는 함수를 사용합니다. 프로세스가 완료되고 오류가 처리 된 시점까지
Ajedi32

11

이것은 나쁜 것이 아닙니다. 사실, 그것은 아주 좋은 것입니다.

함수에 함수를 전달하는 것은 프로그래밍에서 매우 중요하므로 람다 함수 를 속기로 발명했습니다 . 예를 들어, C ++ 알고리즘과 함께 람다를 사용 하여 매우 작지만 표현적인 코드를 작성하여 일반 알고리즘이 지역 변수 및 기타 상태를 사용하여 검색 및 정렬과 같은 작업을 수행 할 수 있습니다.

객체 지향 라이브러리 에는 본질적으로 적은 수의 함수를 지정하는 인터페이스 인 콜백 이 있을 수 있습니다 (이상적으로 항상 그런 것은 아니지만). 그런 다음 해당 인터페이스를 구현하고 해당 클래스의 객체를 함수에 전달하는 간단한 클래스를 만들 수 있습니다. 이는 이벤트 중심 프로그래밍 의 초석입니다 . 프레임 워크 수준 코드 (아마도 다른 스레드에서도)는 사용자 작업에 대한 응답으로 상태를 변경하기 위해 개체를 호출해야합니다. Java의 ActionListener 인터페이스가 이에 대한 좋은 예입니다.

기술적으로 C ++ functor는 구문 설탕을 활용 operator()()하여 동일한 작업을 수행하는 콜백 객체 유형입니다 .

마지막으로 C에서만 사용해야하는 C 스타일 함수 포인터가 있습니다. 자세한 내용은 다루지 않겠습니다. 위에서 언급 한 다른 추상화는 훨씬 뛰어나므로 해당 언어로 사용해야합니다.

다른 사람들은 함수형 프로그래밍과 그 언어에서 함수 전달이 매우 자연스러운 방법에 대해 언급했습니다. Lambda와 콜백은 절차 및 OOP 언어가이를 모방하는 방식이며 매우 강력하고 유용합니다.


또한 C # 델리게이트와 람다는 모두 광범위하게 사용됩니다.
Evil Dog Pie

6

이미 말했듯이 나쁜 습관은 아닙니다. 그것은 단지 책임을 분리하고 분리하는 방법 일뿐입니다. 예를 들어 OOP에서는 다음과 같은 작업을 수행합니다.

public void doSomethingGeneric(ISpecifier specifier) {
    //do generic stuff
    specifier.doSomethingSpecific();
    //do some other generic stuff
}

일반적인 방법은 인터페이스를 구현하는 다른 객체에 특정 작업을 위임하는 것입니다. 일반적인 방법은이 인터페이스 만 알고 있습니다. 귀하의 경우이 인터페이스는 호출되는 함수입니다.


1
이 관용구는 단순히 함수를 인터페이스에 래핑하여 원시 함수를 전달하는 것과 매우 유사한 기능을 수행합니다.

그렇습니다. 나는 이것이 드문 습관이 아니라는 것을 보여주고 싶었습니다.
Philipp Murry

3

일반적으로 함수를 다른 함수에 전달하는 데 아무런 문제가 없습니다. 비동기식 호출을 수행하고 결과로 무언가를 수행하려는 경우 일종의 콜백 메커니즘이 필요합니다.

간단한 콜백에는 몇 가지 잠재적 인 단점이 있습니다.

  • 일련의 호출을하려면 깊은 콜백 중첩이 필요할 수 있습니다.
  • 일련의 호출에서 각 호출에 대해 오류 처리에 반복이 필요할 수 있습니다.
  • 여러 번의 전화를 동시에하고 한 번에 모두 마치면 여러 번의 전화 조정이 어색합니다.
  • 일련의 통화를 취소하는 일반적인 방법은 없습니다.

간단한 웹 서비스를 사용하면 잘 작동하지만 더 복잡한 호출 순서가 필요한 경우 어색해집니다. 그래도 대안이 있습니다. 예를 들어 JavaScript를 사용하면 promise 사용으로 전환되었습니다 ( javascript promises에 대한 장점 ).

여전히 함수를 다른 함수에 전달하는 것과 관련이 있지만 비동기식 호출은 콜백을 직접받는 것이 아니라 콜백을받는 값을 반환합니다. 이렇게하면 이러한 통화를 함께 구성 할 수있는 유연성이 향상됩니다. 이와 같은 것을 ActionScript에서 상당히 쉽게 구현할 수 있습니다.


또한 콜백을 불필요하게 사용하면 코드를 읽는 사람의 실행 흐름을 따르기가 더 어려워 질 수 있다고 덧붙입니다. 코드의 먼 부분에 설정된 콜백보다 명시적인 호출이 이해하기 쉽습니다. 그럼에도 불구하고 이는 브라우저 및 기타 이벤트 기반 시스템에서 이벤트가 발생하는 방식입니다. 이벤트 이미 터의 전략을 이해해야 이벤트 핸들러가 언제 그리고 어떤 순서로 호출되는지 알 수 있습니다.
joeytwiddle
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.