如果您关注我们一段时间,您很可能注意到我们改变了描述我们所做工作的方式:从“代码质量”到“持续代码检查”,然后是“代码质量和代码安全性”……感觉就像在在过去的几年里,我们终于找到了我们从一开始就一直在寻找的东西:干净的代码。
但什么是清洁代码,它包含什么?
我们在Sonar解决的问题是一个大问题,它也有很多影响。我们帮助提高生产力,减少风险和停机时间,并增加代码所有权。我们影响源代码,当然也间接影响软件本身。
过去,在描述我们所做的事情时,我们混合了所有这些描述,导致不一致(在最好的情况下)并且难以将我们社区的各个点连接起来。大约两年前,我们决定解决这个问题,并发起了一项内部计划,以更好地解释我们的工作。
长话短说,我们最终决定了三件事:
我们的重点完全放在代码上,这就是我们应该如何描述我们所做的事情
我们应该关注问题的原因,而不是其潜在的后果
我们将我们所做的事情命名为“清洁代码”
一旦做出这些决定,你就会开始看到“干净的代码”到处出现。问题解决了?不完全的。我们知道我们在做什么和我们的重点,但我们仍然有一个差距:如果我们想继续植根于实际代码而不是后果,我们如何将不符合项分类为干净代码?
因此,我们启动了另一个项目来开发分类法,又称分类法。
干净代码分类法的基础是干净的代码和具有以下属性的代码:一致、有意、适应性强和负责任。
换句话说,每当代码出现问题时,这个问题就会“破坏”这些类别之一。
现在让我们详细回顾一下这四个类别。
代码应该一致并遵循共同的风格。这意味着所有代码,即使随着时间的推移由不同的人处理,也应该具有相似的外观并遵循既定的模式。这种一致性不仅应该适用于特定的代码库,而且最好适用于整个编程语言生态系统。
代码应该格式化。例如,即使您不熟悉 Java 代码,您也可能希望在以下代码中看到一致的缩进。这不是制表符与空格的问题,而是一致性的问题。
不符合要求的代码:
class Foo { public int a; public int b; public void doSomething() { if(something) { doSomethingElse(); } }}
符合代码:
class Foo { public int a; public int b; public void doSomething() { if(something) { doSomethingElse(); } }}
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S1120/java
代码应该是惯用的并且遵循语法约定。例如,在 C++ >= 11 中,类型别名可以通过 或 来声明typedef
,using
但是,对于现代代码,您应该更喜欢后者。
不符合要求的代码:
typedef void (*FunctionPointerType)(int);
符合代码:
using FunctionPointerType = void (*)(int);
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S5416/cfamily
代码应该易于识别。考虑用 C# 编写的代码,其中 PascalCase 用于除参数名称之外的所有标识符。在这种情况下,使用下划线或其他大小写样式来区分标识符中的单词是不可接受的。
不符合要求的代码:
class my_class {...}class SOMEName {...}
符合代码:
class MyClass {...}class SomeName {...}
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S101/csharp
有意的代码读起来就像是用心和细心编写的,以传达其目的。该代码应该是不言自明的,并且只允许一种解释。每条指令都有意义,形式充分,并且简单地传达了其行为。代码不应含糊不清或留下猜测的空间。
代码应该清晰、简单。以这段 Python 代码为例,您会注意到变量 ` message
` 和 ` i
` 被定义但从未被使用。当读者遇到此类情况时,他们可能想知道这是否是一个编码错误,应该执行其他操作,或者是否只是可以安全删除的剩余代码。
不符合要求的代码:
def hello(name): message = "Hello " + name print(name)for i in range(10): foo()
符合代码:
def hello(name): message = "Hello " + name print(message)for _ in range(10): foo()
阅读更多:https ://sonarsource.github.io/rspec/#/rspec/S1481/python
代码应该只包含逻辑上合理的指令。例如,在 JavaScript 中,有“` NaN
”,代表“非数字”。它表示不是有效数字的数字数据类型。` NaN
` 不等于任何值,甚至不等于它本身,这种行为可能会导致意外结果。
不符合要求的代码:
if (a !== NaN) { console.log("this is always logged");}
符合代码:
if (!isNaN(a)) { console.log("a is not NaN");}
阅读更多:https ://sonarsource.github.io/rspec/#/rspec/S2688/javascript
代码应该是完整的。PHP 中的一个例子是安全cookie 的使用。``方法setcookie
允许您创建默认情况下可以通过HTTP传输的cookie,使其内容可读。由于 cookie 通常携带敏感数据,因此确保它们安全传输以实现其预期目的非常重要。您需要传递最后一个参数才能仅启用 HTTPS。
不符合要求的代码:
$value = "sensitive data";setcookie($name, $value, $expire, $path, $domain);
符合代码:
$value = "sensitive data";setcookie($name, $value, $expire, $path, $domain, true);
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S2092/php
代码应该高效,不要不必要地浪费资源。例如,大多数 Linux 包管理器在使用 Docker 时默认创建缓存。除非您记得删除 Dockerfile 中的这些文件,否则它们会增加映像的大小,而不会提供任何附加价值。
不符合要求的代码:
RUN apt-get update \ && apt-get install nginx
符合代码:
RUN apt-get update \ && apt-get install nginx \ && apt-get clean
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S6587/docker
当代码具有适应性时,它会以一种更容易管理和查看代码之间关系的方式进行分段和组织。代码的结构应该能够轻松且自信地演化。它应该简化扩展或重新利用其部件的过程,并鼓励局部更改,而不会造成意想不到的副作用。
代码应该是独特的并尽量减少重复。例如,重复字符串文字会增加更新时出错的风险,因为每次出现的情况都必须单独更改。更好的方法是使用可以从多个位置引用的常量,从而允许在单个位置进行更新。这是一个使用 Ruby 的示例。
不符合要求的代码:
def foo() prepare('action random1') execute('action random1') release('action random1')end
符合代码:
def foo() action1 = 'action random1' prepare(action1) execute(action1) release(action1)end
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S1192/ruby
代码应该有重点,每个单元都有特定且有限的范围。例如,在 Swift 中,最佳实践是将类型(例如类)保存在单独的文件中。这有助于防止单个文件中指令的过度积累或过于复杂。
不符合要求的代码:
class MyViewController: UIViewController { // …}extension MyViewController: UIScrollViewDelegate { // …}class UnrelatedController: UIViewController { // …}
符合代码:
class MyViewController: UIViewController { // …}extension MyViewController: UIScrollViewDelegate { // …}
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S1996/swift
代码应该是模块化的,其中一个关键方面是封装。在面向对象语言中,封装通常涉及将字段设为私有。这样,类保留了对其内部表示细节的控制,并防止代码的其他部分对其内部工作原理有太多了解。
然而,封装有多个级别,即使是微小的改进也会产生影响。例如,如果您使用的是 VB.Net,它允许公开访问字段,那么最好避免使用它们,而应使用属性。属性的工作方式与字段类似,但属于接口的一部分,并且可以被 getter 和 setter 覆盖。
不符合要求的代码:
Class Foo Public Bar = 42End Class
符合代码:
Class Foo Public Property Bar = 42End Class
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S2357/vbnet
代码应包括在进行更改时增强信心的测试。理想情况下,我们应该优先考虑全面的功能测试覆盖率。然而,准确测量它可能具有挑战性。尽管如此,重要的是要确保测试覆盖率不会低到让您担心修改代码。
有一些奇怪的例子,你有一个测试文件夹或测试文件,里面没有实际的测试用例,这可能会误导其他开发人员:https://sonarsource.github.io/rspec/#/rspec/S2187/
还有一些测试被跳过并意外提交的情况,如果不以任何方式跟踪,可能会被忽视: https: //sonarsource.github.io/rspec/#/rspec/S1607/
准则应注意其有关数据的道德义务及其对社会规范的潜在影响。无论是职业职责、提供安心还是倡导包容性,底线是代码不应带来无意中伤害第三方的持续风险。无论开发商是否承担直接责任,这都适用。
代码应避免硬编码秘密。虽然这对于内部应用程序或当您相信源代码是安全的时可能很诱人,但事实是负责任的代码永远不应该存储秘密。如果恶意方访问代码,秘密可能会无意中暴露和被利用。这种风险不仅影响软件本身。它可能会产生深远的影响,影响系统和第三方。
下面是一个使用 Go 的简化示例:
不符合要求的代码:
func connect() { user := "root" password:= "supersecret" url := "login=" + user + "&passwd=" + password}
符合代码:
func connect() { user := getEncryptedUser() password:= getEncryptedPass() url := "login=" + user + "&passwd=" + password}
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S2068/go
代码应该合法。它应该尊重基本的许可和版权法规。它行使创建者的权利并尊重他人许可其代码的权利。
一个常见的例子是公司在其代码文件中强制执行版权标头:
/* * SonarQube, open source software for clean code. * Copyright (C) 2008-2023 SonarSource * mailto:contact AT sonarsource DOT com * * SonarQube is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * SonarQube is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
了解更多:https ://sonarsource.github.io/rspec/#/rspec/S1451/
代码应该是尊重和包容的。应避免使用歧视性或冒犯性语言,并在合适的替代方案传达相同含义时选择包容性术语。
正则表达式可用于跟踪标识符名称和注释,例如:
不符合要求的代码:
Master / SlaveBlacklist / Whitelist
符合代码:
Primary / SecondaryDenylist / Allowlist
了解更多: https: //sonarsource.github.io/rspec/#/rspec/ ?query=naming%20convention
首先,我们对这种分类感觉非常好(顺便说一下,每个类别还细分为子类别)。我们认为这是清洁代码的坚实基础。
现在,我们希望在 Sonar 产品中逐步推出清洁代码的详细定义。从我们对代码中问题进行分类的方式开始。第一步已在 SonarCloud、SonarLint 和 SonarQube 10.2 中提供。
此外,我们将开始对代码不干净时对软件造成的后果进行分类,例如安全性、可靠性、可维护性等。
Copyright © 2022 All Rights Reserved. 地址:上海市浦东新区崮山路538号808 苏ICP123456 XML地图