Witからの災い、または優秀な学生が不可解なコードを書く理由

私たちのほとんどは、学校や大学で数学の成績が優秀でした。 例の解決方法を覚えていますか? 関数の導関数を取る必要があるとしましょう:







$ f(x)= \ frac {\ ln {x}} {x ^ 2} $







数秒間考えて、完成した結果を書き留めました。







$ f '(x)= \ frac {1-2ln {x}} {x ^ 3} $







生徒たちは、決定を段階的に書き留め、より多くの時間を費やしました。







$ f '(x)= \ left(\ frac {ln {x}} {x ^ 2} \ right)' = \ frac {(ln {x}) '\ cdot x ^ 2-ln {x} \ cdot (x ^ 2) '} {(x ^ 2)^ 2} = \\ \ frac {\ frac {\ frac {1} {x} \ cdot x ^ 2-ln {x} \ cdot 2 x} {x ^ 4} = \ frac {x-ln {x} \ cdot 2 x} {x ^ 4} = \\ \ frac {x \ cdot(1-ln {x} \ cdot 2)} {x ^ 4} = \ frac { 1-2 ln x} {x ^ 3} $







私たち、優秀な学生、これはすべて役に立たない。 すぐに答えられるのに、なぜ多くの不必要な中間ステップを書くのですか? しかし、次の例に進むために、この例をすぐに取り除きたいです!



他の人ができないのに、なぜ私たちはこれを行うことができますか?



数学と短期記憶



いいえ、心の中で必要な操作をすべて実行できることは明らかであり、中間結果を紙に書く必要はありません。 しかし、なぜこれが可能ですか?



認知心理学では、「心の中で」計算が直接実行される記憶の部分は、短期的で働きやすいと呼ばれます。 そこにはすべてが複雑で曖昧ですが、あなたがそれを呼ぶものは何でも、このメモリの量は非常に限られています。 さまざまな研究者が「マジックナンバー」を7と5と呼んでいます。 これらは平均値です。 「作業」メモリの量は状況に依存し、知的能力と相関します。



中間結果を記録しない機能は、作業(または短期)メモリの機能によるものであることがわかります。 私たち技術者にとって、「技術的な」要素を保存するための作業メモリは人文科学のものよりも大きいです。 メモリが多いほど、書き込みを行わずにメモリに蓄積できる中間ステップが増えます。



プログラミングと短期記憶



それでは、プログラミングを行うときに超大国がどのように機能するかを想像してみましょう。



結果の問題を解決するには、一定量のコードを記述する必要があります。 しかし、私たちは急いでいます、そして、私たちは頭の中で多くの詳細を保つことができます。 私が運転している場所を感じますか? 中間ステップは記録しません。 代わりに、ソースデータを受け取り、すぐに完成した結果を生成するアルゴリズムを作成します。 これらは長く、これらのアルゴリズムであり、多くの作業を行います。 それらが書かれたとき、私たちは自分の作業メモリに収まることができました。

仮説。 プログラマーが賢くなればなるほど(彼が持っている作業メモリが大きくなるほど)、彼が書くメソッドと関数は長くなります。



プログラミング時に必要な作業メモリの量を計算してみましょう。 思考がどのように機能し、どのような種類の「オブジェクト」で動作するのか正確にはわからないので、プログラムコードで見つかった独立したオブジェクトを単純にカウントします。



実験として、 BigBlueButtonプロジェクトから150行のRuby関数取得しました。 私は、このコードが生きていることで私に感動したことをすぐに認めます。 私は数日を費やし、プロジェクトのごく一部の機能に表面的な変更を加えるためにいくつかの方法をほぼ完全に書き直さなければなりませんでした。 単一の長い行シーケンスを再利用することはできません。



このコードは仮説を完全に示しています。 例の解決に使用したとおりに作成されました。 中間ステップの質量は直接頭に保持され、最終決定のみが論文に当たりました。 一気にタスク全体を解決する150行が急降下しました。 このコードは非常に才能のある男によって明らかに書かれました!



これは悪意のあることではありません。 プログラマーの仕事の基本は、膨大な数のオブジェクトとそれらの間の接続を念頭に置くことです。 できるだけ早くそれらを取り除き、次の大きなオブジェクトのセットに進むために、これらのオブジェクトを1つのメソッドですぐに使用するという事実の何が問題になっていますか? 「少しずつ」、「一歩一歩」という問題に対する一貫した解決策-これは、トロエキニキのためのものですよね?


そのため、コードに表示される独立したオブジェクト数を大まかに計算しました。 上から下まで、このすべてのフットクロスで何が起こっているのかを理解するために、多かれ少なかれ同時に私の頭の中に保持しなければならなかったその数のオブジェクト。 ここに私が得たものがあります:





合計で、少なくともカウントすると、4 + 42 + 24 + 8 = 78個の独立したオブジェクトが得られました。 また、オブジェクトに対して実行される操作についてはまだ検討していません。 ただし、操作は作業メモリの一部を「占有」します。



「マジック」7に対して78個のオブジェクト-1つの機能には多すぎませんか?



もちろん、ここでは、コードが記述されて機能しているため、78個のオブジェクトはまったく問題ではないと断言できます。 これは最長の方法ではありませんか? それで、さらに多くのオブジェクトがあることができますか? さらに、誰もが78すべてを厳密に同時に開催しなければならないと言ったのですか?



長い方法の問題は、理解できないということではありません。 問題は、「キャッシュをウォームアップ」するのに手間がかかるため、理解しにくいことです。 調査対象のコードフラグメントを構成するオブジェクトのセット全体を作業メモリにロードして、そこに長期間保持するのには、時間と労力が必要です。 より多くのオブジェクト-作業メモリをより多く与えますが、それは誰にとっても異なり、同じ開発者にとっては疲労と気分の程度に依存します...



メトリックと短期メモリ



コードの品質を評価するために、 さまざまなメトリックが使用されます。 たとえば、Maurice Halsteadは70年代に数値コードメトリックを研究しました(!)。 コードの品質を測定して評価することは良いことであることは明らかです。 そして間違いなく、コードが複雑になるほど、精神的な努力が必要になります。 しかし、メトリックに関する質問が1つあります。 EvgeniyRyzhkovの言葉では、「メトリクスは主なものを思いつきませんでした-それらをどうするか」。



プログラミングは複雑な知的プロセスです。 そのコースは多くの要因に影響されます。 私の意見では、最も重要な要因は、コードを作成するための主要な作業ツールの特性と制限、つまりプログラマの知能です。 知性の「内部構造」の研究は、認知心理学に従事しています。 彼女のおかげで、知性の可能性は限られていることが確実に知られており、これらの制限の大きさも測定されています。 また、このツールの機能は限られているため、「製品」には特定の特異性があります。 「ウィル」-コードはブレインツールの成果物であるため。 「必須」-コードは原材料のソースでもあるため。



処理中にブレインツールが破損しないように、生のコードは特定の基準を満たす必要があります。


インテリジェンスの特性を研究する科学は認知と呼ばれるため、このインテリジェンスの限界と相関する指標は認知と呼ばれることもあります。 たとえば、 認知重量と呼びます。 そして認知の複雑さはすでに取られています。 ところで、Halsteadはプログラムの科学の始まりで、認知の重みが非常に似ているメトリックについて説明しています。 ハルステッドだけが「認知」の概念に訴えない。 (ちなみに、認知心理学R.ソルソは1979年に最初に出版され、Elements of Software Science M. Halsteadは1977年に出版されました)。



そこで、メトリックに関する質問に答えます。

コード品質の実用的に役立つ指標は、ブレインツールがどのコードで簡単に機能し、どのコードで「壊れる」かを示すように構築する必要があります。 「直感的」ではなく、認知科学から得られたデータに基づいています。


まとめ



解決策を「段階的に」記録することは、3人のプレーヤーが例を解決できるようにするためだけではありません。 ソリューションを読んで検証するのに必要な精神的な労力がほとんどなく、3人でも解決できるようにする必要があります。 優秀な学生も中間ステップなしで解決策を理解しますが、例が複雑で、数千を読む必要がある場合...一般に、あなたは理解しています。



次回は、コードの複雑さを軽減するために使用する手法について説明します。



PS手でリファクタリングできないシャイタンメソッドの1つは、120行の長さです。 認知重量は考慮されることすら望まない。 恥ずかしい。






UPD



kamentyから判断すると、「優秀な学生」と「trochik」という用語に入れた意味をはっきりと表明していませんでした。 この用語のペアは、単なる隠deviceと誇張という文学的デバイスです。 「平均以上の正確な科学の能力を持つ人」と「正確な科学の能力があまり発達していない人」の概念には、いくつかの短い名前が必要でした。 テキストのどこにも、私には思えないが、前者を賞賛し、後者を信用しない。 それどころか、テキストで「結ばれた」アイデアの1つ(新しいものでも、私のものでもない):「優秀な学生」がコーディングプロセスで優れた能力を考えずに使用すると、良い結果は得られません。



私にとっての学年は、重要な何かの指標ではありませんでした。 私自身、数学を除くすべての科目で非常に平均的な成績がありました。 私はいつも、成績は人生の主なものではないという考えで娘を感心させようとしました。 何かが頭の中にあることが重要です:知識、理解、何かへの関心。 しかし、彼女は私に耳を傾けず、金メダルで学校を卒業しました。






UPD2



いいえ、バイソンではなく、考えて理解できる優秀な学生を正確に念頭に置いていました。 学問分野では、私たちの能力により、無関係な中間ステップをスキップして、非常に迅速に正しい決定を下すことができます。 また、実際の技術的な問題では、原則として高速な解決策がプラスの要因です。



プログラミングでは、中間ステップが突然最も重要なものになります。 そして、私たちは美しい300行の機能に対する襲撃について真に当惑し始めています。 しかし、私たちは試してみました、私たちは最善を尽くしました! プログラミングではまったく逆のことが必要だと説明した人はいませんでした。 愚かなコードを書くと、高速でスマートなソリューションは常に有害な結果をもたらします。



彼らは大学でダイクストラの構造プログラミングについてのみ語ったが、私はずっと後に単独責任の原則について学んだ。 驚くべきことは、メソッドの長さについて話し、画面サイズについての誰かのアドバイスに頼って、メソッドが短くなる真の理由を理解していないことです。



All Articles