web-dev-qa-db-ja.com

レガシーソースコードに新しい言語機能を導入するにはどうすればよいですか?

コーディングスタイルに関する質問があります。私の例ではJavaですが、急速に変化している言語に関する一般的な質問になると思います。

私はJavaコードベースを主にターゲットに記述されているコードベースに取り組んでいますJava 8.コードはJavaに移行されました12.移行とは、コードをjdk12で実行できるため、必要なライブラリの変更/追加が行われたことを意味しますが、新しい言語機能はまだ使用されていません(eg var keyword)。

私の質問は、読みやすさの観点から新しい言語要素を導入するためのアプローチとは何ですか?一貫性はどのくらい重要ですか?

私は心の中でいくつかの可能なアプローチを持っています。

  1. 新しい言語機能は新しいクラスでのみ使用する必要があります
  2. クラスの残りの部分が更新されていなくても、新しい言語機能を既存のクラスの新しく追加された部分(新しいメソッドなど)で使用できます。
  3. 新しい言語機能が既存のクラスの新しい部分に追加されたら、クラスの残りの部分も更新する必要があります

この質問は(コーディングスタイルの質問一般として)答えるのが少し難しいことはわかっていますが、それでも結論が出ることを願っています。

12
melonT

ローマにいるときは、ローマ人がするように。

コードベース全体が1つの一貫したスタイルに従っているのは素晴らしいことです。しかし、それは過去のスタイルをトラップします。

新しいスタイルに魅了されている場合、最悪の方法は、古いスタイルに残ったコードにランダムに分散させることです。

これが、家を別の色に再ペイントするとき、ペイントが損傷している場所でそれを行うだけではない理由です。部屋ごとに行います。

境界内で変更を行うことをお勧めします。コードを読む人は、それぞれの場所でどのようなスタイルが見つかるかを簡単に予測できるはずです。

作業コードのスタイルを変更することはリファクタリングです。テストなしでリファクタリングしないでください。また、すべてを一度にリファクタリングしないでください。部屋を1つ作り、一歩下がって、他の人にどう思うか尋ねます。

それができない場合は、古いスタイルを使いましょう。古いスタイルとうまく調和する新しい言語機能のみを使用してください。

23
candied_orange

私はバージョン1.1以降(2003年頃)にC#を使用しており、長年にわたって私たちが増大するコードベースに新しい言語機能を導入した方法を直接経験しています。それらが利用可能になったときはいつでも簡単に紹介し、チームの全員が、作業しているコードの領域でそれらを使用し始めました。

これらの機能が含まれています

  • ジェネリックコレクション(弱く型付けされたコレクションの代わり)

  • プロパティ構文の改善

  • varキーワード

  • 拡張メソッド

  • ラムダ式、クロージャーなどの機能ツール.

  • Linq

  • 非同期/待機

(ちょうどいくつかの例を挙げると)。

新しく書かれたコードであっても、これらの機能はそれぞれ、古い言語機能と組み合わせて使用​​されます。 Linqが使用できるからといって、すべての可能なループをLinq構成で置き換え始めるわけではありません。 「拡張メソッドが使用できる」という理由だけで、すべての関数に拡張メソッドを使用し始めません。そして、今日、every変数宣言にvarを使用しても、コードが読みやすくなるわけではありません。

したがって、実際の経験は他の答えがふりをするかもしれないほど悪くはありませんでした-全く逆です。より大きなコードベースでは、古くて不格好な構成にずっと固執したくない場合は、新しい構成somewhereを使い始める必要がありますが、それらを導入することはできませんどこにでも-そして、それらをどこでも使用するのは意味がありません。他にやむを得ない理由がない場合は、通常、作業コードセクションを新しい言語構成に更新しません。これにより、いくつかのセクションでは、新しい言語構成要素がいくつか含まれ、一部は少なくなり、一部はまったく含まれなくなり、すべてが適切に機能し、十分に読みやすく、並べて、しばしば何年もの間、自動的に機能します。

だから私のおすすめはこれを考えすぎないでくださいです。これらの機能が混在するコードの可読性は非常に主観的であり、誰もが古い言語機能と新しい言語機能をよく知っているチームでは、これは考えられるほど問題にはなりません。

18
Doc Brown

あなたは技術的負債にどう対処するかを尋ねています。重要な事柄が処理されている(新しいバージョンのJavaで動作するようにコードを更新している)と仮定すると、行う必要のある変更の種類は、ユーザーベースに直接的な影響を与えません。その結果、製品の所有者や経営陣にその移行への投資に同意してもらうことは困難です。

オープンソースプロジェクトを管理している場合、そのような管理の側面について心配する必要はありません。その場合、更新にどれだけ早く投資するかは、コミュニティ次第です。

リスクがあります

  • 新機能の仕様を誤解しているため、検出が難しい微妙なバグが発生する可能性があります
  • 一部の機能は、ライブラリ/アプリ/サービスの実装方法を再考することを強いる可能性があります。これらのターゲットを絞った書き換えは、テスト方法も変更する可能性があるため、非常に高いリスクです。
  • 最終的な結果は、コードが以前よりも理解しにくくなる可能性があります-マイナスの利点が提供されます

単体テストの健全なセットなしで作業コードを変更することは、ネットなしで綱渡りをするようなものです。細心の注意を払えばそれは可能ですが、物事がうまくいかなかった場合、それは重大な問題を引き起こす可能性があります。

技術的負債を返済する場合は、リスクを軽減するためにできることを常に実行することをお勧めします。

4
Berin Loritsch

クラスで他のリファクタリング/変更を行う場合は、クラス全体を現在のコーディングガイドラインに対応させる必要があります。同じクラスで一貫性のないスタイルを使用しないでください。クラスは、それを簡単かつ低リスクで実行できるように十分に小さくする必要があります。おそらく、クラスは変更するときにテストされます。

機械的に適用できる場合は、コードベース全体に一度に変更を適用できます。例えば。 var foo = Foo()Foo foo = Foo()よりも優れていると判断した場合、リファクタリングツールを使用して、これをコードベース全体に合理的に安全に適用できます。

2
JacquesB