11

ベストプラクティスに従うのが好きな人として、

コード メトリクスを実行した場合 (ソリューション エクスプローラーでプロジェクト名を右クリックし、[コード メトリクスの計算] - Visual Studio 2010) を選択します。

    public static string GetFormFactor(int number)
    {
        string formFactor = string.Empty;
        switch (number)
        {
            case 1:
                formFactor = "Other";
                break;

            case 2:
                formFactor = "SIP";
                break;

            case 3:
                formFactor = "DIP";
                break;

            case 4:
                formFactor = "ZIP";
                break;

            case 5:
                formFactor = "SOJ";
                break;
        }

        return formFactor;
    }

それは私に61の保守性指数を与えます

(もちろん、これしかない場合、これは重要ではありませんが、哲学がそのようなことをしているクラスのようなユーティリティを使用する場合、ユーティリティクラスの保守性指数は最悪になります..)

これに対する解決策は何ですか?

4

7 に答える 7

26

まず第一に:61は保守可能なコードと見なされます。保守性指数の場合、100はコードの保守が非常に簡単ですが、0は保守が困難です。

  • 0-9=維持するのが難しい
  • 10-19=中程度の維持
  • 20-100=維持するのが良い

保守性指数は、3つのコードメトリックに基づいています。つまり、Halstead Volumen、Cyclomatic Complexity、およびLines of Codeであり、次の式に基づいています。

MAX(0、(171-5.2 * ln(Halstead Volume)-0.23 *(循環的複雑度)-16.2 * ln(コード行))* 100/171)

実際、あなたの例では、保守性指数の値が低い根本的な原因は循環的複雑度です。このメトリックは、コード内のさまざまな実行パスに基づいて計算されます。残念ながら、メトリックは必ずしもコードの「人間の可読性」と一致するとは限りません。

コードの例では、インデックス値が非常に低くなります(覚えておいてください、低いと保守が難しくなります)が、実際には非常に読みやすくなっています。これは、循環的複雑度を使用してコードを評価する場合に一般的です。

日(月〜日)のスイッチブロックと月(1月〜12月)のスイッチブロックがあるコードを想像してみてください。このコードは非常に読みやすく、保守しやすくなりますが、循環的複雑度が非常に高くなるため、VisualStudio2010の保守性インデックスが非常に低くなります。

これはメトリックについてよく知られている事実であり、コードが数値に基づいて判断される場合は考慮する必要があります。コードの変更の指標として理解するために、絶対数ではなく、数値を経時的に監視する必要があります。たとえば、保守性指数が常に100で、突然10に下がった場合は、これを引き起こした変化を調べる必要があります。

于 2010-06-21T13:01:29.257 に答える
5

ソリューションに選択している方法に拡張性がないため、保守性指数が高くなる可能性があります。

正しい解決策 (上記で触れた Mark Simpson) は、コードを再構築せずに新しいフォーム ファクターを使用するように拡張できるものです。悪いコードの匂いとして。

個人的には、私は実装します...

interface IFormFactor
{
    // some methods
}

class SipFormFactor : IFormFactor...

class DipFormFactor : IFormFactor...

Etc.

...そして、インターフェイスのメソッドが必要な機能を提供するようにします-GoFコマンドパターンに似ていると考えることができます[私は推測します]。

このようにして、より高いレベルのメソッドは...

MyMethod(IFormFactor factor)
{
    // some logic...

    factor.DoSomething();

    // some more logic...
}

...そして、ハードコードされた switch 句の場合のようにこのコードを変更することなく、後日、新しいフォーム ファクターを導入することができます。また、このアプローチは簡単にモック化できるため、TDD にも簡単に適用できることがわかります (TDD を適切に実行している場合は、最終的にはこれになるはずです)。

于 2011-10-28T13:59:01.550 に答える
3

私はこの答えが非常に遅いことを知っていますが、誰もまだ辞書の解決策を提示していないことに興味がありました. このようなデータ指向の巨大な switch ステートメントを扱う場合、多くの場合、switch-case を辞書にまとめた方が読みやすいことがわかりました。

public static readonly IDictionary<int, string> Factors = new Dictionary<int, string> {
   { 1, "Other" },
   { 2, "SIP" },
   { 3, "DIP" },
   { 4, "ZIP" },
   { 5, "SOJ" }
};

public static string GetFormFactor2(int number)
{
   string formFactor = string.Empty;
   if (Factors.ContainsKey(number)) formFactor = Factors[number];
   return formFactor;
}

これにより、74 の保守性インデックスが得られます。ディクショナリへのクラス結合のため、配列ソリューションよりもわずかに低くなりますが、通常はオンにする任意の数の型に対して機能するため、より一般的だと思います。配列ソリューションと同様に、拡張性が非常に高く、反復的なコードを大幅に削減できます。

一般的に言えば、データ駆動型のアプローチを使用すると、重要な部分 (この場合は条件と結果) が不要な部分 (この場合は switch-case) から分離されるため、コードがより明確になります。

于 2014-05-28T19:37:48.763 に答える
2

次の 2 つのことが思い浮かびます。

列挙型を使用して、説明と値を結びつける

public enum FormFactor
{
    Other = 1,
    SIP = 2,
    etc.
}

クラスまたは構造体を使用して各フォーム ファクタを表す

public class FormFactor 
{
    public int Index { get; private set; }
    public string Description { get; private set; }

    public FormFactor(int index, string description)
    {
        // do validation and assign properties
    }
}
于 2010-05-29T22:43:17.860 に答える
2

私はこのようにして保守性指数を忘れます:

public static string GetFormFactor(int number)
{
    switch (number)
    {
        case 1: return "Other";
        case 2: return "SIP";
        case 3: return "DIP";
        case 4: return "ZIP";
        case 5: return "SOJ";
    }

    return number.ToString();
}

私見は読みやすく、変更も簡単です。

于 2010-05-29T23:19:11.920 に答える
0

明らかに私にとってEnumメソッドは、ハードコードされた文字列を含まないため、タイプミスの問題やコンパイル時の構文チェックがないため、最も保守しやすい方法です。制限のみが命名規則です。

于 2010-09-23T13:38:55.667 に答える
0

それがどれほど重要かはわかりませんが、次の例では 76 が得られます。

private static string[] _formFactors = new[] { null, "Other","SIP","DIP", "ZIP", "SOJ"};
public static string GetFormFactor2(int number)
{
    if (number < 1 || number > _formFactors.Length)
    {
        throw new ArgumentOutOfRangeException("number");
    }

    return _formFactors[number];
}
于 2010-05-29T23:04:31.927 に答える