「既存のコード1の設計を改善するためのリファクタリング」リファクタリングの原則

序文

古典的な神聖な本である既存のコードのデザインをリファクタリングします。2年前に始めて半年前に読みました。それは普通のことです。今日からもう一度読みます。別の収穫があることを願っています。

/**
* @startTime 2020-12-16 23:22
* @endTime 2020-12-16 23:59
* @startPage 1 
* @endPage 55
* @efficiency 56/1 = 56页/天
* @needDays 412/56 = 7天
* @overDay 2020-12-16 + 7天 = 2020-12-22 
*/

第1章リファクタリング、最初のケース

いわゆるリファクタリングとは、コードの外部動作を変更せずにコードを変更して、プログラムの内部構造を改善することです。リファクタリングは、ハードワークによって形成された整然としたプログラム仕上げ方法であり、仕上げプロセスでエラーが発生する可能性を最小限に抑えることができます。基本的に、リファクタリングとは、コードの記述後にコードの設計を改善することです。

愚か者なら誰でもコンピュータが理解できるコードを書くことができ、人間が理解できるコードだけが優れたプログラマーです。

第2章リファクタリングの原則

1.リファクタリングとは

ソフトウェアの内部構造を調整する目的は、ソフトウェアの観察可能な動作を変更することなく、理解しやすさを向上させ、変更のコストを削減することです。

リファクタリングの目的は、ソフトウェアの理解と変更を容易にすることです。

コードによって表される設計意図を確認するのが難しいほど、設計を保護するのが難しくなります。頻繁なリファクタリングは、コードが適切な形式を維持するのに役立ちます。同じことを達成するために、不十分に設計されたプログラムは多くの場合、より多くのコードを必要とします。これは、コードが同じことを行うために異なる場所でまったく同じステートメントを使用するためです。したがって、設計を改善するための重要な方向性は、重複するコードを排除することです。このアクションの重要性は、将来の変更を容易にすることです。コードの量を減らしても、プログラムの実行トラックに明らかな影響がほとんどないため、システムの実行速度は向上しません。ただし、コードの量を減らすことで、将来のプログラムの変更がはるかに簡単になります。

/**
* @startTime 2020-12-17 22:00
* @endTime 2020-12-17 22:50
* @startPage 56 
* @endPage 64
* @efficiency 64/2 = 32页/天
* @needDays 412/32 = 13天
* @overDay 2020-12-16 + 13天 = 2020-12-29 
*/

2.リファクタリングにより、ソフトウェアが理解しやすくなります

レビュー担当者が理解しやすくし、次の人がコードを引き継ぐのを容易にします。たぶん、あなたのコードを引き継ぐ次の人はあなた自身です。場合によっては、コードの一部を自分で作成することもできます。確信が持てませんね。

  • リファクタリングの利点
  • バグを見つけるのに役立つリファクタリング
  • プログラミング速度を向上させるためのリファクタリング

3.再建のタイミング

  • 3つのこと、3つの再構築
  • 機能を追加するときにリファクタリングする
  • エラーを修正するときにリファクタリングする
  • コードを確認するときにリファクタリングする

4.リファクタリングが役立つ理由

  1. 読みにくく、変更が難しいプログラム。
  2. 論理的に繰り返される手順、変更が難しい。
  3. 新しい動作を追加するときは、既存のコードのプログラムを変更する必要がありますが、これは変更が困難です。
  4. 複雑な条件付きロジックを持つプログラムは変更が困難です。

したがって、私たちはプログラムが:

  1. 読みやすい
  2. すべてのロジックは、一意の場所でのみ指定されます。
  3. 新しい変更は、既存の動作を危険にさらすことはありません。
  4. 条件付きロジックをできるだけ単純に表現します。

間接レイヤーとリファクタリング

間接レイヤーの値:

  1. ロジック共有を許可します。
  2. 意図と実現の別々の説明;
  3. 変更を分離します。
  4. 条件付きロジックをカプセル化します。

5.再建の問題

(1)データベース

データ移行

(2)インターフェースを変更する

インターフェイスを早めにリリースしないでください。コード所有権ポリシーを変更して、リファクタリングをスムーズにしてください。

(3)リファクタリングでは完了が難しい設計変更

(4)リファクタリングすべきでない場合 

/**
* @startTime 2020-12-20 11:50
* @endTime 2020-12-20 15:30
* @startPage 65 
* @endPage 102
* @efficiency 102/5 = 20.4页/天
* @needDays 412/20.4 = 20天
* @overDay 2020-12-16 + 20天 =  2020-01-04
*/

6.リファクタリングと設計

多くの人々は、設計をソフトウェア開発の重要な部分と見なし、プログラミングを機械的な低レベルの労働にすぎないと見なしています。彼らは、デザインはエンジニアリング図面を描くようなものであり、コーディングは建設のようなものだと考えています。

システムを十分に理解していても、推測するのではなく、実際にパフォーマンスを測定してください。推測はあなたに何かを学ばせるでしょう、しかしあなたはおそらく間違っています。

7.リファクタリングとパフォーマンス

最初に調整可能なソフトウェアを作成し、次に十分な速度が得られるように調整します。

高速ソフトウェアを作成する3つの方法:

(1)タイムバジェット方式

通常、非常に高いパフォーマンス要件を持つリアルタイムシステムで使用されます。

設計を分解する際には、事前に予算を立て、時間や実行軌道などの特定のリソースを各コンポーネントに割り当てる必要があります。コンポーネント間の時間をスケジュールおよびプロビジョニングするメカニズムがある場合でも、各コンポーネントは独自の予算を超えてはなりません。

この方法はパフォーマンスを非常に重要視しており、心拍数レギュレーターなどのシステムでは最新のデータが間違っているため、この方法が必要です。しかし、一部の管理システムでは、このようなパフォーマンスの追求は少しやりすぎです。

(2)継続的注意方法

この方法では、プログラマーはいつでも何かをするときにシステムの高性能を確保しようとする必要があります。

この方法は非常に一般的に見え、非常に魅力的ですが、通常はあまり役に立ちません。

(3)パフォーマンス最適化段階

プログラムを作成するときは、パフォーマンスにあまり注意を払う必要はありません。コードが開発された後、パフォーマンスの最適化段階があります。この段階に入ると、プログラムのパフォーマンスは特定のプログラムに従って調整されます。

パフォーマンスの最適化段階では、最初に測定ツールを使用してプログラムの動作を監視し、プログラムのどこで多くの時間とスペースが消費されているかを通知する必要があります。このようにして、パフォーマンスのホットスポットが配置されている小さなコードを見つけることができます。次に、これらのホットコードに焦点を当て、継続的注意方法の最適化方法を使用してそれらを最適化する必要があります。すべてのステップをコンパイルし、テストし、再度測定する必要があります。

8.再建の起源はどこにありますか?

第3章コードの悪臭

1.重複するコード

同じクラスの2つの関数に同じ式が含まれている場合は、繰り返されるコードを抽出してから、両方の場所で抽出されたコードを呼び出す必要があります。

2.機能が長すぎる

間接レイヤーによってもたらされるすべての利点、説明、共有、および選択する機能。

関数はもっと積極的に分解する必要があります。何かを説明するためにコメントが必要だと感じるときはいつでも、説明する必要があるものを独立した関数に記述し、(実装ではなく)目的にちなんで名前を付けます。1つを比較することもできます。これを行うには、1行のコードでもグループ化します。置き換えられた関数呼び出しアクションが関数自体よりも長い場合でも、関数名がその目的を説明できる限り、遠慮なくそうする必要があります。重要なのは関数の長さではなく、関数の「何」と「どのように」の間の意味的な距離です。

(1)リファイン機能

(2)一時変数をクエリに置き換えます

(3)パラメータオブジェクトを導入するか、オブジェクトをそのまま保持します

(4)関数を関数オブジェクトに置き換えます

この特別な関数を別のオブジェクトに入れて、ローカル変数がオブジェクトのフィールドになるようにします。そうすると、この大きな関数を同じオブジェクト内の複数の小さな関数に分解できます。

この本は、小さな機能の美しさを強調し続けています。

(5)条件式とループも、多くの場合、洗練された信号です。

分解条件式;

ループとそのコードを独立した関数に抽出します。

3.特大のカテゴリー

1つのクラスで多くのことを実行したい場合は、インスタンス変数が多すぎます。これが発生すると、繰り返されるコードが続きます。

洗練されたクラスを使用して、いくつかの変数を一緒に新しいクラスに抽出できます。

4.パラメータ列が長すぎます

5.発散的な変化

6.ショットの変更

特定の種類の変更が発生し、多くの異なるクラスで小さな変更を加える必要がある場合は、一緒に変更されたコードを新しいクラスに抽出できます。

7.アタッチメントプロット

特定のクラスに対する関数の関心は、現在のクラスにはるかに関心があります。この時点で、関数の位置を転送する必要があります。

8.データマッドグループ

適切な判断方法は次のとおりです。多くのデータの1つを削除すると、他のデータはその意味を失いますか?それらが意味をなさなくなった場合、これは明確なシグナルであり、新しいオブジェクトを生成する必要があります。

フィールドとパラメーターの数を減らすことで、もちろん悪臭を取り除くことができますが、さらに重要なことは、新しいオブジェクトを取得したら、プログラムに香りを放出させる機会があります。新しいオブジェクトを取得したら、添付ファイルのプロットを探し始めることができます。これは、新しいカテゴリに移動できるさまざまなプログラムの動作を指摘するのに役立ちます。それほど時間はかかりません。すべてのクラスが、小さな社会での価値を十分に発揮します。

9.パラノイアの基本的なタイプ

オブジェクトテクノロジーの初心者は通常、お金、電話番号、数値と通貨を組み合わせた郵便番号などの特別な文字列など、小さなタスクで小さなオブジェクトを使用することを望んでいません。簡単に思えます。この場合、オブジェクトを使用してデータ値を置き換えることができます。従来の洞窟から抜け出し、ホットなオブジェクトの世界に入るには、元々単独で存在していたデータ値をオブジェクトに置き換えます。

10.スイッチホラーが登場

オブジェクト指向プログラムの最も明白な特徴の1つは、使用するswitchステートメントが少ないことです。

本質的に、switchステートメントの問題は繰り返しです。同じswitchステートメントがさまざまな場所に散在していることがよくあります。新しいcase句を追加する場合は、すべてのswitchステートメントを見つけて変更する必要があります。オブジェクト指向の多形性は、エレガントなソリューションをもたらすことができます。

11.並列継承システム

クラスがサブクラスを追加することがわかった場合は、別のクラスにもサブクラスを追加する必要があります。ある継承システムのクラス名プレフィックスが別の継承システムの名前プレフィックスとまったく同じであることがわかった場合、この悪臭を放ちます。

この重複を排除するための一般的な戦略は、継承システムのインスタンスが別の継承システムのインスタンスを参照できるようにすることです。転送方法と転送フィールドを使い続けると、参照側の継承システムを非表示にすることができます。

12.冗長性

継承システムを崩壊させます。

クラスをインライン化します。

13.未来について話す

14.紛らわしい一時フィールド

15.マルチディグリー結合メッセージチェーン

16.仲買人

17.あいまいな関係

18、同じクラスに似ています

19.不完全なクラスライブラリ

追加機能の導入、つまり複雑なパラメーターのカプセル化。

ローカル拡張機能を導入します。つまり、クラスライブラリを継承し、必要なメソッドを追加します。

20、ナイーブデータクラス

21.拒否されたギフト

継承を委任に置き換えます。

22、コメントが多すぎる

たくさんのコメントが表示された場合、それはコードが不良であり、コメントを使用して説明する必要があることが原因であることがよくあります。コメントが多すぎる場合は、コードをリファクタリングする必要があることを示しています。

コメントを書く必要があると感じたら、最初にリファクタリングして、すべてのコメントを冗長にするようにしてください。

第4章テストシステムの構築

1.セルフテストコードの価値

実際、テストコードを書くのに最も役立つのは、プログラミングの前です。機能を追加する必要がある場合は、最初に対応するテストコードを記述します。

テストコードを書くことは、実際には、この機能を追加するために何をする必要があるかを自問することです。テストコードを書くことで、実装ではなくインターフェースに集中することもできます。

2.JUnitテストフレームワーク

3.さらにテストを追加します

  • 完全なテストを待つよりも、不完全なテストを作成して実際に実行する方がよいでしょう。
  • うまくいかない可能性のある境界条件を考慮し、そこにテスト火力を集中させます。
  • 問題が発生したと思われる場合は、予期された例外がスローされるかどうかを確認することを忘れないでください。
  • テストは実際にほとんどのバグをキャッチできるため、テストがすべてのバグをキャッチできないという理由だけでテストを作成しないでください。

 

前の投稿:[高品質のコードを書く:Javaプログラムを改善するための151の提案]

次の記事:Java仮想マシンの詳細な理解

おすすめ

転載: blog.csdn.net/guorui_java/article/details/111305499