プログラミング:1つの病気の歴史

この記事にはおそらく新しい考えや新鮮な考えはありません。また、このようなことを複数回読んだことは間違いありません。 この記事は真実であると主張していません。 その内容は、独自の経験、試行錯誤の結果であり、同時に同僚から学び、Habréや他の場所で読むことができるという知識を絞り出した結果です。 おそらく、特定の個人ごとに、このテキストで述べられていることは現実とは非常に異なるでしょうが、多くの人が自分自身の説明で見つけることができると確信しています。 最初の段階は、おそらく学生や生徒だったときにオリンピアードプログラミングに関与していなかったプログラマーの特徴ではありませんが、次の段階はこの要因からほとんど完全に独立しています。



ステージ1。 誕生



「私はプログラマです。 私はオリンピアードです。 私は少し「ああ」が何であるか知っています。 「O」が大きいことは知っています。 「en-square」と「en-factorial」がどのように異なり、「en-logarithm-en」の形でどちらも恥ずかしげに隠れているのかを理解しています。 今度はプロジェクトに来て、このブレーキの混乱をコードから書き直して、何倍も速く動作するようにします! 見て、私はKnut-Morris-Prattアルゴリズムを知っています! そして、ここで平等のために行の比較を1つ保存できます! そして、この再帰をループで展開すると、メソッド呼び出しを保存し、スタックにメモリを割り当てることによって...何が、プログラムが遅くなりますか? ここでコードを見てみましょう...ここに! ここで、2つのネストされたループの代わりに、1つを記述して、内部ループの代わりにバイナリ検索を使用できます。



これが最初の段階です。 以下とは対照的に、それは特にオリンピックの特徴です。 患者は高速コードの書き方を考えています。 彼は速いコードに夢中です。 残念なことに、高速コードが利用できると、ソフトウェア製品全体が常に高速になるとは限りません。



患者は、Webサーバーの起動時に1回実行されるコードを最適な方法でコピーしましたが、これは全体的なパフォーマンスに影響しませんでした。 患者はコードの一部をコピーしましたが、プロジェクトの要件の変更により10回変更されたため、その最適化によってとらえどころのないバグが発生しました。 そのアルゴリズムは線形時間で実行され、古いアルゴリズムは2次時間で実行されましたが、古いアルゴリズムはデータベースに対して1つのクエリを実行し、新しいアルゴリズムは各反復で実行します。 患者は、多くのユーザーが同時にWebプロジェクトで作業しており、静的データの使用が膨大であることを認識していません...長期間継続できます。

患者の主な問題は、彼がいくつかのクラスまたは方法で考えていると同時に、プロジェクトのこの部分の周りで何が起こっているかを十分に理解していないことです。 彼の考えは、彼の仕事のコードとアルゴリズム、つまりプログラムの動作ではなくプログラムの動作によって制限されます。 ただし、この段階は、患者が自分や他の人に危害を加えるほど長く続くことはめったにありません。 かなり早く、彼がしていることの何か、彼がしていないこと、そして彼が学び始めることを理解する。



ステージ2。 理想主義と自信



「私は開発者です。 はい、そうです、私はソフトウェア開発者であり、プログラマーではありません。 私の仕事は、安定して動作し、正しいコードで構成される製品を開発することです。 私が書いたコードは、最初に正しく動作し、その後すばやく動作するはずです。 コードは構造化し、コメントアウトする必要があります-他の開発者がサポートする可能性があります。 OOPは私のメインツールです。サブジェクトエリアを分析し、その中のクラス階層を強調表示できます。 テンプレートまたはジェネリックによって記述できるすべてのものは、テンプレートまたはジェネリックによって記述されます。 このツールはコードを可能な限り読みやすく理解しやすいものにするため、可能な限り宣言型プログラミングを使用します。 コードを書く時間を節約できるので、コード生成を使用します。 私は新しいテクノロジーのみを使用しています。 どのパターンまたはテクノロジーがタスクを解決するのに最も適しているか、このアプローチまたはそのアプローチを使用するのが正しいかどうかについて、同僚との論争に多くの時間を費やしています...」



そして、これは2番目です。 患者は成熟し、前の段階で多くの隆起を埋めました。 早すぎる最適化がすべての不幸の根源であるというクヌースの主張は記憶され、患者の体に熱い鉄で焼き付けられます。 世界の何よりも、彼はスピードではなくコードの美しさを気にかけています。

クラス階層の巨大なツリーは、密林でプロジェクトをカバーします;特別な属性、ジェネリック、およびインターフェースは、緑豊かな冠から垂れ下がっています。 この森の厚い部分では、モノリシックな岩、コールバック関数、オブザーバー、イテレーター、訪問者、コントローラー、および4部族のギャングの代表者がオブジェクトの工場を立ち上げます。 フォレスト内のどこかで、ユーザーインターフェイスを生成するXSLTテンプレートを生成するコードを生成するコードを生成するコードが生成されます。 すべてのコードには、正しく使用する方法とその機能に関するコメントが豊富に含まれています。 患者は、 非自明なオブジェクト指向の構造のために、数日よりも早く理解できないプロジェクトに喜んでいます。

要件の変更には、大規模なリファクタリング、別の抽象レベルの導入、新しいエンティティの割り当て、Habréで読んだばかりの新しいテクノロジーとアプローチの使用が伴うことがよくあります。 防衛的プログラミングに関する記事を読んだ後、彼はすべてのメソッドにアサーションを押し出し始めました。 メモリ内のデータのキャッシュに精通した後、彼はプロジェクト内のすべてのデータをキャッシュします。 TDDに精通した彼は、ロジック自体を書く前に、基本ロジックのテストを書いています。 彼の労働の成果は記念碑的であり、同じ段階にいる同僚を喜ばせます。 彼は、自分が書いた言語は完璧であり、技術は最も近代的であると心から信じています。 多くの場合、患者はブログを開始します。このブログでは、コードを正しく記述する方法や特定のフレームワークを使用する方法について書いたり、自分のコードで見つかったバグや、彼のように機知に富んだ、それらを排除して防止する方法について説明しています。 彼はお気に入りのテクノロジーの福音主義的なブログを購読し、彼らの言葉を究極の真実として聞いています。

彼は、彼の頭脳が減速しているという事実に直面したとき、彼はプロファイラーを取り上げ、高さ1000階のコールツリーで彼の助けを借りてそれを見つけようとします。 時々それは成功し、問題は解決されます...はい、追加のキャッシュを備えた別の抽象レイヤーを導入することによって。 またはその逆に、ロジックの一部はストアドプロシージャの形式でデータベースサーバーに転送されます。

プロジェクトの締め切りが近づくと、患者は突然 、あまりにも多くの準備ができていないことに気付き、その時間は絶え間ないリファクタリングと選択するパターンについての議論に費やされました。 彼は時間通りに仕事で寝て、時々成功します。 ただし、配信後、プロジェクトをサポートする必要があり、次のバージョンの新しい機能を追加し、新しいユーザーの要件を満たします。ここでも、 突然 、新しい機能を地面に破壊せずにプロジェクトのモノリスに収めることはほとんど不可能であることがわかりました。 製品はすでに生産に取り組んでおり、先週金曜日にこのバグを修正する必要があったため、完全な破壊のための時間を割り当てないため、コードは松葉杖、小道具、「todo:これを後で修正する」というコメントで迅速に修正されます。 そして、建造物が記念碑的であるほど、そのための支持体と松葉杖は記念碑的です。

患者の問題は、フォームの背後にあるコンテンツを失ったことです。 彼はアーティストが絵を描くときにコードを書きます:熱意と賞賛で、彼はこのコードに恋をしており、彼の仕事の主な目標は美しいコードを書くことではないことを忘れがちですが、機能する製品はすぐに機能し、簡単になりますサポートされています。 彼は、ソフトウェア製品が顧客を見つけなければならない製品であることを忘れがちです。顧客は、プログラムコード内の行ごとのパターンの集中度を気にしません。 しかし、このユーザーは製品に新しい機能を追加するためにお金を払う用意ができています。これは最初のバージョンを書くときに誰も知らなかったので、この機能を追加することはプロジェクトの単一の既存の機能から外れてはならず、このプロセスは最小限で済みます はい、これらのボタンの角が丸いことはユーザーにとって非常に重要です。



ステージ3。 啓発



「私は間違っていると思う。 いいえ、間違いなく、私は間違っています。」



はい、第3段階は、患者が病気の第2段階にいることを認識し、自分の欠点と間違いを理解することです。 病気の認識は、治癒につながります。

プロジェクトのクラス階層が2〜3レベルの継承を超えることはめったになく、メソッドには数十行、多くの場合10行未満が含まれます。 コードには、コードにアクセスできないサードパーティの開発者が使用できる外部インターフェイスを除き、コメントはほとんど含まれていません。 驚くべきことに、コメントがないからといってコードが読めなくなるわけではありません。変数とメソッドの正しい名前、明確なコード規約、そして少量のコードは驚くべきことです。 複雑な設計パターンを使用せずにアクションを簡単に説明できる場合は、この方法で説明します。 より複雑なソリューションが将来の生活を簡素化する可能性が高い場合、この単純化を提供するのに十分なだけ実装されます。

宣言型プログラミングは、パフォーマンスを損なわない場所で使用されます。 コードは生成されますが、開発者の時間を節約する場合にのみ、生成の結果は可能な限り単純でデバッグされます。このために10倍のコードを生成する必要がある場合でも。 単体テストはコードの一部のみを対象としますが、これはまさに、新しい機能を導入したりバグを修正したりするときにエラーが発生した場合に影響を受ける可能性がある部分です。 データベースからのデータのキャッシングを追加する前に、患者は、データベースサーバー上のストアドプロシージャのコードにロジックを転送する場合と同様に、それがどれだけ必要か、ソリューションのスケーラビリティが影響を受けるかどうかを明確に考えます。 彼は、別のサーバーを購入することは、プロジェクトの一部を書き直してテストするよりも最終的にはるかに安くなることを理解しています。 ただし、最適化によってパフォーマンスが大幅に向上する可能性のある場所では、当面は行われませんが、必要に応じて簡単に加速できるようにコードが記述されます。 もちろん、これが必要になります。

テクノロジーと言語に対する子犬の熱意は、よりリラックスした態度に変わります-すべてに時間と場所があります。 患者は、各ツールが特定の範囲のタスクに適していることを理解しているため、「動的言語vs. 静的「、」Java対 .Net vs. C ++ "など。 彼は自分のプロジェクトに新しい言語と技術を試して喜んでいますが、長所と短所を慎重に検討し、プロトタイプまたはプロジェクトの別のブランチでイノベーションをテストした後にのみ、作業コードでそれらを使用することにしました。 彼は、新しいことすべてに批判的であり、賛否両論を強調し、論争のすべての側面がある場合はそれを注意深く耳を傾けようとします。 彼はいくつかの言語と技術を熟知しており、自分に割り当てられたタスクを解決するのに十分ですが、必要な量を習得するには不十分です。 伝道者と教祖のことわざは、彼らによって究極の真実として認識されていない-彼は彼らが言ったことをあまり理解していないが、なぜそれが理にかなっているのかを理解しようとしている 。 患者が特定の場合に自分の自転車が既存の技術よりも効果的であると理解した場合、患者は自分の自転車を書くが、それは彼が自分の必要性を証明したときだけである。 自転車が美学と機知に富んだ決定で彼を喜ばせ、雇用主との合意に矛盾しない場合、彼はオープンソースライセンスの下でコードを公開することをorしないか、少なくとも彼のブログで解決策を概説します。 そして、はい、これらのばかがボタンの丸い角を本当に見たいなら、患者は間違いなくそれらを作ります。 しかし、それは患者ですか?



あとがきの代わりに



私自身は患者に会ったことがありません。それは、友人、同僚、自分の経験、そして原作者や起源のない単なる物語からコピーされた、宇宙の真空に深く住んでいるプレハブの球形の画像であり、時々ウェブ上のさまざまなリソースに現れます。



ありがとう



All Articles