700 行のクラスをコーディングしました。最悪。恥ずかしそうに頭を下げる。英国の夏と同じようにDRYとは正反対です。
所々に微調整を加えたカットアンドペーストでいっぱいです。これにより、リファクタリングの最有力候補になります。これに着手する前に、繰り返しが多い場合に尋ねたいと思っていたのですが、最初にリファクタリングの機会を探すのは何ですか?
記録のために、私はおそらく使用しています:
- ジェネリック クラスとメソッド
- メソッドのオーバーロード/連鎖。
あなたのものは何ですか?
700 行のクラスをコーディングしました。最悪。恥ずかしそうに頭を下げる。英国の夏と同じようにDRYとは正反対です。
所々に微調整を加えたカットアンドペーストでいっぱいです。これにより、リファクタリングの最有力候補になります。これに着手する前に、繰り返しが多い場合に尋ねたいと思っていたのですが、最初にリファクタリングの機会を探すのは何ですか?
記録のために、私はおそらく使用しています:
あなたのものは何ですか?
最初の機会ではなく、必要なときにリファクタリングを開始するのが好きです。これは、リファクタリングに対するアジャイル アプローチのようなものだと言うかもしれません。必要だと感じるのはいつですか?通常、コードの醜い部分が広がり始めていると感じたときです。醜さは封じ込めていれば良いと思いますが、蔓延したいという衝動に駆られた瞬間から対策が必要です。
リファクタリングに使用する手法は、最も単純なものから始める必要があります。Martin Fowler の本を強くお勧めします。一般的なコードを関数に結合したり、不要な変数を削除したり、その他の単純な手法を使用すると、多くのマイレージが得られます。リスト操作については、関数型プログラミングのイディオムを使用することを好みます。つまり、私はできる限り内部イテレータ、map、filter、reduce (python で言えば、ruby、lisp、haskell に対応するものがあります) を使用します。これにより、コードがはるかに短くなり、自己完結型になります。
場合によっては、コピー アンド ペースト コードを使用して「機能を完成させる」までに、リファクタリングを試みると実際には、元の時点でリファクタリングするよりもはるかに長い時間がかかるほど、十分に機能が損なわれ、破損している場合があります。明らか。
私の個人的な経験では、私のお気に入りの「繰り返しを削除する方法」は、Resharper の「メソッドの抽出」機能です (ただし、これは通常の Visual Studio でも利用できます)。
メソッド全体としてではなく、完全に個別のメソッド内のチャンクで繰り返しコード (私が保守している一部のレガシー アプリ) を何度も目にします。これにより、これらのチャンクをメソッドに変換する絶好の機会が得られます。
また、モンスター クラスは、複数の機能が含まれていることを明らかにする傾向があります。これは、それぞれの異なる機能を独自の (できれば小さい) クラスに分離する機会になります。
繰り返しますが、これらすべてを行うことは(私にとって)まったく楽しい経験ではないため、大きな泥のボールを転がしてから試してみるよりも、小さな泥のボールである間に正しく実行したいと思います。それを修正します。
#領域
1,000回線クラスを1回線だけにしました!
真剣に、繰り返しを避ける最善の方法は、リストに記載されていることだけでなく、ポリモーフィズムを十分に活用し、クラスを調べて、基本クラスで行うのが最善であること、およびそのさまざまなコンポーネントをどのように分離できるかを発見することです。サブクラス。
「あちこちで微調整を加えてカットアンドペーストする」というのは、私が通常完全に非エキゾチックなアプローチで解決する種類のコードの繰り返しです。同様のコードのチャンクを取り出して、別のメソッドに抽出します。そのコードブロックのすべてのインスタンスで異なる少しは、それをパラメータに変更します。
繰り返しに見えるif/else ifおよびswitchブロックを削除するための簡単なテクニックもいくつかあります。ScottHanselmanの厚意によります: http ://www.hanselman.com/blog/CategoryView.aspx?category = Source + Code&page = 2
私はこのように行くかもしれません:
データ構造のカスタム (プライベート) タイプを作成し、関連するすべてのロジックをそこに配置します。Dictionary<string、List<int>> など。
動作を保証する内部関数またはプロパティを作成します。パブリックにアクセス可能なプロパティから条件を継続的にチェックしている場合は、すべてのチェックが組み込まれたプライベート getter メソッドを作成します。
処理が多すぎるメソッドを分割します。に簡潔なものを入れたり、適切な名前を付けたりできない場合は、コードが完成するまで関数を分割し始めます (これらの「子」関数が他の場所で使用されていなくても)。
他のすべてが失敗した場合は、[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] を平手打ちし、理由をコメントしてください。
まず第一に、クラスの最初のバージョンを使い終わったときよりもずっと早くリファクタリングすることをお勧めします。重複を見つけたら、すぐに削除してください。これには最初は少し時間がかかるかもしれませんが、最終的にはよりクリーンな結果になると思います。コードを再考して、正しいことを確実に行うのに役立ちます。
重複を取り除く私のお気に入りの方法については....クロージャー、特に私のお気に入りの言語(Ruby)で。それらは、2 つのコードを取り、類似点をマージする非常に簡潔な方法である傾向があります。もちろん (他の「ベスト プラクティス」やヒントと同様)、これはやみくもに行うことはできません。
私が行っていることの 1 つは、エディター (ビジュアル スタジオ) の 1 ページで確認できる小さくて単純なメソッドを作成することです。
コードをシンプルにすると、コンパイラーがコードを最適化しやすくなるということを経験から学びました。メソッドが大きくなればなるほど、コンパイラの作業が難しくなります!
また、最近、大規模なメソッドがメモリ リークを引き起こすという問題も見ました。基本的に、次のようなループがありました。
while (真) { var smallObject = WaitForSomethingToTurnUp(); var largeObject = DoSomethingWithSmallObject(); }
smallObject が何かを返すまで 'largeObject' がスコープ内になかったとしても、ガベージ コレクターはまだそれを見ることができるため、アプリケーションが大量のデータをメモリに保持していることがわかりました。
「DoSomethingWithSmallObject()」およびその他の関連コードを別のメソッドに移動することで、これを簡単に解決しました。
また、小さなメソッドを作成すると、クラス内での再利用が大幅に向上します。私は通常、自分のメソッドが他のメソッドと同じように見えないようにしています!
お役に立てれば。
ニック