タグ付けされた質問 「refactoring」

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

11
TDDを行う人々は、主要なリファクタリングを行うときに仕事の損失をどのように処理しますか
しばらくの間、コードの単体テストを書くことを学んでいます。 最初は、真のTDDを開始しました。最初に失敗したテストを記述するまで、コードを記述しませんでした。 しかし、最近、多くのコードが関係する解決しにくい問題がありました。テストとコードの記述に数週間を費やした後、私は全体のアプローチが機能しないという不幸な結論に至り、2週間の作業を捨ててやり直す必要がありました。 これは、コードを作成したばかりの場合には十分な判断ではありませんが、数百のユニットテストを作成した場合、すべてを捨てるのはさらに感情的に困難になります。 概念実証のためにコードをまとめて、その後自分のアプローチに満足したらテストを書くことができたのに、これらのテストを書くのに3日間または4日間の努力を無駄にしたと考えるのは仕方ありません。 TDDを実践する人々は、このような状況を適切に処理しますか?いくつかのケースでルールを曲げる場合はありますか、それともコードが役に立たないことが判明した場合でも、常に最初にテストを慎重に書くのですか?
37 tdd  refactoring 

10
マジックナンバーの削除:「いいえ」と言うタイミングはいつですか?
マジックナンバー(ハードコードされた値)がプログラムに大混乱をもたらす可能性があることは誰もが知っています。特にコメントのないコードセクションを変更するときは、どこに線を引きますか? たとえば、2日間の秒数を計算する関数がある場合、置き換えますか seconds = num_days * 24 * 60 * 60 と seconds = num_days * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE どの時点で、ハードコーディングされた値の意味が完全に明らかであると判断し、そのままにしておくのですか?

12
コードの作成方法の段階的なシフトは、システムのパフォーマンスに影響しましたか?そして、私は気にする必要がありますか?
TD; DR: 私が尋ねていたものに関していくつかの混乱があったので、ここに質問の背後にある運転のアイデアがあります: 私はいつもそれが何であるかという質問を意図していました。当初はうまく表現できなかったかもしれません。しかし、意図は常に「モジュール式、分離、疎結合、分離、リファクタリングされたコード」であり、「モノリシックな単一ユニット、1か所ですべてを行う、1つのファイル、密結合された」コードよりも、それ自体の性質が著しく遅い。残りは単なる詳細であり、その際に私が出会った、または現在または将来出会うであろうさまざまな症状です。ある程度の規模では確かに遅いです。最適化されていないディスクのように、どこからでも断片を拾わなければなりません。遅いです。確かに。しかし、私は気にする必要がありますか? そして問題は…ではない マイクロ最適化、時期尚早な最適化などに関するものではありません。「これまたはその部分を最適化して死ぬ」ことではありません。 それは何ですか? それは、時間の経過とともに現れたコードの記述についての全体的な方法論と手法、および考え方に関するものです。 「このコードを依存関係としてクラスに挿入する」 「クラスごとに1つのファイルを書き込む」 「データベース、コントローラー、ドメインからビューを分離する」。 スパゲッティの均質な単一のコードブロックを書くのではなく、一緒に動作する多くの個別のモジュールコンポーネントを書く 現在-この10年以内に-ほとんどのフレームワークで見られ、主張され、規約で主張され、コミュニティを介して伝えられているコードの方法とスタイルについてです。「モノリシックブロック」から「マイクロサービス」への考え方の転換です。それに伴い、マシンレベルのパフォーマンスとオーバーヘッド、さらにプログラマレベルのオーバーヘッドの面で価格が発生します。 元の質問は次のとおりです。 コンピュータサイエンスの分野では、プログラミングに関しては思考の著しい変化に気付きました。私はこのようなアドバイスを頻繁に目にします。 より小さな関数ごとのコードを記述します(この方法によりテストと保守が容易になります) ほとんどのメソッド/関数の長さが数行になり、目的が明確になるまで、既存のコードをますます小さなコードチャンクにリファクタリングします(より大きなモノリシックブロックと比較して、より多くの関数を作成します) 1つのことだけを行う関数を書く-関心の分離など(通常、スタック上により多くの関数とフレームを作成します) より多くのファイルを作成します(ファイルごとに1つのクラス、MVC、ドメインアーキテクチャ、デザインパターン、オブジェクト指向などのレイヤーの目的のために、より多くのファイルシステム呼び出しを作成するために、分解の目的でより多くのクラス) これは、2500行にまたがるメソッドと、すべてを行う大きなクラスと神オブジェクトを持つ「古い」または「時代遅れの」または「スパゲッティ」コーディングプラクティスと比較した変更です。 私の質問はこれです: 呼び出しがマシンコード、1と0、アセンブリ命令、HDDプラッターに至るとき、リファクタリングされたさまざまな小から小の関数とメソッドを備えた完全にクラス分離されたOOコードも生成されることを心配する必要がありますか余分なオーバーヘッドですか? 詳細 OOコードとそのメソッド呼び出しが最終的にASMでどのように処理されるか、またDB呼び出しとコンパイラー呼び出しがHDDプラッター上のアクチュエータアームの移動にどのように変換されるかについてはよく知りませんが、いくつかの考えがあります。追加の関数呼び出し、オブジェクト呼び出し、または(#include)呼び出し(一部の言語)は、追加の命令セットを生成するため、実際の「有用な」コードを追加することなく、コードの量を増やし、さまざまな「コードワイヤリング」オーバーヘッドを追加すると想定しています。また、ASMが実際にハードウェアで実行される前に、ASMに対して適切な最適化を実行できることも想像しますが、その最適化を実行できるのはそれだけです。 したがって、私の質問-十分に分離されたコード(何百ものファイル、クラス、デザインパターンなどに分割されるコード)が(スペースと速度で)どのくらいのオーバーヘッドをもたらすかは、「このオーバーヘッドのために、すべてを1つのモノリシックファイルに」 明確にするために更新: 同じコードを取得して分割し、リファクタリングし、より多くの関数とオブジェクト、メソッド、クラスに分離することで、より小さなコード間でより多くのパラメーターが渡されると想定しています。確かに、リファクタリングコードはスレッドを継続する必要があり、そのためにはパラメーターを渡す必要があります。より多くのメソッドまたはより多くのクラスまたはより多くのファクトリメソッドのデザインパターンは、単一のモノリシッククラスまたはメソッドの場合よりも、さまざまな情報を渡すオーバーヘッドを増やします。 どこか(TBDを引用)では、すべてのコードの最大70%がASMのMOV命令で構成され、実際の計算ではなくCPUレジスタに適切な変数をロードすると言われていました。私の場合、PUSH / POP命令を使用してCPUの時間を増やし、さまざまなコード間でリンケージとパラメーターの受け渡しを行います。コードを小さくするほど、より多くのオーバーヘッド「リンケージ」が必要になります。このリンケージがソフトウェアの肥大化とスローダウンに追加することを懸念しており、これを心配する必要があるのか​​、もしあれば、どれくらいの量を心配する必要があるのか​​、次の世紀のソフトウェアを構築しているプログラマーの現在と将来の世代、これらのプラクティスを使用して構築されたソフトウェアと共存し、使用する必要があります。 更新:複数のファイル 古いコードを徐々に置き換えている新しいコードを書いています。特に、古いクラスの1つが〜3000行のファイルであったことに注意しました(前述のとおり)。今では、テストファイルを含むさまざまなディレクトリに配置された15〜20のファイルのセットになりつつあり、いくつかのものを結合するために使用しているPHPフレームワークは含まれません。さらに多くのファイルが来ています。ディスクI / Oに関しては、複数のファイルのロードは、1つの大きなファイルのロードよりも遅くなります。もちろん、すべてのファイルがロードされるわけではなく、必要に応じてロードされ、ディスクキャッシングとメモリキャッシングのオプションが存在しますが、それでもメモリloading multiple filesよりも多くの処理が必要になると思いloading a single fileます。それを懸念に加えています。 更新:依存性のすべてを注入 しばらくしてこれに戻って..私の質問は誤解されたと思います。または、いくつかの答えを誤解することを選んだかもしれません。いくつかの答えが出てきたので、マイクロ最適化については話していません(少なくとも、マイクロ最適化について話していることは間違った呼び方だと思います)。 、コードのあらゆるレベルで。私は最近、このスタイルのコードがコンベンションの中心的なポイントの1つであり、Zend Conから来ました。ビューからロジック、モデルからビュー、データベースからモデルを分離し、可能であればデータベースからデータを分離します。依存関係-すべてを挿入します。これは、何もしない配線コード(関数、クラス、ボイラープレート)を追加することを意味する場合があります、ただし、シーム/フックポイントとして機能し、ほとんどの場合、コードサイズを簡単に2倍にします。 更新2:「コードをより多くのファイルに分割する」ことは、パフォーマンスに大きな影響を与えますか(コンピューティングのすべてのレベルで) compartmentalize your code into multiple files今日のコンピューティング(パフォーマンス、ディスク使用率、メモリ管理、CPU処理タスク)の哲学はどのように影響しますか? …

4
このタイプのリファクタリングの用語は何ですか
次のリファクタリングの用語があると確信していますが、それを思い出すことができず、Google-fuが失敗しています! リファクタリングは、ステートメントを変更すると、ステートメントが最も影響を与える場所に移動します $test = someFunctionThatReturnsABool(); for($x = 0; $x < 10000; $x++) { if ($test) { echo $x; } } これに $test = someFunctionThatReturnsABool(); if ($test) { for($x = 0; $x < 10000; $x++) { echo $x; } }

7
未知のコードの重複を防ぐにはどうすればよいですか?
私はかなり大きなコードベースに取り組んでいます。数百のクラス、大量の異なるファイル、多くの機能が、新しいコピーの取得などに15分以上かかります。 このような大きなコードベースの大きな問題は、かなりの数のユーティリティメソッドがあり、同じことを行うか、可能な場合にこれらのユーティリティメソッドを使用しないコードがあることです。また、ユーティリティメソッドは、すべてが1つのクラスに含まれているわけではありません(巨大な混乱のせいだからです)。 私はコードベースにはかなり慣れていませんが、何年もこのコードに取り組んでいるチームリーダーも同じ問題を抱えているようです。それは多くのコードと作業の重複につながり、そのため、何かが壊れると、通常は基本的に同じコードの4つのコピーで壊れます このパターンをどのように抑制できますか?ほとんどの大規模プロジェクトと同様に、すべてのコードが文書化されているわけではありません(一部は文書化されています)。しかし、基本的には、この点で品質の改善に取り組み、将来コードの重複を減らし、ユーティリティ関数のようなものを見つけやすくすることができれば、本当に素晴らしいことです。 また、ユーティリティ関数は通常、いくつかの静的ヘルパークラス、単一のオブジェクトで動作する非静的ヘルパークラス、または主に「ヘルプ」を行うクラスの静的メソッドのいずれかにあります。 拡張メソッドとしてユーティリティ関数を追加する1つの実験がありました(クラスの内部は不要であり、非常に特定のシナリオでのみ必要でした)。これには、プライマリクラスなどが乱雑になるのを防ぐ効果がありましたが、すでにそれを知っていない限り、実際には発見できません

8
「変数は可能な限り最小のスコープ内に存在する必要があります」には、「変数は可能であれば存在してはならない」というケースが含まれていますか?
「インスタンス変数よりもローカル変数を好む理由」で受け入れられている回答によると、変数は可能な限り最小のスコープ内に存在する必要があります。 問題を私の解釈に単純化します。つまり、この種のコードをリファクタリングする必要があるということです。 public class Main { private A a; private B b; public ABResult getResult() { getA(); getB(); return ABFactory.mix(a, b); } private getA() { a = SomeFactory.getA(); } private getB() { b = SomeFactory.getB(); } } このようなものに: public class Main { public ABResult getResult() { A a = getA(); …

10
「親x = new Child();」ではなく「親x = new Child();」は、後者を使用できる場合の悪い習慣ですか?
たとえば、次のようなフラグメントを作成するコードを見たことがあります。 Fragment myFragment=new MyFragment(); MyFragmentではなくFragmentとして変数を宣言します。MyFragmentはFragmentの子クラスです。このコードは次のようにすべきだと思うので、このコード行を満足していません MyFragment myFragment=new MyFragment(); より具体的ですが、本当ですか? または質問の一般化では、使用するのは悪い習慣ですか? Parent x=new Child(); の代わりに Child x=new Child(); 前者をコンパイルエラーなしで後者に変更できるとしたら?

9
リファクタリングするタイミング
ファウラーのリファクタリングの本のほとんどを読み、過去の大小の多くのアプリケーションをリファクタリングしました。 私が教えるのが難しいのは、「いつ」リファクタリングするかです。私は過去に非常によく役立ってきた腸の感覚に基づいてこれを行う傾向があります。ただし、コードをそのままにするかリファクタリングするかについて人々と議論するとき、「ガットチェック」に耐えることは困難です。 もっと厳密なアプローチが必要だと感じていますが、それが何であるかはわかりません。 私は「コード臭」、赤緑リファクタリング、その他の考えを理解していますが、リファクタリングに最適なのは、コードを最初に書くのではなく、コードを使用して2回目または3回目にすることですそれは実際に問題であり、実際に使用されていることです。

4
マジックストリング/数字の使用[終了]
これはやや物議を醸すトピックであり、プログラマーと同じくらい多くの意見があると思います。しかし、そのために、ビジネス(または職場)での一般的な慣行を教えてください。 私の職場では、厳密なコーディングガイドラインがあります。その1つのセクションは、マジックストリング/マジックナンバー専用です。状態(C#の場合): コードでは、記号定数を定義する以外に、数値または文字列のリテラル値を使用しないでください。次のパターンを使用して、定数を定義します。 public class Whatever { public static readonly Color PapayaWhip = new Color(0xFFEFD5); public const int MaxNumberOfWheels = 18; } 例外があります:値0、1、nullはほとんど常に安全に使用できます。多くの場合、値2および-1も問題ありません。ロギングまたはトレースを目的とした文字列は、この規則から除外されます。リテラルは、意味が文脈から明らかであり、将来の変更の影響を受けない場合に許可されます。 mean = (a + b) / 2; // okay WaitMilliseconds(waitTimeInSeconds * 1000); // clear enough 理想的な状況は、次の場合にコードの可読性/保守性への影響を示す公式の研究論文です。 魔法の数字/文字列がいたるところにある 魔法の文字列/数字は、一定の宣言によって合理的に(またはさまざまな範囲で)置き換えられます-「合理的に」使用することについて私に怒鳴らないでください 魔法の文字列/数字は、過剰に置き換えられる必要があります(以下の私の例を参照) 私の同僚の1人と議論するときに科学的根拠に基づいた議論をするためにこれをしたいと思います。彼は次のような定数を宣言するようになります: private const char SemiColon = ';'; private …

11
友達と小さなプロジェクトをいつ放棄するかを決定する方法に影響する要因は何ですか?[閉まっている]
私は最近、厳しい状況に陥っています。ほぼ8か月間、プログラミング仲間とのゲームに取り組んでいます。私たちは両方とも昨年の8月頃にプログラミングの初心者としてスタートしました。彼は2年目のCS学生であり、私は業界のITサポート技術者であり、多数の書籍とオンラインサブスクリプションを持つ独学のプログラマーです。 私が常に見てきた問題は、コードの塊を書き出すと、多くの場合、一緒に少しハッキングされ、多くの失敗があり、それが私たちの新しいコンセプトである場合、素朴なソリューションでいっぱいです。これは問題ありません。学習中です。最初のパスまたは2回目のパスで、両方のコードが少しハッキングされることを期待しています。問題は、ハッキングされたこれらの動作を実際に修正およびリファクタリングするときに発生します。 私のパートナーは、動作を開始した瞬間にエラーを見ることを露骨に拒否して、彼の新鮮な一緒に行動を保持します。構造の一部からほぼ完璧を主張して、コメントがあり、適切な名前のメソッドとフィールドがあっても、使用することさえできません。どんなに一生懸命努力しても、動作を完全に破壊することなく、それ以上の変更や動作の拡張を妨げる明白な欠陥を彼に見せることはできません。それらはすべて同じクラスに属する可能性があります。ハッキングされたソリューションは、常にハッキングされたままであり、設計が十分に検討されていないため、最初に考案およびテストされたときの設計はそのままです。 新しいコードを自分で作成するのと同じくらい多くの時間をベビーシッターに費やしています。私のパートナーは今夜それを失い、ベンチマーク、一般的な慣行、反論できない証拠に関係なく、彼のコードは彼が最初に作った方法のままであることを明らかにしました。あなたが何かをすることを避けたい理由について本全体が書かれていたとしても、彼はそれが単なる誰かの意見であると主張する彼らの妥当性を認めることを拒否するでしょう。 私は私たちのプロジェクトに強い関心を持っていますが、パートナーと一緒に仕事を続けられるかどうかはわかりません。私には3つの選択肢があります。 コンパイルの時点を過ぎて機能するコードベースを気にするのをやめ、かろうじてリンプしている動作を維持および解析しようとすることに対処します。物事が真剣に壊れ始めたら、彼はそれを見て、根本的に欠陥のあるデザインにただ絆創膏をかける以上のことをしようとするでしょう。 他のはるかに有能な個人によって10年前に見つけられた問題についての無限の議論を続けてください。 このプロジェクトでのプログラミングを停止し、コードの10,000行近くを放棄し、設計に時間を費やす無数の時間を費やして、自分で新しいプロジェクトを見つけてみてください。 この人とこのプロジェクトを続ける価値があるかどうかを判断するには、どのようなアプローチを取ることができますか?または、どの要因が私の決定に影響を与えるべきですか?私たちは多くのコードを書きましたが、必要がない限りこれをあきらめたくありません。

6
技術的負債を処理することでどのような見返りがありますか?
技術的負債に関するこの記事には、次のような優れた点があります。 「技術的な問題」に取り組むことは、ストーリーによって推進されるときに最も効果的です。コードベースはおそらくどこでも作業を必要としますが、ユーザーに面した理由でコードが作業される場所でのみペイオフが受け取られます。ストーリーがなかなか難しい領域を通過しない場合、その作業はほとんど無駄になります。 したがって、私はいつものように(しかしおそらくそれよりも少ない)物語を取り上げ、あなたが見つけたよりもキャンプ場を去るという「ボーイスカウトのルール」に従うアプローチを好む。言い換えれば、ストーリーが私たちを導くところはどこでも、より多くのテストを書きましょう、より積極的にリファクタリングしましょう。 このアプローチには、少なくとも次の利点があります。 「賢明な」ストーリーの流れを維持します。 チームのすべての才能からの支援を提供します。 チーム全体がコードをクリーンに保つ方法を学習できるようにします。 改善が必要な場所に正確に焦点を合わせます。 「必要な」改善を無駄にしない; コードの品質が長期的な生産性に非常に大きな影響を与えるのを見てきましたので、技術的な負債を処理する必要があると考えています。上記の投稿は理にかなっていると思いますが、最後の2つのポイントについてはよくわかりません。たとえユーザーのストーリーに関係していなくても、技術的な負債を取り除くことで得られるメリットの実際の経験を見つけることに興味があります。 コードベースを整理し、技術的な負債をなくすことで、どのようなプラスのメリットがありましたか?仕事を成し遂げるためにどのような方法を使用しましたか?

8
リファクタリング時にユニットテストをどのように機能させ続けるのですか?
別の質問で、TDDの問題の1つは、リファクタリング中およびリファクタリング後にテストスイートをコードベースと同期させることであることが明らかになりました。 今、私はリファクタリングの大ファンです。TDDをやめるつもりはありません。しかし、マイナーなリファクタリングが多くのテストの失敗につながるような方法で書かれたテストの問題も経験しました。 リファクタリング時にテストが中断しないようにするにはどうすればよいですか? テストを「より良い」と書いていますか?もしそうなら、あなたは何を探すべきですか? 特定の種類のリファクタリングを避けていますか? テストリファクタリングツールはありますか? 編集:質問の意味を尋ねる新しい質問を書きました(ただし、これは興味深いバリエーションとして残しました)。

6
フラグをチェックする必要をなくすためのデザインパターンはありますか?
データベースに文字列ペイロードを保存します。2つのグローバル構成があります。 暗号化 圧縮 これらは、構成を使用して有効または無効にすることができます。その場合、どちらか一方のみを有効にするか、両方を有効にするか、両方を無効にします。 私の現在の実装はこれです: if (encryptionEnable && !compressEnable) { encrypt(data); } else if (!encryptionEnable && compressEnable) { compress(data); } else if (encryptionEnable && compressEnable) { encrypt(compress(data)); } else { data; } デコレータパターンについて考えています。それは正しい選択ですか、それとももっと良い選択肢がありますか?

6
Switchステートメントのリファクタリングと、Switchステートメントの実際の使用はありますか?
私はこの記事を読んでいて、プロジェクトにswitchステートメントがまったくないように、すべてのswitchステートメントをディクショナリーまたはファクトリーに置き換えることで削除するのかと疑問に思っていました。 何かが足りませんでした。 問題は、switchステートメントを実際に使用するか、辞書やファクトリーメソッドに置き換えるか(ファクトリーメソッドを使用する場合は、オブジェクトを作成するためにswitchステートメントを最小限使用することです)工場を使用して...しかしそれはそれについてです)。

13
外部動作を変更せずにリファクタリングをどこまでプッシュできますか?
Martin Fowlerによると、コードのリファクタリングは次のようになります(私の強調): リファクタリングは、既存のコード本体を再構築し、外部の動作を変更せずに内部構造を変更するための統制された手法です。その中心は、変換を維持する一連の小さな動作です。各変換(「リファクタリング」と呼ばれます)はほとんど行いませんが、一連の変換によって大幅な再構築が行われる可能性があります。それぞれのリファクタリングは小さいので、間違いが起こる可能性は低くなります。また、システムは小さなリファクタリングのたびに完全に機能し続けるため、再構築中にシステムが深刻に破損する可能性が低くなります。 この文脈における「外部行動」とは何ですか?たとえば、移動メソッドのリファクタリングを適用して、あるメソッドを他のクラスに移動すると、外部の動作が変更されたように見えますか? それで、私はどの時点で変更がリファクタリングでなくなり、さらに何かになるのかを知ることに興味があります。「リファクタリング」という用語は、大きな変更に誤用される可能性があります。別の言葉がありますか 更新。インターフェースに関する多くの興味深い回答がありますが、メソッドのリファクタリングを動かしてインターフェースを変更しませんか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.