Метрики кода Visual Studio и индекс ремонтопригодности случая переключения

StackOverflow https://stackoverflow.com/questions/2936814

Вопрос

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

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

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

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

Это было полезно?

Решение

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

  • 0–9 = сложно поддерживать
  • 10-19 = умеренно поддерживать
  • 20-100 = хорошо поддерживать

Индекс ремонтопригодности основан на трех показателях кода:А именно, объем Холстеда, цикломатическая сложность и строки кода, основанные на следующая формула:

MAX(0,(171 - 5.2 * ln(Холстед Объем) - 0,23* (цикломатический Сложность) - 16.2 * ln(Строки Код))*100 / 171)

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

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

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

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

Другие советы

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

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

Лично я бы реализовал...

interface IFormFactor
{
    // some methods
}

class SipFormFactor : IFormFactor...

class DipFormFactor : IFormFactor...

Etc.

... и чтобы методы интерфейса обеспечивали желаемую функциональность - вы можете думать об этом [я думаю] как о похожем на шаблон команды GoF.

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

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

    factor.DoSomething();

    // some more logic...
}

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

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

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

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

На ум приходят две вещи:

Используйте перечисление, чтобы объединить описание и значение.

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

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

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

ИМХО легко читается и легко меняется.

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

Для меня очевидно, что Перечисление Метод является наиболее удобным в обслуживании, поскольку он не использует жестко запрограммированные строки, поэтому нет проблем с опечатками и проверкой синтаксиса во время компиляции.Единственными ограничениями являются правила именования.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top