LINQ 和 Lambda 表达式是否会降低圈复杂度?
LINQ 和 Lambda 表达式是否会降低圈复杂度? 只是好奇,因为当 VS 分析器增加 cc 时,CodeRush 实际上显示 cc 减少。
Does LINQ and Lambda expressions reduce cyclomatic-complexity? Just curious because CodeRush actually shows a reduction in cc when the VS analyzer increases it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我怀疑这种差异可能是由于延迟执行造成的。 当您将 LINQ 与 lambda 表达式结合使用时,您将指定在您随后迭代该集合时运行的代码。
就我个人而言,我并不那么担心圈复杂度,但我绝对确信(如果使用得当)LINQ 可以提高可读性。 这就是我真正关心的:)
I suspect that the discrepancy may be due to deferred execution. When you use LINQ with lambda expressions, you're specifying code which will be run if you then iterate over the collection.
Personally I'm not so worried about cyclomatic complexity, but I'm absolutely sure that (when used appropriately) LINQ improves readability. That's what I really care about :)
我刚刚遇到了同样的问题,事实上,lambda 可以增加圈复杂度。 我做了测试,Where() 子句可以合理地增加它。
可读性确实是你的首要任务之一。
但是我没花很长时间就替换了一些 LinQ通过 Get() 方法进行查询,这为我提供了相同的数据和额外的好处。
我在构建/发布脚本中保留 Fxcop,因此在圈复杂度达到 25 的目标之前我绝不会部署某些内容。
这很难,但我认为这是值得的。
当我的伙伴提出一个非常糟糕的代码时,这让我在讨论中获得了一些观点:
这有效,这才是最重要的。
我的建议是:将圈复杂度保持在 25 以下。
这可以帮助您保持每种方法足够简单,以便进行良好的维护。
I just came around with the same question and, in fact, lambda can increase the cyclomatic complexity. I did the test and Where() clauses can increase it sensibly.
Readability is indeed one of your top priorities.
But it didn't take me to long to replace some LinQ queries by Get() methods which provided me with the same data and extra benefits.
I keep my Fxcop on in my build/publish script so I never deploy something without reaching the target of 25 for cyclomatic complexity.
It's tough, but I think it's worth the effort.
This grants me some points in discussions when my mates come with a very bad code saying:
this works, that's what matters.
my tip is: keep your cyclomatic complexity below 25.
this may help you to keep every method simple enough for good maintenance.
乔恩·斯基特非常简洁地回答了这个问题。 我想补充一点,根据我使用 C# 等高级语言的经验,测量圈复杂度的价值会降低,因为 LINQ 等语法糖包为开发增加了价值。
在过去的十年里,随着语言的发展,网上的许多人都说明了圈复杂度和代码行之间的紧密相关性,这使得他们中的许多人质疑这种衡量标准实际上带来了多少价值。 另一种看待它的方式是,贬低 CC 作为代码质量的衡量标准实际上是对可读性重要性的断言,因为一个通常是另一个的倒数。
例如,如果我在 foreach 循环中放置一个条件,则该条件将被评估为我的代码,并且会计算适当数量的代码路径。 另一方面,如果我将函数树应用于我正在迭代的集合(例如Where(evalStr => evalStr == origStr)),我会将条件移至循环外部并移至编译器生成的代码中。分支数量仍然相同,但是条件不是循环的一部分,但 CC 的增加超出了 foreach 循环的范围,在实际分支计数之上使用匿名方法(lambda 和委托)会受到“惩罚”。 Where 函数允许我对迭代集合进行预处理,以便循环仅在需要时进行迭代。
代码的可读性无疑会更高。
但是,如果您认为不需要在 LINQ IQueryable 函数中使用布尔表达式,那么 进行单元测试,表面上是因为如果存在异常,它是一个高阶(又名业务级)异常(正在测试错误的值、错误的运算符、错误的操作数等),而不是不太理想的使用语言的(使用 switch 代替 if,if 代替三元等),那么测量圈复杂度应该考虑到这一点:Where() 函数不应该增加我的 CC。 测量圈复杂度无助于编写更好的代码; 如果有的话,它将人为地增加开发人员在不需要或不需要简化的情况下进行简化的倾向。
Jon Skeet pretty much answered the question succinctly. I would like to add that in my experience with high-level languages like C#, the value of measuring cyclomatic complexity is reduced because of the value that syntactic sugar packages like LINQ adds to development.
Over the past ten years, as languages have evolved, many on the net have illustrated a strong correlation between cyclomatic complexity and lines of code, making many of them question just how much value such a measure actually brings. Another way to look at it would be that the devaluation of CC as a measure of code quality is actually an assertion of the importance of readability, as one is often the inverse of the other.
For example, if I put a conditional inside a foreach loop, the conditional is evaluated as my code, and the appropriate number of code paths is counted. On the other hand, if I apply a function tree to the collection I am iterating over (e.g. Where(evalStr => evalStr == origStr) I am moving the conditional to the outside of the loop and into compiler-generated code. There are still the same number of branches, however the conditionals are not part of the loop, yet the CC increases beyond that of the foreach loop, with "penalties" for using anonymous methods (lambdas and delegates) on top of the actual branch count. The Where function lets me precondition the iterated collection so that the loop only iterates if it needs to.
However, the code is far and away more readable.
Finally, if one decides that a Boolean expression used inside a LINQ IQueryable function does not need to be unit tested, ostensibly because if there is an exception, it is a higher-order (a.k.a. business-level) exception (wrong value being tested, wrong operator, wrong operand, etc.) as opposed to a less-than-ideal use of the language (using switch instead of if, if instead of ternary, etc.) then measuring cyclomatic complexity should take this into account: A Where( ) function should not increase my CC. Measuring cyclomatic complexity won't help make better code; if anything, it will artificially increase a developer's tendency to simplify where no simplification may be necessary or desired.