【写给自己的开发知识树】——编码

3.编码

在编码、修改、重构的时候,多多思考本节内容。
假设有个需求:“跑”。

3.1.能跑

正确性。
最起码的应该是做到能跑,而不是爬。即写出来的功能要符合需求的运行起来。

3.1.1.搞清需求

需求串讲:别人给你讲了一遍需求后,反过来你给那个人再讲一遍你的理解,以免自己觉得理解了,实则误解了。

3.2.长时间的跑

能跑起来之后,就要再考虑怎么长时间的跑。
健壮性、稳定性、安全性。
尽可能的保持软件运行而不是退出、重启(包括出现异常时)。

3.2.1.多判断

1、对入参进行检查(是否空指针、长度等),防止特殊情况(比如越界)、
	边界情况下程序奔溃(功能出问题没有奔溃严重)。不要觉得你传进去的肯定是没问题的,就不进行检查了。
	因为以后有可能有别的人维护、调用你的代码,别人万一传错了呢。
2、对函数返回值进行判断,比如malloc别想当然的认为肯定成功。
3、指针要判空,if(p != NULL),避免使用空指针。free的之后要置为NULL,避免使用已经释放的指针。
4、操作数组和指针的时候要做好边界判断。
5、做减法操作时,进行大小判断,如果小的减去大的将会得到一个意外的值。

3.2.2.避免泄露

malloc-free、fopen-fclose类似的要一一对应。
尽量做到谁申请的,谁来释放。防止别人忘记释放造成泄露。
在break和return之前,确保资源已经释放。
结构指针释放时,要从底层向上一次释放。

3.2.3.避免越界

避免使用sprintf、strcat、strcpy、gets等不安全函数,
应该使用snprintf、strncat、strncpy、fgets。
操作数组和指针的时候要注意边界。
字符串要保证都以’\0’结束。
字符变量有效值范围是-128~127,小心溢出。

3.2.4.少炫技

1、If的条件有多个的情况下,不要写赋值语句,因为如果前一个条件可以判定整个条件,后面的条件不会被运行。
2、不要写出a+++b这种东西。
3、不确定符号优先级的地方,多用括号。
4、传进来的指针,尤其是字符串情况下,如果仅仅是为了使用而不是为了修改它,那就定义成const。
3.2.5.做好同步
1、多任务会并发调用的函数中,不要使用共享变量(static、全局变量),若使用则必须加上同步机制(锁等)。

3.3.跑的更快

能跑了,也能长时间跑了,那继续考虑怎么能跑的更快呢?
效率、性能。
尽可能的提高开发过程的效率和程序执行的性能。

3.3.1.编译速度

1、不需要的头文件不要包含,避免过多的展开头文件。
2、经常改动的文件先包含,这样如果改动有错,可以在编译未改动头文件前就发现,减少编译时间。

3.3.2.编码效率

1、一个函数最好不要超过50行(在一屏之内可以看到整个函数)。
2、代码控制块嵌套深度不要超过4曾,不然阅读起来可能绕不过来。(if、for、switch、while)
3、一个变量的作用要单一,别既用作入参又用作返回值。
4、添加好注释。
5、变量定义时初始化。防止出现使用随机值的情况。
(有人说:没事,我下面会初始化。那请问你能保证以后别人添加代码的时候,他也初始化吗?)
6、避免魔鬼数字:有意义的数字,使用宏定义或const变量。方便修改、阅读。
7、如果是入参,不要进行修改。特别是当入参为指针的时候,不小心修改了,返回后继续使用会有隐患。
8、加入适当的打印。打印可以有开关、等级。
9、不要再extern C里包含头文件

3.3.3.运行性能

1、If...else if...else if...else,此种情况下,应该把执行到的概率最高的分支放最前面。
2、循环中,非必须在循环中执行的操作,移到循环外。
例:for(int i = 0; i<strlen(strBuff); i++)
{
	sum += i;
	total = sum;
}
改为
int strLen = strlen(strBuff);
for(int i = 0; i<strLen; i++)
{
	sum += i;	
}
total = sum;
3、频繁申请内存或进行连接的情况,使用内存池或者连接池,避免频繁的创建、销毁。
4、短小且调用特别频繁的“小函数”可改成宏实现。
5、尽可能避免反复初始化,例:
int i = 0;
for(i = 0; i < 10; i++)
{
	//do something
}

3.4.换几个环境继续跑

当你跑得不是很慢的时候,可以考虑下,要是别人让你换个姿势,或者换个跑道,你是不是也可以跑。

3.4.1.灵活性

不要简单的在代码上堆叠代码,要富有弹性,尽可能的减少其他程序对自己的影响。
1、功能实现要抽象化,实现一个功能,不仅要在特定场景下可用,而且换个类似的场景也可用。
例:时间2:3:14 中 : 换成 - ,2-3-14。
×:把下标1、3的字符变成 - ;这样子如果时间表示方法是02:03:14呢?不灵活,没弹性。
√:找到 : 再换成 - 。

3.4.2.可移植性

3.5.带别人一起跑

当你上面几条都做到了,可以考虑下怎么顺便给以后的你或别人铺好路。
想要做到这点,可以看看一些源码。

3.5.1.可读性

1、正确分支和错误分支最好整齐的分开
  改成  
2、就近原则
把相关的语句放在相近的地方
3、

3.5.2.可维护性(可扩展性、可理解性、可修改性)

新功能的增加、旧功能的修改,改动的地方越少越好,改动的影响越小越好,改动的效率越高越好。
函数要有条理,给人看起来就是:它做这个,做那个,然后做那个……很容易理解。

3.5.3.可测试性、可复用性

1、编码时要考虑给测试和后期的产品维护提供必要的手段和接口支持。
比如要给别人单独演示某个功能的时候,可以重新写个main,调用一些接口,该功能就出来了。
这个main很像开源软件中给的example、demo。
回忆下,你以前写过的程序,能不能通过调用几个函数来抠出你的那块功能?
2、编码时每个函数要尽可能的独立。其实做到上面的说的基本已经独立了。
当程序员发现一段代码、函数、模块所做的事情可以在新的模块、或者新的系统中使用的时候,
他们总是发现,这些已有的代码依赖于一大堆的其他的东西,以至于很难将他们分开。
他们可能选择不去碰这些代码,也可能以最原始的复制去复用。

3.6.其他

3.6.1.历史数据处理

会用到时间的地方,最好都传递time_t类型,虽然要转成字符串的地方多的话比较重复,
	但是方便进行运算(现在不需要以后需要)。
历史数据的存储:
	方便增加和删除。
历史数据的清理:
	如果数据一直不能发出去,那不能一直存着,会越来越多。

3.6.2.高质量代码

1、代码规范性
2、代码完整性:功能测试、边界测试、负面测试。一个函数可以解决同类的问题
3、代码的鲁棒性(健壮性)。这是一个音译,robust,是在研究控制系统稳定性时候提出的一个词。

坚持积累

发布了38 篇原创文章 · 获赞 17 · 访问量 4285

猜你喜欢

转载自blog.csdn.net/qq_14877637/article/details/104653364
今日推荐