90%的程序员都犯过的代码错误

栏目: IT资讯 · 发布时间: 6年前

内容简介:最近参加了多次的代码review会,在review的过程中,发现有些问题几乎每次都出现。挑了几个比较典型的问题讲解下。这几个问题都是初级问题,解决方法都很容易。只要掌握了方法,有意识避免,能让短时间内迅速提高代码质量。真所谓投入小,见效快。为变量命名时最重要的考虑事项是,该名字要例如:

最近参加了多次的代码review会,在review的过程中,发现有些问题几乎每次都出现。挑了几个比较典型的问题讲解下。这几个问题都是初级问题,解决方法都很容易。只要掌握了方法,有意识避免,能让短时间内迅速提高代码质量。真所谓投入小,见效快。

变量命名不清晰,一词多义

为变量命名时最重要的考虑事项是,该名字要 完全、准确地描述出该变量所代表的事务 。容易阅读,不会与其他事务混淆。

例如:

if(staff_id == 0)
{
    printf("系统归档,不是员工归档");
}

上面这段代码,staff_id是员工号的意思,用staff_id为0表示是系统归档。一词多义,本来应该把系统和人分开,但是混用到了一个变量。如果调用方出现个bug忘记把初始化的变量赋值,还会走到意外的逻辑。

解决方法是变量名称首先要符合变量的实际意义,没有歧义;对于一个变量名,不用特定值表示特殊逻辑。

有些代码会把变量取不到的值赋予其他的意义,感觉是省事了,实际后患无穷。例如用户名不可能为空,就用空值表示这个用户数据已经被删除了。而且判定数据是否删除的代码看着也让人莫名其妙。

总之,变量命名要保证没有「潜规则」,防止给自己挖坑。

使用魔数

命名不清晰更严重的是,没有命名,直接用魔数。如果连注释都没有,就只能靠猜。

使用魔数有两个不好的地方:

1、不方便修改。

使用常量替换魔数是一种将程序「参数化」的方法,需要修改改动一处就可以了,而不必代码中到处修改。

例如在代码中默认绑定的端口是80,如果不用一个常量代替,哪天软件升级默认端口变成443了。要整个代码搜索80这个数字,既耗时,又容易改错。

2、代码不方便阅读。

只有一个数字,很难了解到具体的意思。

for(int i = 0; i < 13; ++i)
{
    ...
}

上面这段代码,只看13,谁能猜出来是什么意思呢,为什么用13这个数值?可能只有写代码的人和上帝知道,如果天长日久,写代码的人忘记了,就只有上帝知道了。

也有同学会问,有的数字只用到一个地方,也起个常量的名字会不会太麻烦了?

答案是:不麻烦。给魔数起个好名字是应该的,这是对的事,不要因为麻烦就不做。有时为了起个准确的名字,甚至要查下词典。

有一个常用的判定方式:

一、如果引用魔数的地方不超过3个,直接用数字影响也不大。如果超过了3个,都是表示同一个数值意义,还是乖乖地用有意义的变量名代替。

二、如果魔数本身就是表示一个纯粹的数字定义,例如是几米、几千克这种,作为参数传递。在函数的定义明确表示了形参数所代表的意义。大家看用到的地方和函数定义,就知道数字是表示多少个单位的意思,可以用魔数。但是如果用数字表示种类,例如

const int ieBrowser=1;
const int chromeBrowser=2;

表示浏览器的种类,如果直接只是看到1或2,是不明白什么意思的。即使在函数声明的地方已经说过是浏览器种类了,也不要用魔数。

魔数解决的办法很简单: 用枚举、常量等方式,代替魔数

if else 或switch等逻辑判断语句太长

例如下面的伪代码代码,条件分支很多,用很长的if else语句或者switch语句才能表达完整的逻辑,要思考下是否能用「表驱动」方式来优化。

const int CN=1;
const int US=2;
const int UK=3;

string language;
if(country==CN)
{
    language="中文";
}
else if(country==US)
{
    language="english";
}
else if(country==UK)
{
    language="english";
}
else
{
    language="";
}

条件分支太多太长有几点不好:

1、代码太长,不易阅读。

如果超过了一个屏幕能表示的长度,要翻页才能看完代码,会大大降低看代码的效率。因为代码的信息密度太低了。

2、不易扩展,修改代码。

就像上面的例子,如果又增加了新的条件判断,那么要增加新的if else语句,由于修改了逻辑,要重新测试,也要防止改错。

可以用「表驱动」的方式替代太长的逻辑分支。

把每个条件要用到的数据放到一个「表」里。用条件分支的判断条件来索引到表中的数据。

上面的代码可以修改为

const int CN=1;
const int US=2;
const int UK=3;

string languageTable[]={"","中文","English","English"};
//先判断country变量是否在定义的CN、US、UK范围内,如果在继续
language = languageTable[country];

经过修改,代码变得很短,一眼就能看出代码所表示的逻辑。而且以后更新的只有数据,逻辑部分不用修改。

使用「表驱动」后,逻辑和数据分离。使得新增数据修改简单,而且一目了然。

总结

上面只是简单的说明了几种常见的代码书写错误。稍加注意,就能够在短时间内迅速提升代码质量。具体的方法可以参考一些代码规范,或者重构的书籍,例如「表驱动」会有更详尽的介绍。

最本质的还是要从意识上有足够的认识。 代码是写给人看的 ,写代码时要有同理心,想到以后让阅读代码的人尽量能够不费力读懂。换位思考,如果你就是review人,或后面接手这个代码的人,你会喜欢这段代码吗?

毕竟代码阅读的次数远远超过编写的次数。确保代码阅读方便,而不仅是编写方便。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Beginning ARKit for iPhone and iPad

Beginning ARKit for iPhone and iPad

Wallace Wang / Apress / 2018-11-5 / USD 39.99

Explore how to use ARKit to create iOS apps and learn the basics of augmented reality while diving into ARKit specific topics. This book reveals how augmented reality allows you to view the screen on ......一起来看看 《Beginning ARKit for iPhone and iPad》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码