Показатели кода Visual Studio и индекс работоспособности корпуса коммутатора

Как человек, который любит следовать лучшим практикам,

Если я запустил метрики кода (щелкните правой кнопкой мыши по имени проекта в проводнике решений и выберите "Рассчитать метрики кода" - 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

(конечно, это незначительно, если у вас есть только это, но если вы используете такую ​​утилиту, как философия класса, которая делает такие вещи, ваш класс полезности будет иметь индекс работоспособности намного хуже).

Какое решение для этого?

Ответ 1

Прежде всего: 61 считается поддерживаемым кодом. Для Индекса работоспособности 100 очень просто поддерживать код, а 0 трудно поддерживать.

  • 0-9 = трудно поддерживать
  • 10-19 = умеренный, чтобы поддерживать
  • 20-100 = хорошо поддерживать

Индекс работоспособности основан на трех показателях кода: именно Halstead Volumen, Cyclomatic Complexity и Lines of Code и на основе следующей формулы:

MAX (0, (171 - 5.2 * ln (Halstead Объем) - 0,23 * (Цикломатический Сложность) - 16,2 * ln (Линии Код)) * 100/171)

Фактически, в вашем примере основной причиной низкого значения индекса работоспособности является Cyclomatic Complexity. Эта метрика рассчитывается на основе различных путей выполнения кода. К сожалению, метрика не обязательно соответствует "удобочитаемости" кода.

Примеры, так как ваш код приводит к очень низким значениям индекса (помните, что более низкие средства сложнее поддерживать), но на самом деле их очень легко читать. Это часто встречается при использовании Cyclomatic Complexity для оценки кода.

Представьте код, в котором есть блок-переключатель для дней (Mon-Sun) плюс блок-переключатель для месяцев (январь-декабрь). Этот код будет очень читабельным и поддерживаемым, но приведет к огромной Cyclomatic Complexity и, следовательно, к очень низкому индексу работоспособности в Visual Studio 2010.

Это хорошо известный факт о метрике и должен рассматриваться, если код оценивается на основе цифр. Вместо того, чтобы смотреть на абсолютное число, цифры должны отслеживаться со временем, чтобы понять как показатель изменения кода. Например. если индекс работоспособности всегда находился на уровне 100 и внезапно уменьшался до 10, вы должны проверить изменения, вызвавшие это.

Ответ 2

Индекс ремонтопригодности может быть выше из-за отсутствия возможности расширения в методе, который вы выбираете для своего решения.

Правильное решение (Mark Simpson, затронутое выше) - это тот, который может быть расширен, чтобы использовать новый форм-фактор без перепрограммирования кода. Операторы switch/case в коде всегда являются признаком того, что дизайн OO был забыт и должен всегда воспринимается как плохой запах кода.

Лично я бы выполнил...

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 должным образом), поскольку это легко насмехаться.

Ответ 3

Я знаю, что этот ответ очень поздний, но мне было интересно, что никто не предложил словарное решение. Я обнаружил, что, когда речь идет о огромных операторах switch, которые ориентированы на данные, как это, часто более читаемо, чтобы свернуть случай переключения в словарь.

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 - немного ниже, чем решение массива из-за сочетания класса со словарем, но я считаю его более общим, потому что он работает для любого количества типов, которые вы обычно включаете. Как и решение массива, он очень хорошо масштабируется и удаляет много повторяющегося кода.

Вообще говоря, использование подхода, основанного на данных, может помочь вашему коду быть более четким, поскольку он отделяет важные фрагменты (в данном случае, условие и результат) от крутильного (в данном случае случая переключения).

Ответ 4

Две вещи spring:

Используйте перечисление, чтобы выйти замуж за описание и значение

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
    }
}

Ответ 5

Я сделал бы это так и забуду индекс работоспособности:

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();
}

IMHO легко читается и легко меняется.

Ответ 6

Я не знаю, насколько это важно, но следующее получает 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];
}

Ответ 7

Очевидно, что метод Enum наиболее удобен в обслуживании, так как он не включает жестко закодированные строки, поэтому нет проблемы с опечатками и проверки синтаксиса времени компиляции. Только ограничения - это правила именования.