第一章 概述
1.1工欲善其事,必先利其器
1.2常用工具软件
- SourceInsight
- Notepad++
- Araxis Merge/Beyond Compare
- FTP工具:如FileZilla
1.2.1 Araxis Merge
Araxis Merge是一个可视化的文件比较、合并和同步的软件,能够方便地被软件工程师用于快速精确地比较不同版本的源文件。此外,它还能被用于进行版本和质量控制。
1.2.2 Beyond Compare
Beyond compare是一套由Scooter Software推出的软件,主要用于文件之间的比较。
第二章 学校到职场
第三章 程序的样式
3.1 头文件
/********************************************************
* 版权所有 (C)2015 公司或个人名称。
*
* 文件名称:
* 内容摘要:
* 其他说明:
* 当前版本:
* 作 者:
* 完成日期:
*
* 修改记录:
* 修改日期:
* 版 本 号:
* 修 改 人:
* 修改内容:
** *****************************************************/
#ifndef _XXX_H //防止头文件被重复引用
#define _XXX_H
/********************************************************
相关宏定义
********************************************************/
/*******************************************************
相关结构体定义
*******************************************************/
/*******************************************************
源程序中出现的函数声明
*******************************************************/
#endif
3.2 源文件
/********************************************************
* 版权所有 (C)2015 公司或个人名称。
*
* 文件名称:
* 内容摘要:
* 其他说明:
* 当前版本:
* 作 者:
* 完成日期:
*
* 修改记录:
* 修改日期:
* 版 本 号:
* 修 改 人:
* 修改内容:
** *****************************************************/
#ifndef _XXX_H //防止头文件被重复引用
#define _XXX_H
/********************************************************
头文件引用
********************************************************/
/*******************************************************
全局变量定义
*******************************************************/
/*******************************************************
函数实现
*******************************************************/
#endif
说明:
- 当源程序中的函数比较多时,会出现很多函数都需要使用同一个变量的情况,这就需要定义一个全局变量供他们使用。但全局变量的个数要尽量少,尽量不要定义多余的全局变量,这样可以减少不同函数之间的耦合性。就拿人类来说,我们依靠别人越少,我们越自由,如果很多事情都要先问问别人的意见,你的心里感觉如何?
- 函数头部的注释
/*******************************************************
* 功能描述:
* 输入参数:
* 输出参数:
* 返 回 值:
* 其他说明:
* 修改日期 版本号 修改人 修改内容
* YYYYMMDD XXX Name YYY
********************************************************/
3.3 空格和空行
3.3.1 空格
- c语言的关键字之后要留空格,以突出该关键字;函数名之后不要留空格,紧跟左括号(,以与关键字作区别;但在函数定义的参数之间,要留有空格,如Function(x, y, z)
- 二元操作符的前后应该加空格,一元操作符的前后不加空格
- 在一行代码的结尾之后不要加空格
- 在代码中,使用空格进行缩进,一般缩进4个空格,不要使用制表符进行缩进
3.3.2 空行
- 空行起着分隔程序段落的作用,适当的空行将使程序的布局更加清晰
- 在每个函数定义结束之后都要加空行,建议加2个以上的空行
- 函数体内不要随意加空行,空行多用于分隔关系不是很大的代码段
3.3.3 大括号
一个函数的所有语句是包括在{}之中的,除此之外,大括号还有其他用处
- 分隔功能关联不大的语句块
void function A()
{
//功能A代码块开始
{
//功能A的实现代码
}
//功能B代码块开始
{
//功能B实现代码
}
}
- 突出添加或修改的代码-阅读和维护代码容易
void function A()
{
......
......
......
//修改或添加代码块开始
{
//修改或添加的代码
}
......
......
......
}
3.3.4 注释
- //用来单行注释,/*/用来多行注释
- 注释的位置要与被描述的代码相邻,可以放在代码的上方或者右方,但不可放在下方
- 注释应简单、准确、易懂,防止二义性,避免使用缩写
- 边写代码别注释,修改代码修改注释,保持代码与注释的一致性
- 遵循内容重于形式的原则
第四章 变量和函数
4.1 数据类型
在实际工作中,我们需要对一些基本数据类型进行重定义(规范化),才能够满足编程规范的要求,才能够用于定义变量。
4.1.1 整型
typedef unsigned short int UINT16;
typedef signed short int INT16;
typedef unsigned int UINT32;
typedef signed int INT32;
typedef unsigned long ULONG;
typedef signed long LONG;
typedef unsigned char UINT8;
typedef signed char INT8;
- 在代码文件中,按照这个规范编写的程序阅读起来比较方便,便于理解
- 提高了工作效率,让读者一看就觉着十分专业
- 这样做会简介提升开发工程师在客户心中的地位,能够获得他们比较好的评价。
4.2 变量及函数
- 变量及函数要有描述性,不要过度缩写
- 遵循一个原则让读者一眼就能看出他们表达的意思
- 函数的功能要单一,不要设计多用途的函数;函数体的规模要小,将函数内的代码行数控制在项目规定的范围之内。
- 避免函数带有记忆功能,相同的输入应该产生相同的输出
- 函数调用的时候,传入的实参类型要和形参的类型完全一样。如果不一样,用代码检查工具是很容易发现的。如果确实需要传入该参数,可使用强制数据类型转换。
- 对于有返回值得函数,尽量在被调用的时候对返回值进行处理。不处理的话是不符合规范的。
4.3 静态变量
在实际的软件开发中,有一类变量非常特殊-静态变量。它主要应用于函数中,具有记忆性,即本次函数本次调用时使用的变量值是上一次函数执行结束时该变量的值。
第五章 内存操作
常用内存操作函数-可以参见K&R的书籍《the c program language》
第六章 文件
常用文件操作函数-可以参见K&R的书籍《the c program language》
第七章 指针和结构体
第八章 算法和协议
8.1 算法
- 图形化表示——流程图
8.2 协议
在通信协议中,一条完整的消息由消息头和消息体组成。在C语言中,用结构体来表示协议,在消息解析的时候,一般只关注消息体的内容。
示例:
//消息头结构
typedef struct
{
UINT16 iReserve1;
UINT16 iReserve2;
UINT16 iReserve3;
UINT16 iReserve4;
}MsgHead_T;
//消息结构体(包含消息头和消息体)
typedef struct
{
MsgHead_T tMsgHead;//消息头
UINT32 iOperType;//操作类型
UINT8 szUserNumber[30];//用户号码
UINT8 szOperTime[20];//操作时间:yyyymmdd
UINT32 iReservel;//保留字段1,便于扩展
UINT8 szReservel[50];//保留字段2
}UserReqMsg_T;
第九章 程序重构
9.1 重构原因
- 原程序编码不规范,函数封装做的不好
- 源程序架构不能满足新需求
- 源程序有bug
- 源程序效率低下,性能不足以满足客户要求
9.2 重构原则
- 小步快跑:一次一小步的修改模式
- 两顶帽子:一顶是只重构源代码而不增加新功能;一顶是增加新功能以实现新需求
- 糟糕设计零容忍度:先重构代码或系统使之适应新需求,在顺理成章的去实现这些新需求
第十章 SQL语句和Shell命令
由于自己还没接触到这方面的知识,所以就不在这里做记录了。
第十一章 程序问题排查
根据故障的严重程度,软件故障可以分为3类:
- 严重故障
这类故障一般会导致软件产品无法正常使用,需要立即解决。
- 一般故障
这类故障虽然不会导致软件产品无法正常使用,但会影响某些功能流程,会影响到用户的体验。如果出现了此问题,那么软件工程师在手中任务不紧张的情况下,需要抽时间来处理掉,不能让问题一直遗留下去。
- 轻微故障
这类故障几乎不会对软件产品产生不良影响,用户也很少能够感觉到故障的存在。对于追求高质量和良好用户口碑的公司,在后续产品功能升级的时候,会附带将该类问题一起处理掉。
程序问题排查
11.1 日志
11.1.1 日志等级
- 严重错误-level1
- 一般错误-level2
- 警告信息-level3
- 一般信息-level4
- 跟踪信息-level5
- 调试信息-level6
11.1.2 日志配置
在配置文件中,有一个专门的[LOGINFO]配置段,其中的配置项如下:
[LOGINFO]
;日志等级,1-严重错误,2-一般错误,3-警告信息,4-一般信息,5-跟踪信息,6-调试信息
LevelOfLog =
;每个日志文件的最大容量
MaxSizeOfLog =
;是否输出该条日志在代码中的位置(行数),1-是,0-否
PositionOfLog =
11.1.3 日志函数
有两类写日志的函数
- 形如WriteLog(LevelOfLog,InfoOfLog)
如:
WriteLog(LOGINFO,“the value of this integer is 3”);
- 刑如WriteLogEx(LevelOfLog,InfoLog,InfoOfParam),这是扩展的日志函数,不但能够输出日志信息,还能够在日志信息中显示变量的值
如:
WriteLog(LOGINFO,“the value of this integer is %d”,iInt);
11.1.4 日志说明
日志编写的总体原则是简单清晰,便于排查问题。
- 分多条信息分别输出,不要企图将所有信息一次打印出来
- 分时输出
- 必须分日志级别
- 控制日志信息的条数,不重要的信息尽量不要打印日志
- 所有的输入输出,包括收消息和发消息都要求输出日志
- 关键控制点必须输出日志
- 调用底层或第三方软件,必须输出日志,并且对不可靠底层,必须加上begin/end两行日志
- 对方系统处理事件必须输出日志,以利以后维护时快速定位性能问题
11.2 配置项问题
- 千里之堤,毁于蚁穴,很多软件问题并不是由很大的缺陷引起的,反而是一些很细小的问题造成的。
- 在提交软件版本之前,对于需要使用配置文件的软件,相关开发人员一定要认真编写配置文件使用说明书。在说明书中,要详细描述每个配置项的配置规则及注意事项,让即使是不懂程序的人也能够在很短的时间内看明白并做到正确配置。
- 在设置配置值之前,我们一定要对程序的处理流程了然于心,很多软件本身并没有问题,但就是因为某些配置项不符合程序要求而导致了整个软件的故障。
- 在运行软件之前,相关人员要仔细检查 配置文件中的各个配置项的值,确保每个配置值都是准确无误的。
- 细节决定成败,只有不断的实践,不断的总结,我们才能够提高代码的质量,让细节问题无处藏身。
11.3 时序问题
- 详尽的日记处理有助于问题的定位
- 在消息处理顺序很重要的程序中,一定要理清程序执行的前后关系,防止流程越位的情况发生
- 在排查问题的过程中,不要放过任何一个蛛丝马迹,要及时验证自己的想法,多对程序进行验证。
11.4 变量初始化问题
11.5 数据表索引问题
总结:
本书可以闲来无事看看,对于还未进入社会的同学来说会提供很多经验性的参考。但不建议购买。