欢迎访问Sonar Source中文网站!
语言选择: ∷ 

SonarQube:什么是干净代码?

发布时间:2024-03-01浏览次数:30

如果您关注我们一段时间,您很可能注意到我们改变了描述我们所做工作的方式:从“代码质量”到“持续代码检查”,然后是“代码质量和代码安全性”……感觉就像在在过去的几年里,我们终于找到了我们从一开始就一直在寻找的东西:干净的代码。 


但什么是清洁代码,它包含什么?

这是关于原因和(干净的)代码

我们在Sonar解决的问题是一个大问题,它也有很多影响。我们帮助提高生产力,减少风险和停机时间,并增加代码所有权。我们影响源代码,当然也间接影响软件本身。 


过去,在描述我们所做的事情时,我们混合了所有这些描述,导致不一致(在最好的情况下)并且难以将我们社区的各个点连接起来。大约两年前,我们决定解决这个问题,并发起了一项内部计划,以更好地解释我们的工作。 


长话短说,我们最终决定了三件事:

  1. 我们的重点完全放在代码上,这就是我们应该如何描述我们所做的事情

  2. 我们应该关注问题的原因,而不是其潜在的后果

  3. 我们将我们所做的事情命名为“清洁代码”


一旦做出这些决定,你就会开始看到“干净的代码”到处出现。问题解决了?不完全的。我们知道我们在做什么和我们的重点,但我们仍然有一个差距:如果我们想继续植根于实际代码而不是后果,我们如何将不符合项分类为干净代码?


因此,我们启动了另一个项目来开发分类法,又称分类法。

干净代码分类法

干净代码分类法的基础是干净的代码和具有以下属性的代码:一致、有意、适应性强和负责任。


换句话说,每当代码出现问题时,这个问题就会“破坏”这些类别之一。


现在让我们详细回顾一下这四个类别。

持续的

代码应该一致并遵循共同的风格。这意味着所有代码,即使随着时间的推移由不同的人处理,也应该具有相似的外观并遵循既定的模式。这种一致性不仅应该适用于特定的代码库,而且最好适用于整个编程语言生态系统。

示例1:

代码应该格式化。例如,即使您不熟悉 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

示例2:

代码应该是惯用的并且遵循语法约定。例如,在 C++ >= 11 中,类型别名可以通过 或 来声明typedefusing但是,对于现代代码,您应该更喜欢后者。


不符合要求的代码:

typedef void (*FunctionPointerType)(int);

符合代码:

using FunctionPointerType = void (*)(int);

了解更多:https ://sonarsource.github.io/rspec/#/rspec/S5416/cfamily

示例3:

代码应该易于识别。考虑用 C# 编写的代码,其中 PascalCase 用于除参数名称之外的所有标识符。在这种情况下,使用下划线或其他大小写样式来区分标识符中的单词是不可接受的。


不符合要求的代码:

class my_class {...}class SOMEName {...}

符合代码:

class MyClass {...}class SomeName {...}

了解更多:https ://sonarsource.github.io/rspec/#/rspec/S101/csharp

故意的

有意的代码读起来就像是用心和细心编写的,以传达其目的。该代码应该是不言自明的,并且只允许一种解释。每条指令都有意义,形式充分,并且简单地传达了其行为。代码不应含糊不清或留下猜测的空间。

示例1:

代码应该清晰、简单。以这段 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

示例2:

代码应该只包含逻辑上合理的指令。例如,在 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

示例3:

代码应该是完整的。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

示例4:

代码应该高效,不要不必要地浪费资源。例如,大多数 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

适应性强

当代码具有适应性时,它会以一种更容易管理和查看代码之间关系的方式进行分段和组织。代码的结构应该能够轻松且自信地演化。它应该简化扩展或重新利用其部件的过程,并鼓励局部更改,而不会造成意想不到的副作用。

示例1:

代码应该是独特的并尽量减少重复。例如,重复字符串文字会增加更新时出错的风险,因为每次出现的情况都必须单独更改。更好的方法是使用可以从多个位置引用的常量,从而允许在单个位置进行更新。这是一个使用 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

示例2:

代码应该有重点,每个单元都有特定且有限的范围。例如,在 Swift 中,最佳实践是将类型(例如类)保存在单独的文件中。这有助于防止单个文件中指令的过度积累或过于复杂。


不符合要求的代码:

class MyViewController: UIViewController {  // …}extension MyViewController: UIScrollViewDelegate {
  // …}class UnrelatedController: UIViewController {  // …}

符合代码:

class MyViewController: UIViewController {  // …}extension MyViewController: UIScrollViewDelegate {
  // …}

了解更多:https ://sonarsource.github.io/rspec/#/rspec/S1996/swift

示例3:

代码应该是模块化的,其中一个关键方面是封装。在面向对象语言中,封装通常涉及将字段设为私有。这样,类保留了对其内部表示细节的控制,并防止代码的其他部分对其内部工作原理有太多了解。


然而,封装有多个级别,即使是微小的改进也会产生影响。例如,如果您使用的是 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

示例4:

代码应包括在进行更改时增强信心的测试。理想情况下,我们应该优先考虑全面的功能测试覆盖率。然而,准确测量它可能具有挑战性。尽管如此,重要的是要确保测试覆盖率不会低到让您担心修改代码。


有一些奇怪的例子,你有一个测试文件夹或测试文件,里面没有实际的测试用例,这可能会误导其他开发人员:https://sonarsource.github.io/rspec/#/rspec/S2187/

还有一些测试被跳过并意外提交的情况,如果不以任何方式跟踪,可能会被忽视: https: //sonarsource.github.io/rspec/#/rspec/S1607/

负责任的

准则应注意其有关数据的道德义务及其对社会规范的潜在影响。无论是职业职责、提供安心还是倡导包容性,底线是代码不应带来无意中伤害第三方的持续风险。无论开发商是否承担直接责任,这都适用。

示例1:

代码应避免硬编码秘密。虽然这对于内部应用程序或当您相信源代码是安全的时可能很诱人,但事实是负责任的代码永远不应该存储秘密。如果恶意方访问代码,秘密可能会无意中暴露和被利用。这种风险不仅影响软件本身。它可能会产生深远的影响,影响系统和第三方。


下面是一个使用 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

示例2:

代码应该合法。它应该尊重基本的许可和版权法规。它行使创建者的权利并尊重他人许可其代码的权利。


一个常见的例子是公司在其代码文件中强制执行版权标头:

/*
 * 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/

示例3:

代码应该是尊重和包容的。应避免使用歧视性或冒犯性语言,并在合适的替代方案传达相同含义时选择包容性术语。


正则表达式可用于跟踪标识符名称和注释,例如:


不符合要求的代码:

Master / SlaveBlacklist / Whitelist

符合代码:

Primary / SecondaryDenylist / Allowlist

了解更多: https: //sonarsource.github.io/rspec/#/rspec/ ?query=naming%20convention

那又怎么样?

首先,我们对这种分类感觉非常好(顺便说一下,每个类别还细分为子类别)。我们认为这是清洁代码的坚实基础。 


现在,我们希望在 Sonar 产品中逐步推出清洁代码的详细定义。从我们对代码中问题进行分类的方式开始。第一步已在 SonarCloud、SonarLint 和 SonarQube 10.2 中提供。


此外,我们将开始对代码不干净时对软件造成的后果进行分类,例如安全性、可靠性、可维护性等。


微信扫码微信扫码 关注我们

  • 24小时咨询热线180-210-69380

  • 移动电话180-210-69380

Copyright © 2022 All Rights Reserved. 地址:上海市浦东新区崮山路538号808 苏ICP123456 XML地图