良いコードの練習

画像 ハブでの長年にわたる存在の中で、理想的なコードがどのように見えるべきかというトピックに関する多くの記事を読みました。 そして、この理想を具体的に達成する方法に関する小さな記事。 また、これらすべての資料の非常に重要な部分は西洋の情報源の翻訳であり、これはおそらく、より成熟したIT業界が「海外」にあり、その後に続くすべての問題を抱えているためです。



残念ながら、多くの場合、作成者は、詳細な説明に進むことなく、プロジェクトの1%にせいぜい必要な多層アーキテクチャの到達不可能な高さに登るか、「コードを明確にする」または「OOPとパターンを使用する」などの一般的なフレーズに制限されています。たとえば、コードの「わかりやすさ」が測定されます。



この記事では、コードの品質を評価するための基準、およびサイズと特異性、使用するプログラミング言語、およびその他の要因にほとんど関係なく、実際のプロジェクトに適用することができる記述方法を体系化することを試みます。



1.シンプルさ


私たちの前ですべてがすでに発明されています-素晴らしいKISSの原則と、アルバートアインシュタインの格言「すべてはできるだけシンプルに、しかし簡単ではない」と言われています。



単純なコードはあらゆる点で複雑なものよりも優れています-理解しやすく、修正とテストが簡単で、コメントとドキュメントが少なくて済み、エラーが少なくなります(統計的にのみ、言語の数とコードの論理構造の数に関してエラーの平均数をとると、特定のプログラマーごとに一定の値)。



また、理想的なシステムでのTRIZの立場を言い換えると、理想的なコードは存在しないものであり、解決しなければならないタスクは正常に解決されたと言えます。 明らかに、この理想は(他のような)実際には達成不可能ですが、開発者の心を正しい方向に向けることができます。



実際には、これらの美しいフレーズはすべて1つのことを意味します。コードを複雑化し難読化することによる損害を超えない実際の (仮説ではない)ツールを使用しないでください。 解決に役立つ1つの狭いタスクのために、フレームワーク全体にアプリケーションを構築しないでください。 単純なクラスでできる複雑なパターンは使用しないでください。 コード内のネイティブオブジェクトのプロパティでも機能しないペアの関数にクラスを使用しないでください(使用しない場合)。 アプリケーションの他の場所で再利用されていない関数で3行のコードをラップしないでください(150年後ではなく、近い将来使用されません)。



もちろん、これはすべて、5000行の命令型スタイルでスパゲッティコードを記述する必要があるという意味ではありません。 そのような欲求が生じたらすぐに、コードを「 できるだけ単純だが単純ではない」という、上記の引用の2番目の部分を読み直して理解する必要があります。



問題を解決できるのであれば、単純な設計を恐れる必要はありません。 また、プロジェクトを開発したり、顧客の要望を1、2年で変えたりするときに、コードが理論的にどのように使用されるかについての考えを隠さないでください。 シンプルかつ迅速な開発の支持者の多くが主張するように、コードが「とにかく破棄され、ゼロから書き直される」ことすらありません。 おそらくそうではないでしょう。 しかし、問題は、高い確率では、単純に正しい方向を推測できないことです。 (ファイルを少し修正した後)ねじをねじることができるようにハンマーを設計しますが、スイング時に釘とレーザーガイダンスの自動送りを締める必要があることがわかります。 そして、特定の方向の開発のために設計されたアーキテクチャは、「単なるハンマー」と比較して失われるだけです。 私を信じて、私は私が話していることを知っています、なぜなら 5年間、私はRunetでプロジェクトをサポートしてきました。このプロジェクトは、最大の労力が費やされた場所や作成されたものではなく、「サイド」機能の小さなブランチが原因で大きく成長しました。



2.概念


この基準は、コードの「単純さ」と大部分が交差していますが、それでも別のセクションに入れることにしました。 このアプローチの本質は、概念の使用であり、理想的には、他のソリューションですでに広く使用されている一般に受け入れられている概念です。



私が意味することを簡単なアナロジーで説明させてください。

あなたがタスクを持っていると想像してください-2から9までのすべての数を互いに乗算した結果を記憶すること。 2x2 = 4、2x3 = 6、...、3x7 = 21、...などの行を入力して、このテキストを暗記し始めることができます。

正式には、これは使用でき、学習することもできます。 しかし、はるかに実用的なオプションがあります-「テーブル」の概念を使用する-つまり XとYの値のリストを定義するデータ構造。あらかじめ定義された式(この場合はZ = X * Y)を使用して、交差点とこれらの点の値をすばやく決定できます。 その結果、子供の頃から全員に知られている乗算表が得られます。これは、テキストの文字数の平凡な経済に加えて、他のいくつかの利点があります。



この方法でテーブルを「機能させる」ために追加の努力をする必要はなく、また「テーブルを使用するための指示」をドキュメントに添付する必要もないことに注意してください。これはプログラミングで概念を使用する主な強みです。 概念を適切に使用するソリューションは、しばしばエレガントと呼ばれます。



すばらしい概念の例は、 UNIXシステムの「リダイレクト」です 。これにより、ファイルや他のストリームの読み取り/書き込み、またはテキストフィルターなどの他のプログラムとのやり取りに1行のコードを費やすことなく、さまざまなプログラムを作成できますgrep。 必要なのは、標準のテキスト入力/出力インターフェイスを提供することだけです。

したがって、最も人気のある数十のチームでさえ、その使用のために数千のオプションを生成します。 何かを思い出させますか? そうです-これは、「存在しないコード」を使用した問題の解決策です。



より簡単な実用的な例-ある広告サイトサイトの2つの異なるアカウントからサードパーティの広告ネットワークの広告をローテーションする必要がありましたが、それらの間の利益分配はほぼ等しい(許容偏差1〜2%)という条件で。 「額」に適用できる面倒な解決策は、データベースの各アカウントの広告インプレッションを、これらのインプレッションのコスト(異なる場合もあります)を考慮して記録し、ページを開くたびにこれらのデータに基づいて不均衡を最小限に抑えるために表示する広告の決定。



少し後に、多数法則によると、アカウントを選択する際の「ヘッドテール」の原則に関する通常の確率チェックが、与えられた条件内で問題を完全に解決することが判明しました。 また、この方法では、3つ以上のアカウント間でインプレッションを分配するのに問題はありません。 もちろん、これは人によって発明された概念ではなく、基本的な数学的原理ですが、コードの観点から、重要なことはただ1つです。それは機能します。



3.機能の一意性(繰り返さないでください)


「自分自身を繰り返さない」という原則(DRYと略記)は、システムの各機能単位が、コードの論理ブロック、関数、またはクラス全体であるかどうかに関係なく、コードで1回だけ表現する必要があることを示しています。



重複したコードブロックは通常、関数でレンダリングされます。 関数は、プラグ可能なライブラリと名前空間を使用します。 クラスに関しては、些細な継承から、多くの場合より多くのコードと精神的な努力を必要とする「工場を製造する工場」から「工場を生産する工場」までの洗練されたシステムまでプログラマー、保存より。



繰り返しを避けるような方法でコードを設計するという当初からの欲求は、明らかに破壊的です。 80%の状況では、コードを記述するまでコードの重複について知ることができません。



すべてのプロジェクトで実際に使用するための本当のアドバイスは、コードの重複の問題を検出した直後に解決することです(ただし、それ以前ではありません!)。



5〜10行の非常によく似たコードブロックがいくつかあり、いくつかの条件と変数のみが異なりますが、それらを関数でラップする最善の方法はまだわかりません。 ループを使用します。



新しいメソッドのコードを配置するクラス/オブジェクトがわからない? 開発中のシステムに関するより完全な情報が得られるまで、関数を作成してプラグインライブラリに配置するだけです。



クラス継承を使用しますが、1つの論理構造を変更するために、継承者で50行のメソッドを完全に再定義する必要がありますか? まず、大規模なメソッドをいくつかの分離されたメソッドに分割すること、または他のクラスのインスタンスをすべてのメソッドとともに元のオブジェクトのプロパティ値として使用することを検討してください。



シンプルで実績のあるソリューションは、コードの重複に関するすべての問題の95%を解決します。残りの5%については、コードの「悪い」セクションの意味のある再設計と比較して、教科書の複雑な構造を機械的に適用する可能性について10回考える必要があります読みやすさの向上)。



単純なソリューションをいつでも上位レベルのソリューションに置き換えることができます。また、システム全体に重複が既に散在している場合、後の段階で複雑なリファクタリングを生コードに適用するよりもはるかに簡単です。



4.読みやすさ




もちろん、コード自体の優れた設計は、プログラムの品質とその認識の容易さを保証しません。 しかし、まさにそのような細部へのこだわりが、真のプロと「多分それが合う」スタイルで働くシンプルな職人を区別しています。



結論として何を言えますか


この記事は計画よりもややボリュームがありましたが、 接続性や接続性デザインパターン 、本全体がすでに書かれている他の概念など、多くの側面については慎重に議論することを避けましたが、多くの新しいものを書くことができます。



私の目標は、「正しい」(私の観点から)プログラミングの非常に基本的なことを詳細に述べることでした。その多くは、Captain Evidenceのペンにふさわしく、それにもかかわらず、特にWebセグメントでは、ほとんどの開発者によって定期的に無視されています。 完璧主義のジャングルに深く入り込むことなく、これらの簡単な基本のみに準拠することで、あらゆる方法でコードを改善することができます。



私が何かを見逃したか、どこかで間違えられた場合-コメントの建設的な批判が強く推奨されます。



All Articles