(点击上方公众号,可快速关注)
首先说明下,这里说的”新人“仅仅是我接触到的刚参加工作的新同事。肯定存在不少刚毕业的”老手“,比工作上的”老人“还老道。
C++相关不好的习惯
include 冗余头文件
关于这一点,带来的主要副作用是给使用者增加了依赖,举个例子:假设一个http库提供了Get、Post等功能,大体这样子:
#pragma once
#include <string>
#include <map>
using namespace std;
int get(const string& url, const map<string,string>& params);
int post(const string& url, const string& data);
但在实现的时候使用到了nlohmann/json的json库【这是个纯C++头文件的库】,一些同学就把这个依赖体现到头文件:
#pragma once
#include <string>
#include <map>
using namespace std;
#include "nlohmann/json"
...
带来的直接效果就是使用者必须得依赖这个json库,更好的方式是在cpp文件里include,这样使用者就无需为库的实现细节买单了。
我以前专门有篇文章介绍过这个话题,请点击这里。
命名规范”奇怪“
常见的命名法有驼峰、下划线、匈牙利等,基本上常见编程语言的命名规范是这几种命名法的组合使用。当然每个公司也有自己推荐的命名规则,遵守即可,基本问题不大。
但在实际操作过程中,我还是见到过一些比较奇怪的命名方式,比如,变量名首字母大写:
int Age;
这就太随意了,基本上所有的命名规则没有这样的,应该避免。
裸指针横飞
不管适不适合,甚至能用普通变量的情况也new
一个指针出来。使用裸指针主要带来了两个问题:
NULL
是指针的特殊值,理论上必须要特殊处理,否则就会出现段错误为什么一定要处理呢?因为只要你提供了这种可能,就一定会有人传
NULL
,类型系统帮不了你,只能在每个使用指针的地做好保护。new
或malloc
出来的资源很容易忘了释放,而且在堆上分配内存开销要比栈上高得多
第一个问题,尽量避免使用指针,使用普通变量能解决的事为什么要用指针,很多情况引用就够用了,引用在功能上类似于受限的指针。
第二个问题类似,能用普通变量替代最好,不行的话可以使用智能指针替代。
冗余初始化
感觉这都成为一种风格了,例如:
//第一种情况
string a = "";
//第二种情况
string a;
a.clear();
为什么不直接写成string a;
,到底在担心什么呢?
我能想到这么做的原因有两点:
缺乏编程的惯例
默认值在不少语言里都对应了0,不同类型0的表现不同,对于整型就是0,对于字符串就是空字符串,对于字符就是'\0'等,本质上都是初始化为0的一段内存。虽然是惯例,但一般好的设计都会遵循这个原则,否则会很容易使用出错。上例中
string
的默认构造的对象初始值如果不是空字符串,其他值都不合理啊。对C++标准库不熟悉
sizeof(结构体类型)
如:
int a;
//假设使用到了a的大小
fun(sizeof(int));
如果a
的类型变了呢?下面调用的地方也得改,为什么不直接使用sizeof(a)
呢?之前有个项目里修改了一个类型,由sizeof
导致的修改达300多处,只要稍微注意点,很多工作量都是可以省掉的。
这个问题很具体,往大了说,这实际上要求我们怎么将变化、重复的部分做好抽象。好的代码应该做到前人栽树后人乘凉的效果,不要仅仅满足当前的结果,给后人挖坑。
代码未经测试直接提交
写完代码,没单元测试,没接口调试,甚至代码编译都有问题,直接将代码push到代码库;代码是自己的作品,以这样的面目给别人看,说不过去。
刚写完的代码,跟写作文打的草稿一样,基本上100%是有问题的,还需要后面多道工序的加工才能成型,提交有问题的代码没有任何意义;尽量保持每次提交都没问题,很可能别人还会基于你的修改做其他修改。
严重低估日志
日志是排查问题首要考虑的对象。很多成熟的框架、SDK等在出现异常情况下都会打印日志,包含非常有价值的信息。
很多人被千叮万嘱后还是缺乏这方面的意识,实际上大部分看似诡异的问题都能在日志里找到答案。
喜欢我的文章,请关注我的公众号。转载请标明出处。