web-dev-qa-db-ja.com

古いコードを更新して新しい言語構成を使用する必要がありますか、それとも古い構成をそのまま使用する必要がありますか?

ずっと前に書かれた、まだ機能しているコードのいくつかの機能を強化したいと思います。それは、プログラミング言語で書かれたプログラミング言語が機能を追加する前のことです。理論的には、プロジェクト全体で最新バージョンの言語が使用されます。ただし、この特定のモジュール(および実際には他の多くのモジュール)は、古い方言でまだ記述されています。

したほうがいい:

  • 触れる必要のないコードの部分には触れないでください。しかし、パッチの記述を容易にするが、モジュールの他のどこかで類似の状況で使用されない新しい言語機能を使用してパッチを記述しますか? (これは私が直感的に選択するソリューションです。)
  • 何年も経過しているという事実を無視し、パッチの作成中にコードの残りの部分で使用されているスタイルを反映して、何年も前に同じタスクを実行しているかのように効果的に動作しますか? (この解決策は直感的にばかげていると思いますが、「良いコード」について話す誰もが一貫して一貫性を保つことについて大騒ぎしていることを考えると、おそらくこれが私がすべきことです。)
  • モジュール全体を更新して、新しい言語構成と規則を使用しますか? (これがおそらく最良の解決策ですが、別のタスクに費やすことができる多くの時間とエネルギーが必要になる場合があります。)
15
gaazkam

状況の詳細に大きく依存するため、この質問に決定的な答えを出すことは不可能です。

コードベースのスタイルの一貫性は、コードを理解しやすくするために重要です。これは、保守性の最も重要な側面の1つです。
あなたは、異なるスタイルを混合することによってコードを理解しにくくするために地獄に呪われた最初のプログラマーではないでしょう。それはあなた自身でさえ、何年もの間でのろいをします。

一方、コードが最初に記述されたときに存在しなかった新しい言語構成体を使用しても、保守性が低下している、またはコードのスタイルが壊れているとは限りません。それはすべて、使用したい特定の言語機能と、チームがコードの古いスタイルと新機能の両方にどの程度精通しているかによって異なります。

例として、完全にOOスタイルになっているコードベースにmap/reduceなどの関数型プログラミングの概念を導入することは、一般的にはお勧めできませんが、ここにラムダ関数を追加すると機能します。以前はそのようなものを何も使用していなかったプログラムがあります。

ほとんどの場合、コードとその外観は無関係です。どのようなコードdoesが重要です。

保証できる場合、コードを変更/書き換えしてもコードの動作は変更されないので、先に進んで、コードを心ゆくまでリファクタリングできます。その「保証」は、変更の前後に実行できるユニットテストの完全なセットであり、目に見える違いはありません。

保証その安定性(これらのテストがない場合)ができない場合は、そのままにしておきます。

あなたがそれを「より良く」しようと試みていたとしても、ビジネスに不可欠なソフトウェアの一部を「壊す」ことに対して誰もあなたに感謝しません。 「働く」は毎回「より良い」よりも優先されます。

もちろん、そのような練習のためにreadinessでそのようなテストのセットを作成するのを止めることは何もありません...

5
Phill W.

コストとメリットの観点から、ほとんど何でも分析できます。これはここでも当てはまると思います。

最初のオプションの明らかな利点は、短期的に作業を最小限に抑え、動作するコードを書き直すことによって何かが壊れる可能性を最小限に抑えることです。明らかなコストは、コードベースに不整合が生じることです。ある操作Xを実行しているとき、それはコードの一部である方法で行われ、コードの別の部分で別の方法で行われます。

2番目のアプローチでは、明らかな利点である一貫性にすでに気づきました。明らかなコストは、何年も前に放棄した方法で作業するために心を曲げなければならず、コードは一貫して読み取り不能のままであることです。

3番目のアプローチの場合、明らかなコストは、さらに多くの作業を行わなければならないことです。それほど明白ではないコストは、あなたが働いていたものを壊すかもしれないということです。これは、(よくあることですが)古いコードが適切に機能し続けることを保証するためのテストが不十分な場合に特に起こりやすくなります。明らかな利点は、(それが正常に実行されたと仮定して)ニースで光沢のある新しいコードが得られることです。新しい言語構成体を使用することに加えて、コードベースをリファクタリングする機会があります。これにより、作成時に存在していたとおりの言語を使用していても、ほとんどの場合それ自体が改善されます。新しい構成体を追加して、仕事が楽になり、大きな勝利になるでしょう。

ただし、もう1つ重要な点があります。現時点では、このモジュールのメンテナンスは最小限に抑えられているようです(プロジェクト全体がメンテナンスされている場合でも)。これは、かなりうまく記述されており、比較的バグがないことを示している傾向があります。それ以外の場合は、おそらく暫定的にさらにメンテナンスが行われることになります。

それは別の質問につながります:今行っている変更の原因は何ですか?モジュールの小さなバグを修正していて、全体的にはまだ要件を十分に満たしている場合は、モジュール全体をリファクタリングするための時間と労力が、誰かがいじくる必要があるときまでに、かなり無駄になる可能性があることを示している傾向があります。繰り返しになりますが、それらは現在とほぼ同じ位置にある可能性があり、「モダン」な期待に応えないコードを維持します。

ただし、要件が変更された可能性もあり、それらの新しい要件を満たすようにコードに取り組んでいます。この場合、最初の試みが実際の現在の要件を満たさない可能性が高くなります。また、要件が再び安定する前に、要件が数ラウンドの修正を受ける可能性が大幅に高くなります。つまり、このモジュールで(比較的)近い将来に重要な作業を行う可能性が高くなり、モジュールの残りの部分全体に変更を加える可能性が高くなります。今。この場合、モジュール全体をリファクタリングすると、追加の作業を正当化する具体的な短期的なメリットが得られる可能性が高くなります。

要件が変更された場合は、どのような変更が関係しているか、およびその変更を推進しているものを確認する必要がある場合もあります。たとえば、SHA-1の使用をSHA-256に置き換えるためにGitを変更していたとしましょう。これは要件の変更ですが、範囲は明確に定義されており、非常に狭くなっています。 SHA-256を正しく保存して使用すると、残りのコードベースに影響を与える他の変更に遭遇することはほとんどありません。

逆に言えば、最初は小さく離散している場合でも、ユーザーインターフェイスの変更は膨らむ傾向があるため、「この画面に新しいチェックボックスを1つ追加する」として開始されたものは、「この固定UIを変更する」のようになります。ユーザー定義のテンプレート、カスタムフィールド、カスタマイズされた配色などをサポートします。」

前者の例では、変更を最小限に抑え、整合性の面で誤りを犯すことがおそらく最も理にかなっています。後者の場合、完全なリファクタリングが報われる可能性が高くなります。

4
Jerry Coffin

私はあなたのために最初のオプションを選びます。私がコーディングするとき、私はルールに従ってそれをより良い状態のままにします。

新しいコードはベストプラクティスに従っていますが、取り組んでいる問題とは無関係のコードには触れません。これをうまくやれば、新しいコードは古いコードよりも読みやすく、保守しやすいはずです。全体の保守性が向上することを発見しました。これを維持すると、作業のためにタッチする必要のあるコードが「より良い」コードになることが多くなります。これにより、問題の解決が速くなります。

1
Pieter B

他の多くのものと同様に、答えは 場合によります。長期的な保守性が大幅に向上する(たとえば、コールバックの地獄を回避する)など、古い構成を更新するよりも大きなメリットがある場合。大きな利点がない場合、一貫性はおそらくあなたの友人です

さらに、同じ関数に2つのスタイルを埋め込んだり、2つの別々の関数内に埋め込んだりすることは避けたいでしょう。

要約すると、最終的な決定は、特定のケースの「コスト」/「利益」分析に基づく必要があります。

1
user232573