Метрики кода Visual Studio и индекс ремонтопригодности коммутатора - PullRequest
10 голосов
/ 30 мая 2010

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

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

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

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

Ответы [ 7 ]

26 голосов
/ 21 июня 2010

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

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

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

MAX (0, (171 - 5,2 * ln (Холстед) Объем) - 0,23 * (Cyclomatic Сложность) - 16,2 * ln (Линии Код)) * 100/171)

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

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

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

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

5 голосов
/ 28 октября 2011

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

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

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

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 голосов
/ 28 мая 2014

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

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

Это дает вам индекс Maintainability, равный 74 - немного ниже, чем решение для массива из-за связи классов со словарем, но я чувствую, что он более общий, потому что он работает для любого числа типов, которые вы обычно включаете. Как и решение с массивами, оно очень хорошо масштабируется и удаляет много повторяющегося кода.

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

2 голосов
/ 30 мая 2010

Я бы сделал это так и забыл бы индекс обслуживания:

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

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

2 голосов
/ 30 мая 2010

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

Используйте enum для объединения описания и значения

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
    }
}
0 голосов
/ 23 сентября 2010

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

0 голосов
/ 30 мая 2010

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