Почему инициализация списка с помощью лямбда вызывает высокую цикломатическую сложность?

Инициализация списка лямбда-выражениями вызывает высокую цикломатическую сложность IL: почему и как устранить эту сложность? Например, следующий код приводит к тому, что статический конструктор класса (который на самом деле создается компилятором) становится очень сложным: 1 + счетчик списка.

static List<Predicate<string>> list = new List<Predicate<string>>()
{
    s => s == null,
    s=> s.StartsWith(“R”),
    ... With a lot of predicates like that ….
};

Примечание: сложность вычисляется с помощью NDepend


person sthiers    schedule 26.10.2010    source источник


Ответы (1)


Почему? Поскольку ILCC определяется как количество различных пунктов назначения перехода/ответвления. Этот список, который вы инициализируете, содержит много логики if/then, содержащейся в лямбда-выражениях. Я предполагаю, что зависимый от языка CC ниже?

Высокая цикломатическая сложность — это всего лишь намек на то, что ваши функции чрезмерно сложны , и поэтому его трудно понять, поддерживать и тестировать. Правилен ли этот намек в данном случае, будет зависеть от того, как вы используете этот список предикатов. Но это всего лишь намек. Поддержание CC на низком уровне не следует рассматривать как закон природы. Если вы считаете, что код можно поддерживать и тестировать, обратите внимание на высокий уровень ILCC в документации, объясните, почему это не имеет значения, и двигайтесь дальше.

person Pontus Gagge    schedule 26.10.2010
comment
На самом деле, если я декомпилирую код и хорошо разбираюсь в IL (я в этом плохо разбираюсь), кажется, что лямбда-выражения генерируются отдельно. Ветви больше похожи на артефакт генерации кода компилятора. - person sthiers; 26.10.2010
comment
Возможно, вы могли бы добавить краткую выдержку из декомпилированного IL для нас, кому лень бежать в VS. Я удивлен, если лямбда-выражения на самом деле не генерируются в момент статической инициализации, чтобы учитывать сложность статического конструктора. - person Pontus Gagge; 26.10.2010
comment
L_0008: класс ldsfld Predicate1<string> Foo.Class1::CS$<>9__CachedAnonymousMethodDelegate12 L_000d: brtrue.s L_0022 L_000f: ldnull L_0010: ldftn bool Foo.Class1::<FooFunction>b__0(string) L_0016: newobj instance void [mscorlib]Predicate1‹string›::.ctor(object, native int) L_001b: класс stsfld [mscorlib]Predicate1<string> Foo.Class1::CS$<>9__CachedAnonymousMethodDelegate12 L_0020: br.s L_0022 L_0022: ldsfld class Predicate1‹string› Foo.Class1::CS$‹›9__CachedAnonymousMethodDelegate12 L_0027: callvirt instance void Generic.List1<class [mscorlib]Predicate1‹string› ›::Добавить(!0) - person sthiers; 26.10.2010
comment
Трудно сказать наверняка без более полных документов от NDepend (или их исходного кода!), но кажется довольно очевидным, что они подсчитывают содержимое IL анонимных делегатов (будь то из лямбда-выражений или написанных иначе) в сравнении со сложностью их метода ссылки для ILCC. . Что кажется естественным: в конце концов, внутри лямбда-выражений можно спрятать множество условных предложений и альтернативных путей выполнения кода. В конце концов, существует множество способов использования лямбда-выражений для усложнения кода! - person Pontus Gagge; 26.10.2010
comment
Да, я понимаю базовую идею, НО: если я усложню лямбду, это не изменит ILCC. На самом деле ILCC зависит только от количества лямбда. Что согласуется с тем, что я понял из сгенерированного IL: ветвление здесь только для проверки ненулевого значения лямбда, независимо от внутренностей лямбды. Кажется возможным создать сложный код с лямбда-выражениями с низким ILCC! - person sthiers; 02.11.2010
comment
Интересно отметить: я надеюсь, что NDepend учитывает сложности внутри лямбда-выражений где-то... В любом случае, ключевой урок здесь заключается в том, что автоматические измерения являются всего лишь косвенными показателями сложности, а не напрямую измеряют сложность, как это было при тестировании. и техническое обслуживание. Это лучшее, что мы можем сделать, чтобы получить немного объективности. - person Pontus Gagge; 03.11.2010
comment
Что ж, и это, и это, с одной стороны, если что-то сложно по своей сути, и мы можем получить инструмент, который сделает это за нас, мы должны это сделать, но, с другой стороны, инструменты, как правило, не создают особенно читаемый код, если они не разработаны с этой целью. - person Jon Hanna; 31.01.2012