作为一名程序员,如何写出一手让同事膜拜的漂亮代码?

news/2024/12/14 21:13:53/
  • 整洁的代码

  • 有意义的命名

    • 函数命名

    • 变量命名

  • 函数的定义

  • 注释的规范

  • 代码的长度

  • 代码的对齐

我写代码已经有好几年了,最近看了一本书叫做《代码整洁之道》。我发现这本书中介绍的一些内容对我来说非常有启发性。书中提到的一些方法和技巧让我重新审视了自己的代码风格,让我更加注重代码的可读性和可维护性。例如,书中提到了如何给变量和函数命名,编写注释和文档,以及如何避免代码重复等等。这些技巧和方法都非常实用,我会在今后的编程工作中尽可能地应用它们来提高我的代码质量。 

整洁的代码

来让我们思考一个问题,什么样的代码才算是好代码?

关于这一点我大概整理了一些自己的看法,罗列了之后如下所示:

准确性

可以通过测试用例,满足具体应用场景。

简介性

没有重复性的代码,简洁明了,没有过多的繁琐类的封装,函数,方法。

看到这里,你可能会想,说起来很能理解,但是实际工作中又该如何注意呢?别急,我们来看下边这个反面案例:

 

这段代码是早期我在工作时所写的一段支付代码,在进行支付之前,先判断购物车里的商品库存是否充足,如果充足则进行扣减操作。但是现在回过头来看这段代码,你就会发现存在一些问题。

  • 代码优化分析 首先上边的代码在业务含义上并没有什么的问题,不过我们可以在代码的精炼程度 上进行一些优化。

对于参数校验,购物车校验,库存校验 ,其实我们都可以加入一些类似于断言组件之类的设计进行优化。

另外一些对象构建的代码其实可以做一些封装,因为调用这个接口的同事大多数时候都不会太愿意去关心这些参数的构造过程,更多时候我们只需要将它封装起来,然后通过一个函数的名字来告诉使用者就可以了。

进行优化之后的代码可以变成如下所示:

有意义的命名

函数命名

有的时候,我们对于函数的命名会有出现“名不副其实”的情况,例如下边这个案例:

 

这段代码中,返回的类型是Map类型,但是函数的命名却以List结尾,这样就给人有误解的意思。如果函数的名字没法给人很好的易读性,就需要开发者再花费额外的时间趣深入理解,这就会显得很费劲。再看下边这个案例: 

在这个函数里面,会自动生成一个随机数组,但是数字的值如果是负数,则会自动变为0。但是为什么我们不在函数命名中进行定义呢?例如定义命名为:getNonnegativeArr(int len), 这样不是更好理解函数的意思嘛。

变量命名

对于函数变量的命名不要使用0或者o,1或者l很容易让人看混,另外变量或者参数的命名也尽量使其具有意义,例如下边这个案例所示:

 

例如这个案例中,参数命名采用了list1,list2,就很让人容易误解,不知道哪个参数是源集合,哪个参数是需要被比较的子集合。如果我们对它进行一些优化,看起来的效果就会明显不同,例如: 

使用好的变量命名可以让人清晰了解到这个变量的类型是什么样的,另外在定义一些具有特殊含义的变量时候可以结合下具体的业务场景。例如下边这段代码,需要分别计算工作日 和 周末的订单流水金额总数, 

其实在这里我们可以赋予一个特殊的业务命名来表示,例如下边这样的写法: 

相对于上边的变量i,j写法,这种具有业务含义的变量命名更加能让人明确它的具体含义。

函数的定义

函数的命名

函数的命名尽量保证一个函数只做一件事的原则,不要参杂过多的其他业务操作。

函数的参数个数

通常参数的个数建议最多设置在3个左右,如果参数过多容易让人看了有误解,此时可以尝试用一些类去进行封装。

函数的参数命名

对于有共同含义的参数,我们可以将它命名到同一个变量中,这样能够通过业务领域去定义他们,方便识别。

对于参数的命名可以结合一些工作术语,例如当我们需要定义一个队列参数的时候可以定义JobQueue。

再来看下边这个案例,我们定义了一个用户基础属性类:

 

在这个案例中的name,number,street,city字段分别表示了用户所居住的信息,但是如果我们不加以注释或者没有了解的同事和使用者预先说明的话,这些字段的具体含义是很难看出来的。这种时候我们可以尝试给它加上一些特殊的业务前缀来表示,例如下边两种写法: 

不过更好的表示方式还是单独设计一个对象来存储这些具有明确业务含义的对象,例如定义一个Address对象来管理它们,例如下边所示: 

注释的规范

不要太依赖于注释

关于代码注释方面,相信工作了一段时间的开发都会有以下想法:不太相信代码注释所写的内容。为什么会有这样的想法呢? 我感觉主要原因还是和代码的不断迭代有关,随着代码的不断改动,其内部的流程早已经和注释表达的含义背道而驰。所以有时候我们代码注释的意义并不是特别大。

有时候如果代码注释和核心内容不符的时候,它反而成了一段“谎言”的存在。所以我认为:唯一真正好的注释是你要想办法去不用写注释。

别写废话注释

在我早期工作的时候,这个点确实经常会犯,例如定义一个对象的时候,我几乎会给每个字段都加入一行注释,例如下边这个类:

 

虽然说给每个字段都备注了注释,看起来也似乎很规范,但是这样的做法反而给人感觉写了一堆废话。通过每个字段的命名来看,难道它们还能有别的意思嘛?而且时间久了,别人看到这些无用的注释之后也会自动过滤掉它们的含义。

代码的长度

通常我们定义的一个类,其包含的代码量不建议设计得太大,大部分都浓缩在500行以内这个范围就好了。这是因为通常短的内容会比长的内容更方便让人理解,这就好比现如今的人更喜欢刷短视频,但是对于一些长达几十分钟或者几个小时的短片/电影却没有那么感兴趣。

除了好阅读之外,在实际工作中,大家如果使用的电脑配置不高,在电脑运行了很久的情况下再去用编辑器去修改一些篇幅非常大的类,反而会塌瘪慢。(我试过用Idea打开一份3000+行数的代码文件,挪动一格光标大概会有1秒的延迟)

另外,也并不是说代码的长度越短越好,有时候适当的空格与换行可以增加代码片段的可读性。

代码的对齐

在编写代码的时候,对于变量的对齐格式不同,其实也是有讲究的。来看下边两组不同代码的书写风格:

变量的名称统一对齐:

变量的类型统一对齐: 

在工作中,我更加会倾向于使用第二种书写格式,因为它给我的感觉会让人更加清晰看到对应变量的格式类型是怎样的。而对于第一种类型而言,给人感觉对于变量的类型不是那么地关注。

你们有哪些很好的代码习惯,欢迎分享。

 

 

 

 

 

 

 

 

 


http://www.ppmy.cn/news/57568.html

相关文章

浙大的SAMTrack,自动分割和跟踪视频中的任何内容

Meta发布的SAM之后,Meta的Segment Anything模型(可以分割任何对象)体验过感觉很棒,既然能够在图片上面使用,那肯定能够在视频中应用,毕竟视频就是一帧一帧的图片的组合。 果不其然浙江大学就发布了这个SAMTrack,就是在…

如何构建数据血缘系统

1、明确需求,确定边界 在进行血缘系统构建之前,需要进行需求调研,明确血缘系统的主要功能,从而确定血缘系统的最细节点粒度,实体边界范围。 例如节点粒度是否需要精确到字段级,或是表级。一般来说&#x…

[Pandas] 构建DataFrame数据框

DataFrame是二维数据结构,数据以行和列的形式排列 构建DataFrame最基本的定义格式如下 df pd.DataFrame(dataNone, indexNone, columnsNone) 参数说明 data: 具体数据 index: 行索引,如果没有指定,会自动生成RangeIndex(0,1,2,...,n) colu…

项目沟通管理和干系人管理

与沟通相关的概念、如何制定沟通管理计划、管理和控制沟通、项目干系人管理等 1、沟通的基本概念 沟通:包括信息的生成、传递、接收、理解和检查 沟通渠道的数量和参与者之间成正比关系 沟通渠道的计算公式: M n(n - 1)/ 2 …

10个最流行的向量数据库【AI】

矢量数据库是一种将数据存储为高维向量的数据库,高维向量是特征或属性的数学表示。 每个向量都有一定数量的维度,范围从几十到几千不等,具体取决于数据的复杂性和粒度。 推荐:用 NSDT场景设计器 快速搭建3D场景。 矢量数据库&…

“探究二叉搜索树:从原理到实现“

📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段>——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程&…

数据结构(C语言版)-第2章

来源书籍&#xff1a; 数据结构(C语言版)(第2版微课版) 秦锋 汤亚玲主编 清华大学出版社 2021年12月 书籍链接&#xff1a;http://www.tup.tsinghua.edu.cn/booksCenter/book_09444301.html# 1.线性表 1.1 线性表上基本运算的实现 1.1.1 顺序表的初始化 #include <stdio…

golang Gin实现websocket

golang使用 Gin实现 websocket&#xff0c;这里笔者重新搭建一个项目 1、创建项目安装依赖 项目名为 go-gin-websocket 在指定文件夹下&#xff0c;新建项目文件夹 go-gin-websocket 进入项目文件夹&#xff0c;打开cmd窗口&#xff0c;在项目&#xff08;go-gin-websocket&a…