リファクタリングでLOCが高くなるのは理にかなっていますか?[閉まっている]


25

より簡潔なコードよりも詳細なコード(より論理的なステートメントのように)のほうがクリーンな場合がありますか?



18
もちろんそうです。重複を排除する場合でも、新しい抽出関数を定義するコードは、独自のスペースを占有します。新しい関数の作成には4行が必要で、2行しか保存できませんが、それでも価値のあることです。
キリアンフォス

5
「より簡潔なコード」?行数が少ないと「より良い」コードを意味するという見当違いの信念を本当に嫌います。そうではありません。実際、通常は逆です。ますます多くの意味をますます小さなスペースに詰め込んで、コードを理解するのが難しくなるというポイントがあります-そして、それは本当に速く到達しました。実際、多くの受賞者が人間の理解の限界に依存して不可解なコードを作成する完全な競争-国際難読化Cコードコンテストがあります。
アンドリューヘンレ

1
質問のタイトルと質問自体が異なる質問をしています。たとえば、ifステートメントは、論理的には同じであるが1行だけの3項式に変更できます。
キャプテンマン

1
-1 ***より冗長なコード(より論理的なステートメントのように)***冗長性と論理ステートメントの数は2つの無関係なものです。定義を変更するのは悪い形です。
ピーターB

回答:


71

それに答えるために、私に起こった現実世界の例を取り上げましょう。私が管理している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);

これを仲間と議論すると、満場一致の評決は、ネストされた三項表現と「巧妙な」使用との組み合わせ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);
}

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

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


34
この時代、開発者の頭脳は、ディスク、CPU、RAM、またはネットワーク帯域幅よりも乏しいリソースです。これらの他のことは重要であり、特定のアプリケーションでは制限要因になる可能性がありますが、ほとんどの場合、開発者が最初にコードを理解し、次にそれらの他のことを理解できるように最適化します。
アナキシマンダー

2
@anaximander、絶対に同意します。他の人が最初に読み、コンパイラを2番目に読むためのコードを書きます。私がコードを開発しているのは自分だけであっても、他の人にコードをレビューしてもらうと便利だと思うのはそのためです。
デビッドアルノ

4
それを検討している場合、returnステートメントの順序を逆にして!、条件から削除することをお勧めします。また、2番目のリターンをに入れることをお勧めしelseます。しかし、現状のままでも、大幅な改善です。
マーティンボナーはモニカをサポートします

2
@DavidArno私はそのロジックを見て、もしif (!foo.HasValue)コードのイディオムであるなら、さらに強くそうです。ただし、これif実際には早期終了ではありませ。これは「これを行うか、それに依存するか」です。
マーティンボナーはモニカをサポートします

2
ブール値の@fabric比較は危険です。できる限り避けます。
マーティンボナーはモニカをサポートします

30

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

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

LOCは非常に基本的な測定基準であり、コードの品質と相関する場合があります。たとえば、数千のLOCを使用するメソッドには品質の問題がある可能性があります。ただし、LOCが唯一のメトリックではなく、多くの場合、品質との相関関係がないことに注意する必要があります。たとえば、4 LOCメソッドは、6 LOCメソッドよりも読みやすく、保守しやすいとは限りません。

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

あなたが取る場合はリファクタリング技術のリストを、あなたは簡単にintentionnallyで構成されたもの見つけることができます追加のLOCを。例:

どちらも非常に便利なリファクタリング手法であり、LOCに対する効果は、それらを使用するかどうかを検討する際に完全に無関係です。

LOCの使用は避けてください。

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

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


LOT(テキスト行)を追加することで回答をリファクタリングし、品質を改善しました:p
grinch

12

ソースコードのバイトカウントまたはLoCカウントを最小限に抑えることの究極の結果をご覧になりたい場合は、Stack Exchange Code Golfサイトへの投稿をご覧ください。

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

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


冗長かもしれませんが、単に説明するだけです。読みやすさのためにゴルフコードをリファクタリングすると、常により多くのLoCになります
-JollyJoker

1

はい、リファクタリングは間違いなくコードの行を増やすことができます。

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

新しく一般的なコードを(単なる内部ソフトウェアコンポーネントとしてではなく)他のユーザーがライブラリとして使用することを期待している場合、通常はユニットテストコードとコード内のドキュメントマークアップを追加することになり、コード行が再び増えます。

たとえば、すべてのソフトウェア開発者に共通する非常に一般的なシナリオを次に示します。

  • 製品には、2週間以内に緊急の高優先度の新機能、バグ修正、または機能強化が必要です(または、プロジェクトサイズ/会社サイズなどで緊急と見なされる期間)
  • あなたは一生懸命働いて、XYZを時間通りに配達します。おめでとうございます!よくやった!
  • XYZを開発している間、既存のコード設計/実装はXYZを実際にはサポートしていませんでしたが、XYZをコードベースに組み込むことができました
  • 問題は、シムがく、コードの臭いがひどいことです。これは、トリッキー/巧妙/ ugい/悪い練習ですが、ちょっとした仕事をしたからです。
  • 時間がたってから、多くのクラスを変更したり、クラスの新しいレイヤーを追加したりするコードをリファクタリングすると、新しいソリューションは「適切に」実行され、コードの悪臭はなくなります... 「正しい方法」は、より多くのコード行を使用するようになりました。

私の頭上から私に来るいくつかの具体的な例:

  • コマンドラインインターフェイスの場合、5000行のif / else-ifコードを使用するか、コールバックを使用することができます。各コールバックははるかに小さく、読み取り/テスト/検証/デバッグ/などが簡単ですが、 /い5000行のif / else-ifコードをおそらくより小さくコーディングします
  • N個の処理方法をサポートするコードの処理部分では、最もagainいように見えるif / elseステートメントを再び使用できます...
    • または、より良い/より良いコールバックに切り替えることができますが、コールバックはより多くのコード行を取ります(ただしコンパイル時間はまだです)
    • または、さらに抽象化し、実行時に変更できるプラグインを実行できます。新しいプラグインごとにメイン製品を再コンパイルしたり、既存のプラグインを変更したりする必要がないため、プラグインは便利です。APIを公開して、他の人が製品を拡張できるようにすることができます。しかし、再びプラグインのアプローチはより多くのコード行を使用します。
  • GUIの場合、素晴らしい新しいウィジェットを作成します
    • あなたまたは同僚は、新しいウィジェットはXYZおよびABCに適していると指摘していますが、現時点では、ウィジェットはXYZでのみ機能するように緊密に統合されています
    • 両方で機能するようにウィジェットをリファクタリングしますが、コードの合計行が増えます
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.