web-dev-qa-db-ja.com

リファクタリングとは何ですか?コードを変更するだけですか?

リファクタリングとは、「機能が変更されないようにプログラムの構造を変更する」ことです。私は大学での最終年度のプロジェクトで一緒に仕事をしている何人かの人たちと話していましたが、彼らがリファクタリングのより多くの拡張(より良いWordが欲しいという)見方を持っていることに驚きました。

リファクタリングは、メソッドの抽出やクラスの名前変更などと考えています。また、データ構造の変更(Java LinkedListからArrayListへ)など)、アルゴリズムの変更(バブルソートの代わりにマージソートを使用)、および大量のコードをリファクタリングとして書き直すこともできます。

私は彼らが間違っていると確信していましたが、彼らが示唆していることは行動を変えずにプログラムを変えた(そしておそらくそれを改善する)ので、私はその理由を正当に述べることができませんでした。私は正しい、そしてもっと重要なのはなぜですか?

73
David Johnstone

Martin Fowler's "Refactoring:Improving the Design of Existing Code" はおそらく参照です:

リファクタリングは、既存のコードベースの設計を改善するための制御された手法です。その本質は、一連の小さな動作を維持する変換を適用することで、それぞれが「実行するには小さすぎます」。ただし、これらの各変換の累積効果は非常に重要です。それらを小さなステップで実行することにより、エラーが発生するリスクを減らします。また、再構築の実行中にシステムが破損することを回避できます。これにより、長期間にわたってシステムを徐々にリファクタリングできます。

リファクタリングは単体テストと密接に関連しています。リファクタリングする前にテストを作成すると、リファクタリングの信頼レベルが得られます(テストのカバレッジに比例)。

適切なリファレンスは次のとおりです。 リファクタリングに関する情報

68
Mitch Wheat

ファウラーは、その動作に影響するコードとそうでないコードの変更の間に明確な線を引きます。彼はそうでないものを「リファクタリング」と呼んでいます。このisは重要な違いです。作業をリファクタリングと非リファクタリングのコード変更アクティビティに分けると(ファウラーは「異なる帽子をかぶる」と呼びます)、さまざまな目標に適した手法を適用できるためです。

リファクタリングまたは動作を維持するコード変更を行っている場合:

  • すべての単体テストは、変更の前後に合格する必要があります
  • テストを変更したり、新しいテストを作成したりする必要はありません。
  • 完了したら、よりクリーンなコードを期待します
  • 私たちは新しい行動を期待していません

動作を変更するコードの変更を行っている場合:

  • 私たちは新しい行動を期待しています
  • 新しいテストを書くべきです
  • 完了すると、よりダーティーなコードを取得する可能性があります(その後、リファクタリングする必要があります)

この区別を見失った場合、特定のコード変更タスクへの期待は混乱して複雑になります。または、いずれにせよ、それを意識した場合よりも混乱して複雑になります。だからこそ、言葉とその意味が重要です。

32
Carl Manaster

私の意見を述べるには:

小規模で、コードが検出された状態よりも良い状態に残る増分変更

間違いなくはい:機能に直接関係のない「化粧品」の変更(つまり、変更要求として請求することはできません)。

完全にいいえ:大きなチャンクを書き換えると、明らかに「小さな増分」部分に違反します。リファクタリングは、多くの場合、リライトのoppositeとして使用されます。再度行う代わりに、既存のものを改善します。

間違いなくたぶん:データ構造とアルゴリズムの置き換えは、やや境界のケースです。ここでの決定的な違いは、小さなステップです:提供する準備ができていること、別のケースに取り組む準備ができていることです。


例:レポートランダマイザーモジュールがベクターの使用により遅くなると想像してください。ベクトル挿入がボトルネックであることをプロファイルしましたが、残念なことに、モジュールは多くの場所で連続したメモリに依存しているため、リストを使用するときは静かに壊れます。

書き換えとは、古いものからいくつかのピースを選択するだけで、モジュールをより良く、より高速な建物をゼロから捨てることを意味します。または、新しいコアを作成し、それを既存のダイアログに合わせます。

リファクタリングとは、ポインター算術演算を削除するために小さなステップを実行することを意味するため、切り替えが行われます。ポインター演算をラップするユーティリティ関数を作成し、直接ポインター操作をその関数の呼び出しに置き換えてから、ポインター演算がまだ使用されている場所についてコンパイラーが文句を言うようにイテレーターに切り替えます thenlistに切り替えて、多機能性関数を削除します。


背後にある考え方は、コード自体が悪化するということです。バグを修正して機能を追加すると、品質は少しずつ低下します-変数の意味は微妙に変化し、関数は分離を壊す追加のパラメーターを取得し、ループは少し複雑になります。これらはどれも本当のバグではありません。ループを複雑にする行数を教えてはいけませんが、読みやすさと保守性が損なわれます。

同様に、変数名の変更や関数の抽出は、それ自体の具体的な改善ではありません。しかし、全体として、彼らは遅い侵食と戦っています。

毎日のように地面に落ちる小石の壁のように。そして、毎日、一人の通行人がそれを拾い上げ、元に戻します。

18
peterchen

マーティン・ファウラーの定義を念頭に置いて、

リファクタリングは、既存のコード本体を再構築し、外部の動作を変更せずに内部構造を変更するための統制された手法です。

...あなたは明らかに正しいと思います。

また、データ構造の変更(Java LinkedListからArrayList)など)、アルゴリズムの変更(バブルソートの代わりにマージソートを使用)、リファクタリングとしてコードの大部分を書き換えることなども提案しました。

外部の動作が変更されるため、アルゴリズムをより高速なものに変更することは明らかにリファクタリングではありません! (その後、効果が目立たない場合は、おそらくリファクタリングと呼ぶこともできます-また、時期尚早な最適化:)

これは私のわざわいです。人々が用語をだらしなく使用するとき、それは迷惑です-基本的にあらゆる種類の変更または修正のためにリファクタリングをカジュアルに使用する人に出くわすことさえあります。ええ、それはヒップでクールな流行語とすべてですが、changerewriteまたはperformance Improvementのような単純な古い用語には何の問題もありません。必要に応じてこれらを使用し、ソフトウェアの内部構造を本当に改善しているだけの場合にはrefactoringを予約する必要があります。特に開発チーム内では、正確にの作業について議論するための共通言語を持っていることが重要です。

12
Jonik

あなたは正しいと思いますが、言葉の意味について議論することは特に面白くないし生産的でもありません。

8
cbp

コードの一部へのインターフェイスが変更された場合、リファクタリング以上のことを検討します。

リファクタリングの典型的なケースは

  • 「ああ、私の単体テストはすべて実行されますが、コードをよりきれいにできると思います」
  • コードを読みやすく、より明確に、効率的に変更する
  • (テストを変更せずに)単体テストを再実行し、それらがまだ機能することを確認します

つまり、リファクタリングという用語は、議論しているインターフェースに関連しているということです。つまり、あるインターフェイスの背後にあるコードをリファクタリングし、より低いレベルで別のコードをより広範囲に変更することができます(おそらく、その違いがあなたと同僚の間で混乱をもたらしているのでしょうか?)

8
DanSingerman

http://en.wikipedia.org/wiki/Code_refactoring

コードリファクタリングとは、ソフトウェアの内部の非機能特性を改善するため、たとえばコードの読みやすさを改善するため、コード構造を簡素化するため、コードを変更するために、外部の機能動作や既存の機能を変更せずにコンピュータープログラムの内部構造を変更するプロセスです特定のプログラミングパラダイムに従う、保守性を向上させる、パフォーマンスを向上させる、または拡張性を向上させる。

コードのリファクタリングには、既存のコードの破壊が含まれることに同意します。バグを導入しないように単体テストを行い、残りのコードをコンパイルしてください。 Resharper for C#などのリファクタリングツールを使用すると、これが非常に簡単になります。

  • コードをより理解しやすくする
  • コードをクリーンアップして整頓する
  • コードの削除!冗長で未使用のコードとコメントは削除する必要があります
  • パフォーマンスの改善
  • より一般的なものにする。できるだけ単純なものから始めて、それをリファクタリングして、テスト/分離または汎用化を容易にし、多態性を通じてさまざまな方法で動作できるようにします
  • コードの保持DRY-繰り返してはいけません。そのため、リファクタリングセッションでは、繰り返しコードを取得して、単一のコンポーネント/クラス/モジュールにリファクタリングする必要があります。
4
superlogical

I 同意しない

ソフトウェアエンジニアリングでは、ソースコードの「リファクタリング」とは、全体的な結果を変更せずに改善することを意味します[...]

リファクタリングのサブセットに使用されるより正確な用語は既に知っています。もちろん、それは非常に一般的な用語です。

2
l0b0

「リファクタリング」という用語の定義が強すぎると、だれも利益を得られないと思います。あなたがそれをどのように知覚するかとあなたの同僚との境界はぼやけており、多くの事実に応じて彼らまたはあなたの見解により近くなる可能性があります。動的なので、定義してみましょう。まず最初に、リファクタリングしようとしているシステムまたはサブシステムの境界を定義します。

メソッドの場合、名前、入力引数、戻り値のタイプ、および場合によってはスローされるステートメントを固定します。メソッドの外部での表示方法を変更せずに、メソッド内のすべての変更を適用します。

クラスをリファクタリングしてパブリックAPIを修正し、変数の名前変更を使用すると、extractメソッドおよび他のすべての利用可能なテクニックにより、クラスが読みやすく、パフォーマンスが向上します。

リファクタリングするコードの一部がパッケージまたはモジュールである場合、クラスの名前変更、削除、インターフェイスの導入、コードのスーパー/サブクラスへのプッシュ/プルなど、その内部でリファクタリングを行います。

1
Boris Pavlović

リファクタリング=機能要件を変更せずに、非機能要件を改善します。

非機能要件=モジュール性、テスト容易性、保守容易性、可読性、懸念の分離、リスコフの原理など...

0
EnzoVici