web-dev-qa-db-ja.com

LOCが高くなることをリファクタリングが意味することはありますか?

(より論理的なステートメントのように)より詳細なコードがより簡潔なコードよりクリーンであるケースはありますか?

25
wrongusername

これに答えるために、私に起こった実際の例を見てみましょう。私が管理しているC#ライブラリには、次のコードがありました。

TResult IConsFuncMatcher<T, TResult>.Result() =>
    TryCons(_enumerator) is var simpleMatchData && !simpleMatchData.head.HasValue
        ? _emptyValue.supplied
            ? _emptyValue.value
            : throw new NoMatchException("No empty clause supplied");
        : _recursiveConsTests.Any() 
            ? CalculateRecursiveResult() 
            : CalculateSimpleResult(simpleMatchData);

これについて仲間と話し合ったところ、全会一致の評決は、ネストされた3項式とis varの「巧妙な」使用を組み合わせた結果、簡潔になったものの、コードの読み取りが困難になったことです。

だから私はそれを次のようにリファクタリングしました:

TResult IConsFuncMatcher<T, TResult>.Result()
{
    var simpleMatchData = TryCons(_enumerator);

    if (!simpleMatchData.head.HasValue)
    {
        return _emptyValue.supplied
            ? _emptyValue.value
            : throw new NoMatchException("No empty clause supplied");
    }

    return _recursiveConsTests.Any() 
        ? CalculateRecursiveResult() 
        : CalculateSimpleResult(simpleMatchData);
}

元のバージョンには、暗黙のreturnを含む複合式が1つだけ含まれていました。新しいバージョンには、明示的な変数宣言、ifステートメント、および2つの明示的なreturnsが含まれています。より多くのステートメントとより多くのコード行が含まれています。それでも、私が相談したすべての人は、「クリーンなコード」の重要な側面である、読みやすく、理由付けが簡単だと考えました。

したがって、あなたの質問への答えは強調された「はい」であり、簡潔なコードよりも冗長である方がクリーンな場合があるため、有効なリファクタリングです。

70
David Arno

1。 LOCとコード品質の相関関係の欠如

リファクタリングの目標は、コードの品質を向上させることです。

LOCは非常に基本的なメトリックであり、コードの一部の品質と相関する場合があります。たとえば、数千のLOCを持つメソッドには品質の問題がある可能性があります。ただし、LOCはonlyメトリックではなく、多くの場合、品質との相関関係がないことに注意してください。たとえば、4 LOC方式は、6 LOC方式よりも必ずしも読みやすく、維持しやすいとは限りません。

2。一部のリファクタリング手法は、LOCの追加で構成されます。

リファクタリング手法のリスト を使用すると、意図的にLOCを追加するものから簡単に見つけることができます。例:

どちらも非常に有用なリファクタリング手法であり、LOCへの影響は、それらを使用するかどうかを検討する場合はまったく関係ありません。

LOCの使用を避けます。

LOCは危険なメトリックです。測定は非常に簡単で、正しく解釈することは非常に困難です。

コード品質の測定手法に慣れるまで、そもそもLOCを測定しないことを検討してください。ほとんどの場合、関連するものは何も得られず、コードの品質を低下させるように誤解させる場合もあります。

30

ソースコードのバイト数またはLoC数を最小限に抑えた最終的な結果を確認したい場合は、 Stack Exchange Code Golfサイト への送信を確認してください。

あなたのソースコードがそのような方法で減らされるならば、あなたはすぐに手に負えない混乱を持っています。あなたがそのようなコードを書いた人であり、その時点でそれを完全に理解していたとしても、6か月後にコードに戻る場合、どのくらい効率的ですか?このような最小限のコードが実際に速く実行されるという証拠もありません。

コードは、チームのどのメンバーもそれを見て、すぐに何が行われているかを理解できるような方法で書く必要があります。

12
Peregrine

はい、リファクタリングは間違いなくより多くのコード行をもたらす可能性があります。

IMOの最も一般的なケースは、ジェネリックではないコードを使用して、それをよりジェネリック/フレキシブルにする場合です。コードを汎用化すると、コードの行が大幅に増加します(2倍以上になる場合もあります)。

新しく汎用的なコードが(内部ソフトウェアコンポーネントとしてだけでなく)他の人によってライブラリとして使用されることが予想される場合は、通常、ユニットテストコードとコード内ドキュメントマークアップを追加することになり、コードの行が再び増加します。

たとえば、すべてのソフトウェア開発者に発生する非常に一般的なシナリオは次のとおりです。

  • 製品には、2週間以内に緊急性の高い優先度の高い新機能、バグ修正、または機能強化が必要です(または、プロジェクトサイズ/会社サイズ/その他で緊急と見なされる時間枠)
  • あなたは一生懸命働き、XYZを時間通りに届け、それは機能します。おめでとう!よくやった!
  • XYZを開発している間、既存のコード設計/実装は実際にはXYZをサポートしていませんでしたが、XYZをコードベースにシムすることができました
  • 問題は、shimが醜く、コードの臭いがひどいことです。これは、トリッキー/賢い/醜い/悪い実践-しかしちょっとした作業をしたためです
  • 後で時間を見つけたときに、多くのクラスを変更するか、クラスの新しいレイヤーを追加する可能性があるコードをリファクタリングすると、新しいソリューションは「正しく行われ」、悪質なコード臭はもうありません...ただし、これを「正しい方法」で行うと、コードの行数が増えます。

私の頭上に浮かぶいくつかの具体的な例:

  • コマンドラインインターフェイスの場合 if/else-ifコードを5000行使用するか、コールバックを使用できます...各コールバックははるかに小さく、読みやすく/テスト/検証/デバッグ/などですが、コードの行を数えると、醜い5000行のif/else-ifコードがおそらく小さくなる
  • N個の処理方法をサポートするコードを処理する場合の場合、if/elseステートメントを再び使用すると、最も醜く見えます...
    • または、より良い/より良いコールバックに切り替えることもできますが、コールバックはより多くのコード行を必要とします(ただしコンパイル時間はかかります)。
    • または、さらに抽象化して、実行時に変更できるプラグインを実行することもできます。新しいプラグインや既存のプラグインへの変更ごとにメイン製品を再コンパイルする必要がないため、プラグインは素晴らしいです。また、APIを公開して、他の人が製品を拡張できるようにすることもできます。ただし、プラグインアプローチでは、さらに多くのコード行を使用します。
  • GUIの場合、素晴らしい新しいウィジェットを作成します
    • あなたまたは同僚は、新しいウィジェットはXYZとABCに最適であると述べていますが、現在、ウィジェットはXYZでのみ機能するように緊密に統合されています
    • ウィジェットを両方で機能するようにリファクタリングしますが、コードの総行数が増加します
1