19

javascriptを深く掘り下げるほど、特定の設計上の決定と奨励された実践の結果について考えるようになります。この場合、JavaScriptが提供するだけでなく、強く使用されている機能である無名関数を観察しています。

私たちは皆、次の事実に同意できると思います。

  • 人間の心は7プラスマイナス2エンティティを超えて処理しません(ミラーの法則
  • 深いインデントはプログラミングの悪い習慣と見なされ、3つまたは4つ以上のレベルをインデントすると、一般に設計上の問題が指摘されます。これはネストされたエンティティにまで及び、PythonZenのエントリ「フラットはネストされたものよりも優れています」によく示されています。
  • 関数名を持つという考えは、参照用であり、実行するタスクを簡単に文書化するためでもあります。removeListEntry()と呼ばれる関数が何をするかを知っているか、期待できます。自己文書化された明確なコードは、デバッグと読みやすさにとって重要です。

無名関数は非常に優れた機能のように見えますが、その使用は深くネストされたコード設計につながります。コードはすばやく記述できますが、読み取るのは困難です。機能の名前付きコンテキストを発明し、呼び出し可能なオブジェクトの階層を平坦化することを余儀なくされる代わりに、「深きものども」を促進し、脳のスタックを押し上げ、7+/-2ルールをすばやくオーバーフローさせます。同様の概念は、アラン・クーパーの「About Face」で表現されており、「人々は階層を理解していない」と大まかに引用しています。プログラマーとして、私たちは階層を理解していますが、私たちの生物学は依然として深い入れ子の把握を制限しています。

この点についてお聞きしたいのですが。匿名関数は有害であると見なされるべきでしょうか、後で塩であることがわかった明らかに光沢のある構文糖衣、あるいはネズミの毒でさえありますか?

正解がないのでCW。

4

8 に答える 8

16

私が見ているように、あなたが直面している問題は匿名関数ではなく、機能を有用で再利用可能な単位に分解したくないということです。これは興味深いことです。なぜなら、ファーストクラス関数(そして必然的に無名関数)を備えた言語では、機能を備えていない言語よりも機能を再利用する方が簡単だからです。

コード内に深くネストされた無名関数がたくさんある場合は、名前付きの高階関数(つまり、他の関数を取得または返す( "ビルド")する関数に分解できる一般的な関数がたくさんある可能性があります。関数)。既存の関数の「単純な」変換でさえ、頻繁に使用される場合は名前を付ける必要があります。これは単なるDRYの原則です。

于 2009-12-25T07:31:48.917 に答える
8

匿名関数は、読みやすく有害であるよりも機能的に有用です。コードを十分にフォーマットすれば、問題はないと思います。問題はありません。7+2は言うまでもなく、7つの要素を処理できないと確信しています:)

于 2009-12-25T05:07:10.073 に答える
4

実際、階層はOOPと同じ方法で7+/-2ルールを克服するのに役立ちます。クラスを書いたり読んだりするときは、そのコンテンツを読み、外部コードは何も読まないため、エンティティの比較的小さな部分を処理します。クラス階層を見るとき、それらの内部を見ることはありません。つまり、ここでも少数のエンティティを扱っていることになります。

入れ子関数の場合も同じです。コードを複数のレベルの階層に分割することで、人間の脳が理解できるように各レベルを十分に小さく保つことができます。

クロージャ(または無名関数)は、コードをOOPとは少し異なる方法に分割するのに役立ちますが、実際には階層を作成しません。これらは、他のコードブロックのコンテキストでコードを実行するのに役立ちます。C ++またはJavaでは、そのためのクラスを作成する必要があります。JavaScriptでは関数で十分です。確かに、スタンドアロンクラスは、人間がスタンドアロンブロックの場合と同じように見やすいため、理解しやすくなっています。関数のサイズははるかに小さいようで、脳は関数を理解し、同時にその周りをコード化できると考えることがありますが、これは通常は悪い考えです。しかし、あなたはそれをしないようにあなたの脳を訓練することができます:)

ですから、いいえ、匿名関数はまったく有害ではないと思います。クラスの扱い方を学んだので、匿名関数の扱い方を学ぶ必要があります。

于 2009-12-25T06:01:15.330 に答える
3

面白いことに、JavaScriptでは「匿名」関数に名前を付けることができます。

function f(x) {
   return function add(y) {
        return x+y;
   };
}
于 2009-12-26T01:18:34.290 に答える
2

閉鎖には、見逃してはならない大きなメリットがあると思います。たとえば、AppleはGCDで「ブロック」(Cのクロージャ)を利用して、非常に簡単なマルチスレッドを提供します。コンテキスト構造体を設定する必要はなく、スコープ内にあるため、名前で変数を参照できます。

Javascriptのより大きな問題は、ブロックスコープ(この場合のブロックは、ifステートメントのように中かっこで囲まれたコードを参照している)がないことだと思います。これは非常に複雑になる可能性があり、プログラマーはこのJavascriptデザインの制限を回避するために不要なクロージャーを使用する必要があります。

于 2009-12-25T05:05:41.240 に答える
0

また、無名関数(最新の言語ではクロージャと呼ばれることが多い)には大きな利点があり、コードが読みやすく短くなることが多いと思います。Java(クロージャがファーストクラスの言語機能ではない)を使用しなければならないとき、私は時々本当に頭がおかしくなります。

インデントとカプセル化された関数変数が多すぎることが問題である場合は、コードをリファクタリングして、よりモジュール化して読みやすくする必要があります。

java-scriptに関しては、関数変数は非常に見苦しく、コードが乱雑になると思います(カプセル化されたfunction(...){}文字列により、java-scriptコードが読みにくくなることがよくあります)。例として、私はgroovyのクロージャ構文('{}'および'->'文字)を非常に好みます。

于 2009-12-26T00:36:40.237 に答える
0

名前がないと関数が理解できない場合は、名前が長すぎる可能性があります。コメントを使用して不可解なコードを説明します。名前に依存しないでください。

于 2009-12-26T04:07:44.420 に答える
-2

関数を識別子にバインドすることを要求するというアイデアを思いついた人は、すべてのプログラマーに不利益をもたらしました。関数型プログラミングを行ったことがなく、関数が一流の値であることに慣れておらず、慣れていない場合は、実際のプログラマーではありません。

実際、あなた自身の議論に対抗するために、私は(グローバルな)名前にバインドされた関数を有害であると考えるところまで行きます!プライベートメンバーとパブリックメンバーに関するCrockfordの記事を確認し、詳細を確認してください。

于 2009-12-25T06:24:45.237 に答える