Существуют ли метрики кода, которые будут охватывать область видимости переменных?

При попытке получить общее представление о том, насколько сложно поддерживать некоторый устаревший код C++ и C#, а также о риске внесения в него ошибок, было высказано предположение, что было бы полезно измерить, насколько широко или узко область видимости переменных. В коде используется много глобальных переменных или переменных с широкой областью видимости, тогда как локальные были бы лучше. Обычным случаем является обнаружение того, что эти переменные используются для 2 или 3 строк кода на несколько уровней области видимости от того места, где они объявлены.

Я знаю, что инструменты статического анализа кода обычно пытаются количественно определить связь и связность, но есть ли что-то более конкретное для измерения области действия переменных/данных?


person krm    schedule 15.01.2013    source источник
comment
Я думаю, что это хорошая идея для измерения.   -  person SpaceTrucker    schedule 15.01.2013


Ответы (3)


Да, это стандартная техника статического анализа. Это называется анализом переменной живучести. В этой книги вводный пример делает такие анализ.

Из статьи Википедии об этом:

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

Проще говоря: переменная активна, если она содержит значение, которое может понадобиться в будущем.

person gefei    schedule 15.01.2013
comment
может понадобиться в будущем, не обязательно будет использоваться в будущем. Простой пример: цикл for в стиле C int i; for (i=0; i<10; ++i) meow(i); после этого цикла i равно 10, и это значение может понадобиться. Однако в большинстве случаев он не нужен/не используется. Компилятор сочтет его живым, но если я правильно понимаю karm, он хочет подсказку/предупреждение о том, что область действия i должна быть ограничена циклом for: for (int i = 0; i<10; ++i) meow(i); - person Arne Mertz; 15.01.2013
comment
@ArneMertz: возможно, анализ живучести - неправильный термин для того, о чем я думаю, но, поскольку он основан на анализе потока данных, я полагаю, что в вашем примере i будет оцениваться как мертвый в конце цикла при условии, что нет операций чтения из i между этой точкой и первой безусловной записью в i или концом области i, в зависимости от того, что наступит раньше. Может быть необходимо, учитывает (в меру возможностей анализатора) всю область действия переменной, а не только код, предшествующий точке программы, в которой оценивается ее живучесть. - person Steve Jessop; 15.01.2013
comment
... так, например, если следующим оператором после цикла является puts("foo");, а i мертв, то оптимизатор знает, что ему не нужно сохранять значение i во время вызова, и, возможно, он может сохранить некоторые инструкции и/или пространство стека, как следствие. Это и распределение регистров - это использование живости, с которым я больше всего знаком, и я вижу точку зрения gefei, что это полезно и для этого вопроса. В вашем примере и при условии, что он не используется после того, как цикл i активен только внутри цикла (не до и не после), что является достаточной информацией, чтобы спровоцировать желаемую подсказку, чтобы уменьшить ее объем. - person Steve Jessop; 15.01.2013
comment
Тем не менее, для другого примера int i = 0; ...; for(;i < 10; ++i) (где ... не используется i) требуется немного больше, чем просто определение живости выше, чтобы сделать вывод, что i может быть уменьшен в объеме. Вы также должны обнаружить, что инициализация i может быть отложена вплоть до его первого чтения (конечно, с учетом ветвей, ведущих к условному чтению, но в этом примере их нет). DFA обычно делает то же самое, но я не знаю, называется ли это живостью или чем-то еще. - person Steve Jessop; 15.01.2013

Я сосредоточусь на локальных переменных в объектно-ориентированных языках (Java, C#, C++). Я могу придумать ряд мер, касающихся области действия локальной переменной.

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

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

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

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

person SpaceTrucker    schedule 15.01.2013
comment
Будет сложно поддерживать количество доступных локальных переменных не более 3, все три языка, которые вы цитируете, имеют стандартные методы/функции с более чем 3 параметрами и поэтому не могут быть реализованы с этим ограничением. В С++ параметр явно является локальной переменной, я не уверен, что говорят другие, но параметры также могут быть локальными для выбора имени, которое вы должны использовать в данном выражении. Конечно, это благородная цель, и, вероятно, вы бы пометили эти стандартные функции как опасные, если бы вас попросили проверить дизайн :-) - person Steve Jessop; 15.01.2013
comment
@SteveJessop Я не имел в виду, что это жесткие ограничения. Но я должен признать, что я не думал о параметрах. Так что я думаю, что 5 является более подходящим значением. - person SpaceTrucker; 15.01.2013
comment
Я, конечно, согласен, что это стоит иметь в виду. На практике я бы посмотрел на функции, которые мне нравятся, и функции, которые я ненавижу, и попытался бы выделить из них ориентировочное значение. Это может варьироваться для разных типов компонентов, так как иногда вы хотите, чтобы код был немного корявым, а иногда вы хотите, чтобы все было очень просто. - person Steve Jessop; 15.01.2013

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

from f in Fields where f.IsGlobal && f.MethodsUsingMe.Count()==1 select f
person James from CppDepend Team    schedule 05.07.2017