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


15

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

したほうがいい:

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

1
@JerryCoffinコメントを議論し続けるつもりはありません。適切な議論ができるメタ投稿しました

回答:


10

状況の詳細に依存しすぎるため、この質問に明確な答えを出すことは不可能です。

コードベースのスタイルの一貫性は、保守性の最も重要な側面の1つであるコードを理解しやすくするのに役立つため、重要です。
異なるスタイルを混在させることでコードを理解しにくくすることで、地獄に呪われた最初のプログラマーではないでしょう。一年のうちに呪いをかけるのはあなた自身でさえあるかもしれません。

一方、コードが最初に記述されたときに存在しなかった新しい言語構造を使用しても、保守性が低下したり、コードのスタイルが崩れたりすることを自動的に示唆するものではありません。それはすべて、使用したい特定の言語機能と、コードの古いスタイルと新しい機能の両方にチームがどれだけ慣れているかに依存します。

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


1
私は部分的に同意しません。オープンクローズの原則に従う必要があります。そのため、できる限り新しいコードを分離し、同時に可能な限り最新の言語構成で新しいコードを作成する必要があります。
アナンドVaidya

3
@AnandVaidya:古いコードがOCPに従うか、OCPに従うように簡単に変更できると仮定しているため、IMHOは非現実的な期待です。
Doc Brown

1
私がocpと言ったとき、私はおっとocpを意味するのではなく、一般的にocpを意味します。基本的には、既存のコードを可能な限り変更せず、独自のコードを分離しようとします。古い手続き型コードでも可能です。スパゲッティコードはそのように変更できないことを理解していますが、どのようなパラダイムでも適切に設計されたコードの場合、オープンクローズは簡単に適用できるはずです。おっと、手続き的または機能的かもしれません。
アナンドVaidya

2
@AnandVaidya:OCPを意味しない場合、そのように呼ぶべきではありません。あなたが本当に言っているのは、Featherがsproutメソッドで新しいコードを書くと呼んでいるものだと思うので、新しいコードスタイルを新しい分離されたメソッドに制限することができます。これが可能かつ賢明な場合、あなたは正しいです、それは大丈夫です。残念ながら、少なくとも古いコードをDRYにしたい場合は、このアプローチは常に適用できるとは限りません。
ドックブラウン

@DocBrown:オープン/クローズドの原則はオブジェクト指向プログラミングに限定されるとは思いません。新しいプロシージャを追加するモジュールを使用できますが、既存のプロシージャは変更しないでください。つまり、既存のコードのセマンティクスをそのまま維持し、新しい機能が必要な場合は新しいコードを記述します。
ジョルジオ

5

大部分、コードとその外観は無関係です。コードが行うことは重要です。

コードの変更/書き換えによってコードの動作が変わらないことを保証できる場合は、先に進み、コードを思いのままにリファクタリングできます。その「保証」とは、変更の前後に実行できる単体テストの包括的なセットであり、知覚可能な違いはありません。

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

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

もちろん、あなたが、このような一連のテスト作成を停止するためには何もありません準備が、このような運動のためには...


4

費用と便益の観点からほとんどすべてを分析できます。これはここで当てはまると思います。

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

2番目のアプローチについては、一貫性という明白な利点に既に注意しました。明らかなコストは、何年も前に見捨てられた方法で作業するために心を曲げなければならず、コードが一貫して読めないままであることです。

3番目のアプローチの場合、明らかなコストは単にもっと多くの作業をしなければならないことです。それほど明白ではないコストは、動作していたものを壊す可能性があることです。(多くの場合そうであるように)古いコードが正しく動作し続けることを保証するためのテストが不十分な場合、これは特に起こりそうです。明らかな利点は、(あなたがうまくやったと仮定して)あなたが素晴らしい、光沢のある新しいコードを持つことです。新しい言語コンストラクトの使用に加えて、コードベースをリファクタリングする機会があります。これは、記述されたときとまったく同じ言語を使用した場合でも、ほぼ常にそれ自体が改善されます-新しいコンストラクトに追加すると、仕事が楽になり、大きな勝利になるかもしれません。

ただし、もう1つの重要なポイント:現在、このモジュールは長期間にわたって最小限のメンテナンスしか行われていないようです(プロジェクト全体がメンテナンスされている場合でも)。それは、それがかなりよく書かれていて、比較的バグがないことを示す傾向があります-そうでなければ、おそらく、その間にもっとメンテナンスを受けていただろう。

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

ただし、要件が変更された可能性もあり、それらの新しい要件を満たすためにコードに取り組んでいます。この場合、最初の試行が実際に現在の要件を満たしていない可能性があります。また、要件が再び安定する前に、要件が数回改訂される可能性が大幅に高くなります。つまり、あなたはこのモジュールで(比較的)短期的に重要な仕事をする可能性が非常に高く、正しいことを知っている1つの領域だけでなく、モジュールの残りの部分全体で変更を行う可能性が非常に高いことを意味します今。この場合、モジュール全体をリファクタリングすると、追加の作業を正当化する具体的で短期的なメリットが得られる可能性が高くなります。

要件が変更された場合、どのような変更が関係しており、その変更を推進している要因も調べる必要があります。たとえば、Gitを変更して、SHA-1の使用をSHA-256に置き換えると仮定します。これは要件の変更ですが、範囲は明確に定義されており、かなり狭いものです。SHA-256を正しく保存して使用すると、他のコードベースに影響を与える他の変更に遭遇する可能性は低くなります。

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

前者の例では、おそらく、変更を最小限に抑え、一貫性を損なうことが最も理にかなっています。後者の場合、完全なリファクタリングのほうがはるかに効果があります。


1

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

そのため、新しいコードはベストプラクティスに従いますが、作業中の問題とは無関係のコードには触れません。これをうまく行えば、新しいコードは古いコードよりも読みやすく保守しやすくなります。全体の保守性が向上することがわかりました。これを維持すれば、作業のために触れる必要のあるコードが「良い」コードになることが多いためです。これにより、問題をより迅速に解決できます。


1

答えは、他の多くのものと同様に、依存します。古いコンストラクトを更新することに大きな利点がある場合(たとえば、長期にわたる保守性の大幅な改善(たとえば、コールバックの地獄の回避)など)。大きな利点がない場合、一貫性はおそらくあなたの友人です

さらに、2つの別個の関数内で回避するよりも、同じ関数に2つのスタイルを埋め込むことも避けたいでしょう。

要約すると、最終決定は、特定のケースの「コスト」/「メリット」分析に基づいている必要があります。

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