美文网首页
Go语言中常见100问题-#2 减少代码的嵌套层数

Go语言中常见100问题-#2 减少代码的嵌套层数

作者: 数据小冰 | 来源:发表于2024-02-24 17:10 被阅读0次

减少代码的嵌套层数

软件开发中的“心智模型”用于描述开发人员在编码时心理活动,每段代码其实是人在编写这段代码时的心智模型投射,不能把代码看成是客观的存在,而是主观的产物,参合了当时心理活动或各种直觉感知。在编程时,必须不断维护心智模型,例如关于整体代码交互和功能实现的心智模型,代码是否具有可读性,代码风格,变量命名规范等。可读性强的代码需要的心智模型更简单,更容易阅读和维护。

代码嵌套层级的数量是影响可读性的一个关键因素,假设正在一个新项目上进行开发工作,并且需要读懂下面join函数实现的功能。此join函数实现的功能是将两个字符连接起来,如果连接起来的字符串超过给定的长度max,则返回前max个字符的子串。在处理的过程中,对参数进行检查并判断concatenate是否有返回错误。

func join(s1, s2 string, max int) (string, error) {
        if s1 == "" {
                return "", errors.New("s1 is empty")
        } else {
                if s2 == "" {
                        return "", errors.New("s2 is empty")
                } else {
                        concat, err := concatenate(s1, s2)
                        if err != nil {
                                return "", err
                        } else {
                                if len(concat) > max {
                                        return concat[:max], nil
                                } else {
                                        return concat, nil
                                }
                        }
                }
        }
}

func concatenate(s1 string, s2 string) (string, error) {
        // ...
}

从功能实现的角度来看,上述函数是正确的。然而,建立一个涵盖所有不同输入参数情况的心智模型可能不是一项简单的任务。为啥呢?由于代码嵌套的数量层级过多。现在,对上面的代码进行重构,得到新的实现如下。

func join(s1, s2 string, max int) (string, error) {
        if s1 == "" {
                return "", errors.New("s1 is empty")
        }
        if s2 == "" {
                return "", errors.New("s2 is empty")
        }
        concat, err := concatenate(s1, s2)
        if err != nil {
                return "", err
        }
        if len(concat) > max {
                return concat[:max], nil
        }
        return concat, nil
}

func concatenate(s1 string, s2 string) (string, error) {
        // ...
}

对比这两种实现,虽然功能一样,但是阅读这个新版本的心智模型需要的认知负荷更少,因为新版实现中函数嵌套层级更少。正如Mat Ryer(Go Time播客小组成员)所说:

将正常情况逻辑(happy path)向左对齐,阅读时能够快速向下扫描一列可以查看预期的执行流程。

由于存在嵌套的if/else语句,很难看出重构前版本中的预期执行流程。相反,重构后的版本眼睛只需向下扫描一列便可知道预期的执行流程,通过第二列了解各种特殊情况的处理逻辑。

2_1.jpg

一般来说,函数需要的嵌套层数越多,阅读和理解就越复杂。下面来看看如何使用这条规则优化代码的可读性。

  • 当if语句在满足和不满足都有逻辑处理时,我们应该省略else语句块,不应该像下面这样写.
if foo() {
        // ...
        return true
} else {
        // ...
}

而应该像下面这样写,将else语句省略掉,并将else语句块中的逻辑移动到顶层,使其更易于阅读。

if foo() {
        return true
}
// ...
  • 对于像下面这种if语句是一条non-happy路径,可以通过改变比较条件来减少代码块数量。
if s != "" {
        // ...
} else {
        return errors.New("empty string")
}

上面s为空是一个non-happy路径,我们可以通过翻转条件,得到如下实现。下面这种实现就更容易阅读,因为它将快乐路径放在了左边并减少了代码块的数量。

if s == "" {
        return errors.New("empty string")
}
// ...

编写可读的代码对每个开发人员来说都是一项重要的挑战,努力减少代码块嵌套的层级数量,将快乐路径对齐放在左侧,并尽早返回是提高代码可读性的具体手段,在工作中,我们应该应用这些手段。

相关文章

  • go fmt与gofmt命令

    go fmt命令会按照Go语言代码规范格式化指定代码包中的所有Go语言源码文件的代码,所有Go语言源码文件即包括命...

  • GO 反射

    虽然在大多数的应用和服务中并不常见,但是很多框架都依赖 Go 语言的反射机制简化代码。因为 Go 语言的语法元素很...

  • go arm 交叉编译

    一、纯GO语言代码 1. 设置 GOARCH export GOARCH=arm 2. 编译go 代码 go bu...

  • 上传多文件及数据安卓端及go语言后台端接收

    1. android端代码 2. Go语言后端代码

  • Go语言之结构体嵌套

    Go语言之结构体嵌套 在type Student2 struct结构体中,注意book参数引用的是地址,方便修改数据

  • Go 语言程序设计(5)

    polar2cartesian.go 示例代码: 知识点: Go 语言的并发依赖的并不是线程,而是协程 Go 语言...

  • go变量分配在栈上还是堆上

    一个问题引发的思考?如下go语言代码 编译运行: $ go build main.go && ./main 竟然没...

  • golang读取stdin

    go语言读取stdin内容代码例子 go程序代码 调用脚本1 运行结果 调用脚本2 运行结果

  • Sass日常使用(1)

    Sass 是对 css的扩展,让 css 语言更强大、具有逻辑并且可以减少代码的冗余。 它允许使用变量、嵌套、函数...

  • Flutter UI代码优化

        Flutter发布到现在最让人吐槽的就是它的布局嵌套的写法,复杂布局嵌套层数多,导致代码阅读困难。其实如安...

网友评论

      本文标题:Go语言中常见100问题-#2 减少代码的嵌套层数

      本文链接:https://www.haomeiwen.com/subject/pnroadtx.html