本 The Pragmatic Programmer では、作家は偶然のプログラミングの概念について言及しています。それはそれが何であるか、なぜそれが引き起こされるのか、あなたが遭遇する危険は何であるかを説明し、戦争の地雷原と比較します。
古い白黒の戦争映画を見たことがありますか?疲れた兵士は用心深くブラシから前進します。先に空き地があります:地雷はありますか、それとも安全ですか?それが地雷原であることを示す兆候はなく、標識、有刺鉄線、クレーターはありません。兵士は爆発を予想して、銃剣とひるみで彼の前に地面を突き刺します。ありません。そのため、彼はしばらくの間、フィールドをじっくりと進んでいきます。結局、フィールドが安全であると確信し、彼はまっすぐにまっすぐになり、誇らしげに前進します。
地雷に対する兵士の最初の調査は何も明らかにしなかったが、これは単に幸運でした。彼は誤った結論に至り、悲惨な結果をもたらしました。
開発者として、私たちは地雷原でも働いています。毎日私たちを捕まえるのを待っている数百の罠があります。兵士の話を思い出して、私たちは誤った結論を出すことに警戒するべきです。偶然のプログラミングは避けてください-運と偶然の成功に頼って-故意にプログラミングすることを優先します...
しかし、私は彼らが「それをどのように克服するか」問題を説明する方法に本当に満足していません。ええ、あなたはコードを書く前に前もって考える必要がありますが、それをどのように実践するのですか?私が考えられる唯一のことは、既存のオープンソースプロジェクトに機能を追加することです。「私は今何をしているか」と「他のコードがどのように機能しているか」についての知識が必要ですが、それは当てはまりませんあなた自身のプロジェクトを書いているとき。
編集:
あなたの投稿の要約:
ところで、答えを受け入れるのは難しいです、それは本当に難しいです。すべての答えは本当に素晴らしいです:)
先を考える必要はありません。何が行われたかを非常に明確にし、現在何をしているかを非常に明確にする必要があります。
サブルーチンは、彼らが何をするか、何を言うかを言うべきであり、隠された依存関係を持っていてはなりません。そうすれば、彼らに電話をかける人は、彼らが何をするかについてより簡単に推論できる。
グローバルな状態を避けます。 (変数、シングルトンなど)何が行われるかを理解するために頭の中にある必要がある状態が多いほど、何が起こるかを理解してEdgeケースを見つけるのが難しくなります。
単体テストを記述します。単体テストは、探している理想的な動作ではなく、記述したばかりのコードの実際の動作をキャプチャするのに最適です。
編集、コンパイル、テストのサイクルを短縮します。大量のコードを追加してテストを不十分にすると、予想よりも動作が異なる可能性があります。次に、ランダムな変更を加えて「修正」すると、今のところ正しい答えが得られますが、実際にどのように起こったかはわかりません。あなたは偶然プログラミングをしています。ただし、5行追加してテストすると、正しく機能すると思うので正しい答えが得られる確率ははるかに高くなります。経験から言うと、個別にテストされた各10行の5つのチャンクは、一度にテストされた50行のコードとはまったく異なるものです。
冷酷にリファクタリングします。多くの場合、コードをいくらか単純にするリファクタリングを見つけましたが、やりたくない多くの作業を行います。私はこれらのリファクタリングを優先的に優先的に取り組み始めた後、通常は1か月以内に報われることがわかりました。ただし、重要な点として、私が焦点を当てているリファクタリングは、日々の生活をよりシンプルにするものであり、より良いまたはより一般的な何らかの恣意的な美学を満たすものではありません。私が学んだこれらのリファクタリングは、はるかに慎重になるように学びました。
これらはどれも事前の計画を必要としません。しかし、それらはすべて、既存のコードを理解しやすくするため、次の小さなチャンクを意図的に実装することが容易になります。
結局のところ推測しないでくださいです。ほとんどの場合、新しいプログラマがそれを行いますが、ベテランも研究時間を節約できると考えているので、ベテランもそれを見ています。何かが機能しないため、+1
または-1
を追加し、true
をfalse
に、またはその逆に変更し、いくつかのステートメントを並べ替え、追加または変更します遅延、スレッドの優先順位の変更、およびその他の小さな変換。基本的に、ランダムな順列が機能するまでテストします。
これは主に既存のコードの変更に適用されますが、真にゼロから始める人がいないため、新しいコードの要素にもなります。常に標準ライブラリ、オペレーティングシステム、または少なくともプロセッサアーキテクチャの上に構築しています。
つまり、修正が機能する理由がわかるまで、作業は完了しません。そこにたどり着くまでの道のりはそれほど重要ではありません。ランダムな順列であっても、「わかりました、trueをfalseに変更して修正しましたが、なぜですか?」と時間をかけて考えると、診断が難しいバグを絞り込むのに役立つことがあります。
私がプログラムで遭遇した中で最も怖いコメントは
これには触れないでください。できます。方法や理由はわかりませんが、うまくいきます。1
そして、それはコードが偶然のプログラミングの結果であると認めているからといって怖いです。
偶然によるプログラミングを回避するには、(同僚、自分自身、または ゴム製のアヒル )を正確に説明できる必要がありますwhatコードが行うことwhy =機能します。故意にプログラミングするための箇条書きは、ほとんどの場合、コードを説明できるというその目標に向かって進むのに役立ちます。
1コンテキストについては、このコメントはプリミティブOSでコンテキストスイッチを処理するコードに表示されました。このコードは、私が遭遇したとき、すでに数年前から製品化されていました。
新しいプログラマーにとって、これを克服するための最も重要な部分は、彼らが何をしているかを本当に理解することです。
多くの分野で、何かを行う方法がわからないときは、試行錯誤するだけです。何かを試してください。うまくいくなら、素晴らしいですが、うまくいかない場合は、別の方法を試してください。
プログラミングでは、特に未定義の動作(CまたはC++など)の概念を持つ言語を使用する場合、成功はブール値の決定ではなくなるため、このアプローチは単に機能しません。 「ある種の」機能、時には機能する機能、一部の入力には機能するが他の機能には機能しない機能を持つことができます。
私は時々新しいプログラマーを指導しました、そして、それがうまくいくかどうか確かめるためにランダムなものをタイプすることを試みる傾向は一般的です。彼らは線を打ち、それから私に振り向いて、「それはこのように働くだろうか?」と尋ねるでしょう。彼らがそうであるかどうか全く手がかりがないことは明らかでした。
要点は、新しいプログラマーとして、あなたは自分のコードが何をするかを説明できる必要があるということです。コードを書くだけでなく、コードを読むことを学ぶ必要があります。
(もちろん、それは熟練したプログラマーにも当てはまりますが、ここでの私の経験は、ほとんどが完全な初心者でした。)
「レーシングライン」でのコーディング、テスト、修正は非常に簡単です。 XとYを指定してZを生成するいくつかの機能があります。しかし、Xが破損していてYが利用できない場合はどうなりますか? Zを出力できない場合はどうなりますか?何が問題になるかを常に念頭に置き、テストサイクルでそれを書き留めます。
ルーチンは短く説明的にしてください。最高のコードには、コメントが(あれば)少ししか必要ありません。
意味のあるメソッド、クラス、変数の名前は、読みやすさを向上させるのに役立ちます。
コードの臭いに遭遇したら、やめてください。そのにおいが消える可能性は低く、少しの努力で、後であなたに多大な悲しみを救うことができます。
開発プロセスにテストを含めます。 [〜#〜] tdd [〜#〜] ではなく、 [〜#〜] bdd [〜#〜] の使用を推奨します。誤った安心感を与える可能性のある多数のテストに盲目的に依存するのではなく、達成しようとしていることを説明します。
クールな機能を追加したいという衝動に抵抗します(自分のペットプロジェクトでない限り)。追加のコードは、設計、記述、テスト、および保守する必要があります。それがクライアント/ビジネスで必要とされない場合-あなたはこれがあなたのリソースの巨大な流出になる危険を冒します。