明快な良心を持ったプログラマーの大部分は、主に常識に導かれて、単純に問題を解決することを好むと言うでしょう。 それは、彼自身の「単純」であり、通常は他のものとは異なるだけです。 同僚との1回の長く非建設的な議論の後、私は自分が単純だと思うこととその理由を述べることにしました。 これは即座の合意には至らなかったが、互いの論理を理解し、不必要な議論を最小限に抑えることを可能にした。
最初の基準
人間の脳の特徴は、うまく保存されず、1〜3の最適な数で1つのリストに7〜9を超える要素を区別するようなものです。
したがって、推奨事項-理想的には、インターフェイスに3つ以下のメンバー、メソッドに3つのパラメーターなどがあり、9を超える数の増加は許可されません。
この基準は、静的分析によって実装できます。
第二の基準
最も重要なことは、クラスの最初の2行です。
- 名前、型パラメーター、実装されたインターフェース。
- コンストラクターオプション。
その結果、残りのコードを見なくても、クラスの使用に必要なすべてのもの(名前、パラメーター、入力、出力)がわかります。
もちろん、これは制限の対象となります:
- 実装の継承を避ける
- コンストラクターオプション以外の依存関係の注入を避けます。
そして、この基準は静的分析によって実装できます。
第三の基準
1つのタイプ-1つのタスク。 インターフェースの契約、クラスの実装、メソッドのアルゴリズム!
マルチツールは、手元に他に何もない場合にのみ有効です。 最初の2つの基準のおかげで、これらのタイプを書くのは簡単です。 はい、これが唯一の責任 (およびヒープへのインターフェイスの分離 )の原則です
そして、ここでは静的分析を人に委ねる必要があります。
第4基準
制約は、メソッドシグネチャと同じ契約の法的部分です。
したがって...
- 契約のコメントはほとんどの場合に役立ちますが、実装コードのコメントはほとんどの場合有害です。
- DTOは完全なオブジェクトであり、その基本的な動作には自動シリアル化が与えられます。
- 不変オブジェクト-検証の利便性、人種の不在、不必要なコピーに報いる。
- 静的メソッドは、完全なステートレスクラスであり、不変オブジェクトからのすべてのバンに加えて、メモリトラフィックが少なくなります。
- 匿名デリゲートとラムダ-一連のインターフェイスクラスを1つのメソッドに置き換えることで、2つの余分な型を捨てて、コードで直接呼び出しの署名を示すことができます。
- 残りの「偽物オブジェクト」を好みに追加します。
ここでの静的分析は、より単純なタイプオプションを使用する場合の推奨事項にのみ役立ちます。
第5基準
再利用のための最大の使いやすさ。
インターフェイスの継承を使用し、実装の継承を回避し、すぐにコードの再利用の3つのソースを取得する
- 既製の実装が機能しない場合でも、コントラクトの再利用は非常に便利です。
- 実装の再利用-契約が受け入れられるところであれば、すでに書かれた実装を使用できます。
- クライアントコードの再利用-インターフェイス(テストを含む)で動作するすべてのコードは、新しい実装ごとに再利用できます。
はい、これはLiskを最も単純で実用的な形式に置き換える原則です 。
静的アナライザーは、不要な実装継承の使用を報告できます。
また、「念のため」に型やメソッドを非表示にしないでください。 実装の詳細として非表示にする必要があるものを除き、すべてを公開する必要があります。
6番目の基準
タイプは、変更よりも構成、装飾、適応、ファサードの構成などの方がシンプルである必要があります。 前の基準に従って、これを達成することは難しくありません。
これにより、現在のコードを書き換えるのではなく、新しいコードを追加することで可能な限り多くの変更を減らすことができます。これにより、リグレッションが減り、古いテストも編集する必要がなくなります。
理想的な例は、一方で機能を追加し、元の契約と実装を変更しないインターフェース拡張メソッドです。
はい、これが開放性と閉鎖性の原則です 。
いいえ、静的分析はここではあまり役に立ちません。
7番目の基準
コンストラクターのパラメーターのタイプは、値の使用方法について可能な限り話す必要があります。
例:
- IService-実装に必要なサービス
- 遅延<IService>-起動時でない可能性があるサービスを使用するには、Valueプロパティを読み取る必要があります。最初の呼び出しで一時停止が可能です。
- タスク<IResource>-非同期的に取得されるリソース
- Func <IArgument、IResource>-パラメーター化されたリソースファクトリー
- 使用可能な<IResource>-特定の時点までに必要なリソース; Disposeメソッドを呼び出すことにより、使用の終了を報告できます。
残念ながら、静的解析はここではあまり役に立ちません。
第8基準
小さい型は大きい型よりも優れています。設計や実装が不十分な小さい型でも、大きい型に比べて修正、書き換え、削除がはるかに簡単だからです。
タイプはリストではなくグラフであるため、多数の小さなタイプはそれ自体致命的な問題ではありません。 現在のタイプの接続を同時に覚えておけば十分であり、その数は最初の基準によって制限されます。
9番目の基準
相互の型依存性は制限する必要があります
- 型グラフのループは避ける必要があります
- また、互いに直接参照する実装を避ける必要があります。
- タイプをレイヤーに分割するパターンを使用することを強くお勧めします。これにより、互いに異なるレイヤーのタイプ間の依存関係に制限が追加されます。
目標は、型の依存関係のグラフをできるだけ単純化することです。 これは、コードをナビゲートするときと、特定の変更の影響を判断するときに役立ちます。
はい、この基準には依存関係の反転の原則が含まれています 。
はい、静的分析がここで役立ちます。
第10基準
9番目の基準と同じですが、アセンブリ用です。 特に、すぐに念頭に置いて設計する場合は、寿命が大幅に簡素化され、アセンブリが高速化されます。 コントラクトを持つアセンブリの場合、後方互換性を維持するのが簡単です(公開されたコントラクトは変更されません)。 実装されたアセンブリは完全に置き換えることができます-それらはまだ互いに直接依存していません。
静的解析により、あるアセンブリが他のアセンブリを参照することを禁止できます。
11番目の基準
最適化が必要な場合、以前のすべての基準に違反する可能性があります。 しかし、私の意見では、1つのことが常に機能します。
最適化されたコードを調整するよりも、正しいコードを最適化する方が簡単です。
まとめ
自分のアイデアを書くことは、私にとって多くのことを明確にしました。
コメントであなたの単純さの基準を見たいです。
静的解析とは、実装の可能性を意味しますが、現時点では存在しません。
補足と批判は伝統的に歓迎されています。