在上一个有关与可读性相关的简单性的问题中,有很多答案可以帮助我看到我对代码简单性的定义和理解是不正确的。
如何定义代码的简单性?哪些软件度量和指标可用于度量代码的简单性?
在上一个有关与可读性相关的简单性的问题中,有很多答案可以帮助我看到我对代码简单性的定义和理解是不正确的。
如何定义代码的简单性?哪些软件度量和指标可用于度量代码的简单性?
Answers:
衡量复杂性(或简单性,如果您认为简单性与复杂性相反)的最常见指标是McCabe的Cyclomatic Complexity和Halstead复杂性指标。
循环复杂度衡量通过给定单元(通常是方法或函数)的不同路径的数量,尽管也可以在类上进行计算。随着路径数量的增加,记住通过给定模块的数据流变得更加困难,这与工作内存的概念有关。较高的圈复杂度往往表明测试模块的能力很困难-需要更多的测试用例才能涵盖通过系统的各种路径。也有研究将高复杂度与高缺陷率联系在一起。通常,圈复杂度为10表示应检查某个单元并可能对其进行重构。
Halstead复杂度度量使用总计和不同的运算符和操作数的输入来计算一段代码的数量,难度和工作量。难度((唯一运算符的数量/ 2)*(操作数的总数/唯一操作数的数量)与读取和理解代码(例如学习系统或执行代码检查)的能力有关。同样,您可以在系统级别,类级别或方法/函数级别进行计数。这里和这里都有一些关于计算这些度量的信息。
只需对代码行进行计数也可以使您了解复杂性。更多的代码行意味着在模块中有更多的阅读和理解。我不愿意将其用作独立测量。相反,我将其与其他度量结合使用,例如给定模块中的缺陷数量以获取缺陷密度。较高的缺陷密度可能表示编写测试和执行代码检查时出现问题,这些问题可能是也可能不是由复杂的代码引起的。
扇入和扇出是另外两个与数据流相关的指标。作为定义在这里,风扇是的程序调用,参数读取的总和,和全局变量读取和扇出是调用一个给定的程序程序的总和,写入参数(暴露给外部用户,在按引用传递)和写入的全局变量。同样,高扇入和扇出可能表示可能难以理解的模块。
在特定的范例中,可能还有其他有用的度量或指标。例如,在面向对象的世界中,可以使用监视耦合(期望低),内聚性(期望高)和继承深度(期望低)来评估系统的简单程度。
当然,重要的是要意识到很多度量和指标只是指标。您需要使用判断力来确定是否有必要进行重构以提高简单性,或者这样做是否值得。您可以进行测量,计算指标并了解代码,但是您不想根据数字来设计系统。最终,做有意义的事情。
我不想看定义简单性的正式模式,而是想将简单性定义为代码编写质量的一个属性。
我不是在说简单性,而是在什么时候称呼简单与否。
1.代码遍历:
浏览代码有多容易?是否容易发现API函数的编写位置?是否容易理解调用流程,例如哪些方法正在调用其他方法(以及为什么)-是否实施了良好的状态机或明确标识的算法?
当代码遍历很容易时,代码很容易遵循。
2.命名
尽管其他编码标准有助于使代码看起来更简洁-最重要的是类/对象实例/变量/方法的命名。在使用清晰明确的名称显然是对很大的影响简单的代码。如果很难识别一个简单的名称,则表明您可能需要重新考虑该变量/方法的想法。
3.解释和引用
您的每个方法是否都有明确的作用。每个变量/属性是否易于确定它们所扮演的角色?当一段代码执行隐含假设或影响无关变量集的操作时,可能会成为维护的噩梦。
4.依赖或耦合
这很难仅通过查看代码来判断,但是如果有人试图修复您的错误,这一点就很明显。当其他对象中的某些其他事物发生变化时,此处的操作是否发生变化?这些变化明显吗?您是否需要经常更改API来容纳东西。这些表明模块间的关系并不简单
5.输入用户或应用程序
最后,在API / UI上接受用户输入或应用程序有多简单?当多个可能的用户/应用程序(出于不同目的)需要给您时-它们明显吗?是否存在与较高抽象无关的状态/细节,但仍然从接口向前/向后前进?
我通常会问一个简单的问题:如果不是程序,而是要求人类执行相同的功能,我是否会将这些信息填写在纸上?如果没有,我在这里还不够简单。
我不会说这个列表是详尽无遗的,但是我想我的标准是使用和修改软件有多容易或有多困难。那很简单。
我不了解任何现有的简单代码度量标准(这并不意味着它们不存在-只是我不知道它们)。我可以提出一些建议,也许会有帮助:
使用的语言功能的简单性:如果语言具有可以被视为“高级”和“简单”的功能,则可以计算高级功能的出现次数。您如何定义“高级”可能会更加主观。我想有些人可能会说这就像衡量程序的“聪明度”一样。一个常见的例子:有些人可能说?:
操作员应该是“高级”功能,而另一些人可能会不同意。我不知道编写一个可以对此进行测试的工具有多么容易。
程序中结构的简单性:您可以测量函数将接受的参数数量。如果你有> ň与>所有功能%米的参数,你可以选择就当没有简单的,这取决于你如何定义ñ和米(也许N = 3和M = 6?)。我认为有一些静态分析工具可以测量此结果-我认为JTest可以简单地测量具有> m个参数的函数。
您可以尝试计算嵌套循环或控件结构的数量。我认为这实际上不是一个坏指标,并且我想它有个名字(我想不起来了)。再次,我认为有些工具(再次类似于JTest)可以在一定程度上衡量这一点。
您可以尝试测量“重构性”。如果你的代码中包含大量的代码块可以进行重构,但都没有,也许这将可能不会简单。我还记得从我与JTest一起工作时起,它也尝试测量这一点,但是我记得在这种情况下我并不经常同意它,所以YMMV。
您可以尝试测量系统不同部分之间的层数。例如:在将Web表单中的数据存储到数据库之前,将触摸多少不同的代码段?要正确衡量这可能是一个棘手的问题...
?:
当它们嵌套5深时,它们就是一个问题。至于层,干净分离的层要好于一个回旋层。但是7个大部分为冗余的层(当只需要2或3个层时)是一件坏事。