Статьи

Давайте построим метрику: использование CQLinq для рассуждения о состоянии приложения

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

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

SecondsVsCyclomaticComplexity

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

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

Кроме того, одна из вещей, которые мне нравятся в NDepend — это то, что он позволяет мне относительно научиться подходу к коду. У меня постоянно возникают вопросы о характере и структуре кода, и NDepend предоставляет отличную основу для быстрого получения ответов. Я фактически превратил это в приятный компонент моей консалтинговой работы — профессиональную оценку баз кода и поиск пробелов, которые можно оценить.

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

  • Понимание методов, которые ссылаются на поля класса, занимает больше времени, чем чисто функциональные методы.
  • Время на осмысление значительно увеличивается благодаря обращению к глобальным переменным / состоянию.

Если я критически посмотрю на эти прогнозы, то здесь будут два ключевых компонента: масштаб и популярность. Под областью я подразумеваю «насколько близко к методу определена эта вещь?» Это локальная переменная, определенная прямо в методе? Это поле класса, которое я должен прокрутить вверх, чтобы найти определение? Это определено где-то в другом файле (или даже в какой-то другой сборке)? Можно было бы предположить, что необходимость приостановить чтение метода, перейти к другому файлу, открыть его и прочитать, чтобы найти определение переменной, означало бы резкий скачок времени для понимания по сравнению с целым числом, объявленным в первой строке метода.

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

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

// Method fields and parameters used
JustMyCode.Methods.Select(
m => new 
  { 
    m,
    Parameters = m.NbParameters,    
    FieldsUsed = m.FieldsUsed.Count(),
    FieldsAssigned = m.FieldsReadButNotAssigned.Count()
  }
)

Если ваша реакция похожа на мою в первый раз, когда я столкнулся с этим, вы, вероятно, думаете: « Вы можете сделать ЭТО ?! «Да, вы уверены, что можете. Вот как это выглядит на фоне конкретного метода в моей базе кода Chess TDD .

MethodFieldsAndParametersResults

Выделенный выше конструктор показан здесь:

BoardConstructor

Как видите, он имеет один параметр, использует два поля и назначает оба этих поля.

Когда вы просто просматриваете готовые метрики, поставляемые с NDepend, это не те вещи, которые вы сразу замечаете. То, к чему тяготеет большинство людей, — это очевидные метрики, такие как размер метода, цикломатическая сложность и охват тестами. Но под капотом в мире CQLinq есть так много вопросов, на которые вы можете ответить по поводу кодовой базы.

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

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