我有一个跨多个项目的大型源存储库.我想制作一份关于源代码健康状况的报告,找出需要解决的问题领域.
具体来说,我想调出具有高圈复杂度的例程,识别重复,并且可能运行一些类似lint的静态分析来发现可疑(因而可能是错误的)构造.
我该如何构建这样的报告?
我不时看到的一个术语是"Cyclomatic Complexity".在这里,我看到了一些关于"如何计算语言X的CC"或"如何使用最小CC量来做Y"的问题,但我不确定我是否真的理解它是什么.
在NDepend网站上,我看到了一个解释基本上是"方法中的决策数量.每个if,for,&&等等都给CC增加+1"得分.)真的是吗?如果是,为什么是这很糟糕?我可以看到,人们可能希望保持if语句的数量相当低,以保持代码易于理解,但这真的是它的一切吗?
还是有一些更深层的概念呢?
在阅读" 你的/你的圈复杂度有什么限制? "之后,我意识到我的很多同事对我们项目的新QA政策非常恼火:每个功能不再有10个圈复杂度.
含义:不超过10'if','else','try','catch'和其他代码工作流程分支语句.对.正如我在' 你测试私人方法吗?',这样的政策有很多好的副作用.
但是:在我们(200人 - 7年)项目开始时,我们很高兴地记录(不,我们不能轻易地将其委托给某种' 面向方面编程 '的日志方法).
myLogger.info("A String");
myLogger.fine("A more complicated String");
...
Run Code Online (Sandbox Code Playgroud)
当我们的系统的第一个版本上线时,我们遇到了巨大的内存问题,不是因为日志记录(在某一点被关闭),而是因为日志参数(字符串),总是被计算,然后传递给'info()'或'fine()'函数,只是发现日志记录级别为"OFF",并且没有记录日志!
所以QA回来并敦促我们的程序员进行条件记录.总是.
if(myLogger.isLoggable(Level.INFO) { myLogger.info("A String");
if(myLogger.isLoggable(Level.FINE) { myLogger.fine("A more complicated String");
...
Run Code Online (Sandbox Code Playgroud)
但是现在,由于每个功能限制的"无法移动"10个圈复杂度级别,他们认为他们在其功能中放入的各种日志被视为负担,因为每个"if(isLoggable())"是计为+1圈复杂度!
因此,如果一个函数有8'if','else'等等,在一个紧密耦合的不易共享的算法中,以及3个关键的日志操作......它们违反了限制,即使条件日志可能不是真的该功能的复杂性的一部分......
你会如何解决这种情况?
我在项目中看到过几个有趣的编码演变(由于这个'冲突'),但我只是想先了解你的想法.
谢谢你的所有答案.
我必须坚持认为问题不是"格式化"相关,而是"参数评估"相关(评估可能非常昂贵,只是在调用一个什么都不做的方法之前)
所以当写一个上面的"A String"时,我实际上意味着机能缺失(),与机能缺失()返回一个字符串,并且是一个复杂的方法收集的调用和计算所有类型的日志数据被记录器...与否(因此该问题,并显示义务,以使用条件记录,因此人为增加'圈复杂度'的实际问题......)
我现在得到你们中某些人提出的" 可变函数"点(谢谢John).
注意:java6中的快速测试表明我的varargs函数在被调用之前会对其参数进行求值,所以它不能用于函数调用,而是用于'Log Retriever object'(或'function wrapper'),其中toString( )只有在需要时才会被调用.得到它了.
我现在已经发表了关于这个主题的经验.
我会留在那里直到下周二投票,然后我会选择你的一个答案.
再次,谢谢你的所有建议:)
language-agnostic logging coding-style cyclomatic-complexity
我一直在玩测量大代码库的圈复杂度.
循环复杂性是通过程序源代码的线性独立路径的数量,并且有许多免费工具可供您选择的语言.
结果很有趣,但并不令人惊讶.也就是说,我知道最毛茸茸的部分实际上是最复杂的(评级> 50).但我发现有用的是,在决定从哪里开始重构时,我可以指出为每个方法分配一个具体的"坏"数字.
你使用圈复杂度吗?您找到的最复杂的代码是什么?
假设有以下代码:
private static int DoSwitch(string arg)
{
switch (arg)
{
case "a": return 0;
case "b": return 1;
case "c": return 2;
case "d": return 3;
}
return -1;
}
private static Dictionary<string, Func<int>> dict = new Dictionary<string, Func<int>>
{
{"a", () => 0 },
{"b", () => 1 },
{"c", () => 2 },
{"d", () => 3 },
};
private static int DoDictionary(string arg)
{
return dict[arg]();
}
Run Code Online (Sandbox Code Playgroud)
通过迭代这两种方法并进行比较,即使"a","b","c","d"扩展为包含更多键,我也会得到字典稍快一些.为什么会这样?
这与圈复杂度有关吗?是因为抖动只将字典中的return语句编译为本机代码一次?是因为字典的查找是O(1),这可能不是switch语句的情况?(这些只是猜测)
在Javascript中是否有可用于计算Cyclomatic Complexity的工具?
我在使用服务器端代码时发现它是一个非常有用的指标,并且希望能够将它用于我编写的客户端Javascript.
我正在研究可以帮助我编写更小但更复杂的代码的算法.我可以设计一个20行的算法,而不是编写150行if-else语句.问题是很多这些算法都很复杂,需要大量的数学才能理解它们.我也是这里唯一了解他们的人.
为了代码的可维护性,像其他人一样编写代码会更好,还是使用算法更好?
algorithm maintainability cyclomatic-complexity code-complexity
以下代码指标计算的首选分数范围是多少?
c# maintainability cyclomatic-complexity code-metrics visual-studio-2008
大多数编程语言中方法的复杂性可以使用静态源代码分析器在圈复杂度中进行测量.是否有类似的度量标准来衡量SQL查询的复杂性?
它很简单,可以衡量返回查询所需的时间,但如果我只想量化查询的复杂程度呢?
[编辑/注意]虽然获得执行计划很有用,但在这种情况下,这并不一定是我想要识别的.我不是在寻找服务器执行查询的难度,我正在寻找一个指标来确定开发人员编写查询的难度,以及包含缺陷的可能性.
[编辑/注释2]不可否认,有时候测量复杂性没有用,但有时也是如此.有关该主题的进一步讨论,请参阅此问题.
我正在开发一个将RequestDTO发送到Web服务的类.我需要在发送请求之前验证请求.
请求可以从3个不同的地方发送,每个"请求类型"都有不同的验证规则,例如request1必须有名称和phonenumber,request2必须有地址,等等)
我有一个DTO,其中包含很长的字段列表(名称,地址,城市,电话号码等),无论发送哪种类型的请求,它都是相同的DTO.
我创建了3种不同的验证方法,并根据类型调用适当的方法.
在每个方法中,我都有一长串if-else来检查每个请求类型所必需的字段.
private void validateRequest1(Request request) {
StringBuilder sb = new StringBuilder();
if (null == request) {
throw new IllegalArgumentException("Request is null");
}
if (isFieldEmpty(request.getName())) { *see below
sb.append("name,"));
}
if (isFieldEmpty(request.getStreet())) {
sb.append("street,"));
}
...
Run Code Online (Sandbox Code Playgroud)
isFieldEmpty()检查字符串是否为null,isEmpty()并返回一个布尔值
这让我在其中一种方法中的圈复杂度为28,所以我的问题是......是否有可能降低这种复杂性? - 如果是的话,我该怎么做呢?
最终我需要检查很多字段,如果没有大量的检查,我无法看到如何做到这一点:/
c# ×2
code-metrics ×2
metrics ×2
algorithm ×1
architecture ×1
clr ×1
coding-style ×1
dictionary ×1
java ×1
javascript ×1
logging ×1
python ×1
refactoring ×1
sql ×1
validation ×1