关于编程气势气魄的接头6
副标题#e#
六、模块化类型:
为了提高软件的重用性,淘汰反复开拓的事情量。同时也为了提高措施的可读性,利便措施的维护,必需增强软件的模块化事情。模块化应该遵循以下几个根基类型:
1、 个函数应该作到精而小,函数的代码应该节制在一个适度的局限,每个函数的代码一般不能高出150行,假如高出这个局限,应该举办模块化的事情。对付一些非凡的函数确实要高出150行,应该提交出来接头,通事后,要求编写者越发具体的对函数注释,并写明函数超行的原因,以及设计思想等。
2、 某一成果,假如反复实现三遍以上,既应该思量模块化,将其写成通用函数。并向开拓人员宣布。并要求将接口文档和实现的成果存案。
3、 每一个开拓人员要尽大概的操作其他人的现成的模块,淘汰反复开拓。
4、 对函数举办模块化时,要思量函数的条理干系,出格是在增加新的成果模块时,对本来的函数代码要举办当真的调解,做到沟通成果的差异函数没有反复代码,此要求的目标在于便于代码维护。举譬喻下:
现有如下函数:
//从szFileName文件中取 ......
long ...... cmGetSomething(const char * c_szFileName,......)
{
CFile * pFile;//用来生存打开文件的地点
pFile=new CFile(c_szFileName,CFile::modeRead);//用建设一个只读文件
if(pFile==NULL)
{
lResult=CM_POINT_IS_NULL;
goto END;
}
//从文件中读取......
......
//封锁文件
delete pFile;
END:
return lResult;
}
若此刻需要增加如下接口的新函数:
long ...... cmReadSomething(CFile * pFile)
{
if(pFile==NULL)
{
lResult=CM_POINT_IS_NULL;
goto END;
}
//从文件中读取......
......
END:
return lResult;
}
#p#副标题#e#
则要求如下:
将 long ……cmGetSomething(const char * c_szFileName,……)改为
long ...... cmGetSomething (const char * c_szFileName,......)
{
CFile * pFile; //用来生存打开文件的地点
long lResult=CM_OK;//错误返回码
//打开文件
pFile=new CFile(c_szFileName,CFile::modeRead);
if(pFile==NULL)
{
lResult=CM_POINT_IS_NULL;
goto END;
}
//从文件中读取......
lResult=cmReadSomething(pFile,......);
IF_ERROR_GOTO_END
//封锁文件
delete pFile;
END:
return lResult;
}
模块化的一些留意事项:
① 、设计好模块接口,用面向工具的概念看,包罗:函数接口和变量接口。
② 、界说好接口今后不要等闲窜改,并在模块开头(文件的开头或函数的开头)加以说明,所以在界说接口时,必然要重复琢磨,保持气势气魄一致。
③ 、留意全局变量也是一种接口,假如不是确实须要,应该只管罕用全局变量。
④ 、在函数接口中,只管使函数的接口容易领略和利用,个中每个输入输出参数都只代表一种范例数据,不要把错误值和其他专用值混在函数的其他输入输出参数中。
⑤ 、争取编写出永远乐成的函数,使挪用者不必举办相应的错误处理惩罚。
此类型为试行版,表明权属于**软件公司技能委员会!员工在编写措施时请参阅FuncTemplate.h和FuncTemplate.cpp
FuncTemplate.h
//////////////////////////////////////////////////////////////////////
//工程: FuncTemplate.h //
//描写: 用来处理惩罚对二叉树的一些算法,以及矩阵内存分派。 //
//版本: FuncTemplate 1.0版。 //
//////////////////////////////////////////////////////////////////////
typedef struct _NODE //界说一个节点
{
struct _NODE * pLeftChild; //节点的左孩子
struct _NODE * pRightChild; //节点的右孩子
} NODE;
//==================================================================//
// 成果: 用轮回来实现二叉树的左序遍历 //
// 参数: pNode //
//(进口) pNode: 二叉树的进口地点,即根节点的地点。 //
//(出口) 无。 //
// 返回: long 的函数返回码,假如返回值为CM_OK,表乐成遍历,返回 //
// CM_POINT_IS_NULL表二叉树指针为空。 //
//==================================================================//
long cmWalkTreeUseCycle(const NODE * pNode);
//==================================================================//
// 成果: 对矩阵举办分派内存 //
// 参数: wRowSize,wColSize,ppplMatrix //
//(进口) wRowSize:矩阵的行数; //
//(进口) wColSize:矩阵的列数; //
//(进口) ppplMatrix:要分派的矩阵的地点; //
//(出口) ppplMatrix:分派的矩阵的地点; //
// 返回: long 的错误号,假如返回值为CM_OK,表分派乐成,返回 //
// CM_POINTER_IS_NOT_NULL表矩阵的进口地点值不为空。 //
// CM_MEM_ALLOC_FAILED 系统的内存不敷 //
//==================================================================//
long cmInitMatrix(const size_t wRowSize,const size_t wColSize,long *** ppplMatrix);
FuncTemplate.cpp
//////////////////////////////////////////////////////////////////////
//工程: FuncTemplate.cpp //
//作者: ** //
//修改者: **,*** //
//描写: 用来处理惩罚对二叉树的一些算法,以及矩阵内存分派。
//主要函数:cmWalkTreeUseCycle,cmInitMatrix
//版本: FuncTemplate 1.0版。
//完成日期:2000-8-26 //
//修他日期: 2000-8-27,2001-12-21 //
//参考文献: 图形措施开拓人员指南(机器家产出书社)
//////////////////////////////////////////////////////////////////////
#define STRICT
#include "stdio.h"
#include "stdlib.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "makehresult.h"
#include "memory.h"
#include "functemplate.h"
#define CM_MEM_POINTER_IS_NULL CMEMAKEHR(0X100) //暗示指针不为空的错误
#define CM_MEM_POINTER_IS_NOT_NULL CMEMAKEHR(0X101) //暗示指针不为空的错误
#define MAX_PUSHED_NODES 100 //界说最大压栈数量
////措施函数说明开始
//==================================================================
// 成果: 用轮回来实现二叉树的左序遍历
// 参数: cpNode //
//(进口) cpNode: 二叉树的进口地点,即根节点的地点。
//(出口) 无。 //
// 返回: long 的函数返回码,假如返回值为CM_OK,表乐成遍历,返回
// MS_POINT_IS_NULL表二叉树指针为空。
// 挪用要领:在挪用此函数前必需先初始化二叉树
// 思路: 假如正在会见某节点,假如该节点有左分枝,就先会见左分枝。
// 接着会见该节点,假如该节点尚有右分支。就再会见右分支。
// 会见左分枝时,在该处栈中做标志,当处理惩罚完左分枝就会见此
// 处。会见完每一个节点后,假如该节点没有右孩子,而且栈已经
// 为空,那么对该节点的会见就完成,代码对每一个节点都反复以
// 上*想*作。 //
// 参阅: 图形措施开拓人员指南(机器家产出书社)Page:927
// 日期: 2000/8/26.9:40--2000/8/26.21:45
//==================================================================
//图解:
// 根节点
// @
// / \
// / \
// 左孩子@ @右孩子
// / \ / \
// / \ / \
// @ @ @ @
// 左孩子 右孩子左孩子 右孩子
HRESULT cmWalkTreeUseCycle(const NODE * cpNode)
////措施函数说明竣事
{
HRESULT lResult;//用来生存返回的错误号。
NODE * pNodeStack[MAX_PUSHED_NODES];//用来作为节点的仓库。
NODE ** ppNodeStack;//用来指示节点仓库的指针。
lResult=CM_OK;
//判定树是否为空。
if(cpNode !=NULL)
{
pNodeStack[0]=NULL; //配置仓库为空。
ppNodeStack=pNodeStack+1;
for(;
{
//假如当前的节点有左孩子,对当前点压栈。
//并把当前点移到左孩子,开始遍历左子树,
//如此,直到找到没有左孩子的节点。
while (cpNode->pLeftChild!=NULL)
{
*ppNodeStack++=(NODE*)cpNode;
cpNode=cpNode->pLeftChild;
}
//我们此刻处于没有左孩子的节点,所以会见
//节点,假如有右子树,然后会见右子树。或
//后入的节点。反复节点的出栈直到我们找到
//有右子树的节点,或所有节点出栈
for(;
{
//会见节点(挪用此外函数,没有实现)
cmVisitNode(cpNode);
//假如节点有右孩子,使该孩子成为当前节
//点并开始遍历其子树,不然回朔会见节点
//直到我们发明一个有右子树的节点,或所
//有的入栈点已经被会见。
if(cpNode->pRightChild!=NULL)
{
cpNode=cpNode->pRightChild;
break;
}
//出栈下一个节点,我们可以会见它,并判
//断是否有右子树。
if((cpNode=*(--ppNodeStack))==NULL)
{
//栈为空而且当前节点没有右子树,完
//成遍历。
lResult =CM_OK;
goto END;
}
}
}
}
//假如指针为空则配置返回值信息为MS_POINT_IS_NULL。
lResult=CM_POINTER_IS_NULL;
END:
return lResult;
}
////措施函数说明开始
//==================================================================
// 成果: 对矩阵举办分派内存
// 参数: cwRowSize,cwColSize,ppplMatrix
//(进口) cwRowSize:矩阵的行数;
// cwColSize:矩阵的列数;
// ppplMatrix:要分派的矩阵的地点;
//(出口) ppplMatrix:分派的矩阵的地点;
// 返回: long 的错误号,假如返回值为CM_OK,表分派乐成,返回
// CM_POINTER_IS_NOT_NULL表矩阵的进口地点值不为空。
// CM_MEM_ALLOC_FAILED 系统的内存不敷
// 挪用要领:在挪用此函数前必需先对传入值赋空。对传入值作引用。
// 如:界说: long ** pplMatrix;对pplMatrix赋空,即:
// pplMatrix=NULL; 挪用为:cmInitMatrix(10,10,&pplMatrix);
// 思路: 先对每一行分派内存,再对每一行对应的列分派内存。
// 参阅: 无
// 修改人:
// 日期: 2000/8/29.9:40--2000/8/29.16:45
//==================================================================
HRESULT cmInitMatrix(const size_t cwRowSize,const size_t cwColSize,long *** ppplMatrix)
////措施函数说明竣事
{
HRESULT lResult; //存储返回值。
lResult=CM_OK;
WORD wI; //轮回变量
//要求对传入值举办初始化NULL.
if(**ppplMatrix!=NULL)
{
lResult=CM_POINTER_IS_NOT_NULL;
goto END;
}
//对矩阵的行举办分派内存
**ppplMatrix=(long*)malloc(cwRowSize*sizeof(long*));
//假如分派失败则返回。
if((**ppplMatrix)==NULL)
{
lResult=CM_MEM_ALLOC_FAILED;
goto END;
}
//对每一行所拥有的列数举办分派内存。
for(wI=0;wI<cwRowSize;wI++)
{
*ppplMatrix=(long**)malloc(cwColSize* sizeof(long));
//假如分派失败则返回错误。
if(*ppplMatrix==NULL)
{
lResult=CM_MEM_ALLOC_FAILED;
goto END;
}
//对内存置为零
memset(*ppplMatrix,0,cwColSize*sizeof(long));
}
END:
//对错误举办处理惩罚。
if(FAILED(lResult))
//假如分派不乐成则释放内存。
if(**ppplMatrix!=NULL)
{
//对每一行内存举办释放。
for(wI=0;wI<cwRowSize;wI++)
{
if(*ppplMatrix!=NULL)
{
free(*ppplMatrix);
*ppplMatrix=NULL;
}
}
//对列的内存举办释放。
free(**ppplMatrix);
**ppplMatrix=NULL;
}
return lResult;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
错误处理惩罚扩展:
#p#分页标题#e#
makehresult.h
//////////////////////////////////////////////////////////////////////////////
//作者: **
//描写: 用来对返回代码的统一划定
//主要函数:
//参考文献:COM技能黑幕(微软组件工具模子);[美]Dale Rogerson著
//////////////////////////////////////////////////////////////////////////////
#ifndef __ERRORDEFINE_H__
#define __ERRORDEFINE_H__
#include "winerror.h"
//图解
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---+-+-+-----------------------+-----------+-------------------+
// |Sev|C|R| 设备代码 | 类编码 | 返回代码 |
// +---+-+-+-----------------------+-----------+-------------------+
//
//==============================================================
////对设备代码的界说
//对通用函数界说的设备代码
#define FACILITY_CM 0x80
//对虚拟现实函数界说的设备代码
#define FACILITY_VR 0x81
//对图象函数界说的设备代码
#define FACILITY_IMG 0x82
//===================================================================================
//界说类编码(后16位中的前6位)
//从0X00~0X3F//
//个中0X38~0X3F为给措施员保存的姑且类编码。
//尺度类编码从0X00~0X37
#define MEMORY_CLASS 0x01
#define FILE_CLASS 0x02
/*
#define TEMP_CLASS1 0X38
#define TEMP_CLASS2 0X39
#define TEMP_CLASS3 0X3A
#define TEMP_CLASS4 0X3B
#define TEMP_CLASS5 0X3C
#define TEMP_CLASS6 0X3D
#define TEMP_CLASS7 0X3E
#define TEMP_CLASS8 0X3F
*/
//=======================================================================
//建造姑且资源时位的前3位屏蔽(即为生存8个姑且类),姑且资源从0X0000~0X1FFF(措施员输入值)
//实际为0XE000~0XFFFF(宏转换后)
#define ADDTEMPCLASS(lResult) ((0X38<10)|lResult)
//界说返回通用函数的返回代码范例
//对lResult的传入值在0X0000~0X1FFF之间
#ifndef CMEMAKEHR
#define CMSMAKEHR(lResult) MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_CM,ADDTEMPCLASS(lResult))
#define CMEMAKEHR(lResult) MAKE_HRESULT(SEVERITY_ERROR,FACILITY_CM,ADDTEMPCLASS(lResult))
#endif //CMEMAKEHR
//界说返回虚拟现实函数的返回代码范例
//对lResult的传入值在0X0000~0X1FFF之间
#ifndef VREMAKEHR
#define VRSMAKEHR(lResult) MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_VR,ADDTEMPCLASS(lResult))
#define VREMAKEHR(lResult) MAKE_HRESULT(SEVERITY_ERROR,FACILITY_VR,ADDTEMPCLASS(lResult))
#endif //VREMAKEHR
//界说返回图象函数的返回代码范例
//对lResult的传入值在0X0000~0X1FFF之间
#ifndef IMGEMAKEHR
#define IMGSMAKEHR(lResult) MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_IMG,ADDTEMPCLASS(lResult))
#define IMGEMAKEHR(lResult) MAKE_HRESULT(SEVERITY_ERROR,FACILITY_IMG,ADDTEMPCLASS(lResult))
#endif //IMGEMAKEHR
//当产生返回代码时,转到END处
//要求返回代码号用lResult,标志号用END
#define IF_ERROR_GOTO_END if(FAILED(lResult)) goto END;
//显示返回代码的描写信息
#define DISPLAY_HRESULT_MESSAGE if(FAILED(lResult)) cmDispResultMessage(lResult);
typedef long HRESULT;
typedef long LRESULT;
//===================================================================
//保持和windows系统(com)一致
#define CM_OK S_OK
#define CM_FALSE E_FAIL
#define VR_OK S_OK
#define VR_FALSE E_FAIL
#define IMG_OK S_OK
#define IMG_FALSE E_FAIL
#define CM_UNKNOW_ERROR CMEMAKEHR(0X000) //未知的错误
//内存错误
#define CM_MEM_ALLOC_FAIL CMEMAKEHR(0X001) //内存分派失败
#define CM_MEM_FREE_FAIL CMEMAKEHR(0X002) //内存释放失败
#define CM_INVALID_POINTER CMEMAKEHR(0X003) //无效的指针
//文件*想*作
#define CM_CREATE_FILE_FAIL CMEMAKEHR(0X010) //文件建设失败
#define CM_OPEN_FILE_FAIL CMEMAKEHR(0X011) //文件打开失败
#define CM_CLOSE_FILE_FAIL CMEMAKEHR(0X012) //文件封锁失败
#define CM_DELETE_FILE_FAIL CMEMAKEHR(0X013) //文件删除失败
#define CM_FILE_HAS_EXISTED CMEMAKEHR(0X014) //文件已经存在
#define CM_COPY_FILE_FAIL CMEMAKEHR(0X015) //文件拷贝失败
#define CM_FILE_NOT_OPEN CMEMAKEHR(0X016) //文件没有打开
#define CM_READ_FILE_FAIL CMEMAKEHR(0X017) //文件读取失败
#define CM_FIND_FILE_FAIL CMEMAKEHR(0X018) //文件查找失败
#define CM_FILE_HAS_ERROR CMEMAKEHR(0X019) //文件自己有错
#define CM_WRITE_FILE_FAIL CMEMAKEHR(0X020) //文件写入失败
//数组*想*作
#define CM_ARRAY_BEYOND CMEMAKEHR(0X060) //数组越界
//函数*想*作
#define CM_PARAM_BEYOND CMEMAKEHR(0X030) //参数越界
//数据库*想*作
#define CM_OPEN_DATABASE_FAIL CMEMAKEHR(0X040) //数据库打开失败
#define CM_OPEN_TABLE_FAIL CMEMAKEHR(0X041) //数据表打开失败
#define CM_TABLE_BEYOND CMEMAKEHR(0X042) //数据表会见越界
#define CM_CREATE_DSN_FAIL CMEMAKEHR(0X043) //建设数据源失败
#define CM_TABLE_EXIST CMEMAKEHR(0X044) //表已经存在
#define CM_DATABASE_NOT_OPEN CMEMAKEHR(0X045) //数据库没有打开
//其他*想*作
#define CM_BEYOND_PARAM CMEMAKEHR(0x100) //参数越界
#define CM_POINT_IS_INVALIAD CMEMAKEHR(0x101) //点为犯科的点
//图象*想*作
#define CM_CREATE_BMP_FAIL CMEMAKEHR(0x200) //建设位图失败
//线程*想*作
#define CM_THREAD_IS_LOCK CMEMAKEHR(0x300) //线程背锁住
//数学计较
#define CM_EDGENUM_NOTENOUGH CMEMAKEHR(0x500) //边数不足
//网络*想*作
#define CM_CONNECT_FAIL CMEMAKEHR(0x700) //毗连失败
//三维设备*想*作
#define DD_CREATE_DEVICE_FAIL CMEMAKEHR(0x400) //建设设备失败
#define DD_DELETE_DEVICE_FAIL CMEMAKEHR(0x401) //删除设备失败
#endif //__ERRORDEFINE_H__
#ifndef __ERRORMATCH_H__
#define __ERRORMATCH_H__
#include "errordefine.h"
#include "windows.h"
//errormatch.h
//用来对错误的匹配
#define lResultCount 128
#define IF_ERROR_DISPLAY_MESSAGE if(FAILED(lResult)) {DisplayChineseMessage(lResult); goto END;}
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) {if(p) {delete (p);(p)=NULL;}}
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) {if(p) {delete[] (p);(p)=NULL;}}
#endif
//===============================================================================
typedef struct _RESULTINFOS //显示返回代码信息
{
long lResultNo; //返回代码号
char szResultMessageChinese[40]; //返回代码的中文描写
char szResultMessageEnglish[40]; //返回代码的英文描写
}RESULTINFOS;
//================================================================================
static RESULTINFOS sResultInfo[lResultCount]=
{
{CM_MEM_ALLOC_FAIL,"内存分派失败","Memeroy"},
{CM_MEM_FREE_FAIL,"内存释放失败","Memeroy"},
{CM_INVALID_POINTER,"无效的指针","Memeroy"},
{CM_CREATE_FILE_FAIL,"内存分派失败","Memeroy"},
{CM_OPEN_FILE_FAIL,"文件打开失败","Memeroy"},
{CM_CLOSE_FILE_FAIL,"文件封锁失败","Memeroy"},
{CM_FILE_HAS_EXISTED,"文件已经存在","Memeroy"},
{CM_COPY_FILE_FAIL,"文件拷贝失败","Memeroy"},
{CM_FILE_NOT_OPEN,"文件没有打开","Memeroy"},
{CM_READ_FILE_FAIL,"文件读取失败","Memeroy"},
{CM_FIND_FILE_FAIL,"文件查找失败","Memeroy"},
{CM_FILE_HAS_ERROR,"文件自己有错","Memeroy"},
{CM_WRITE_FILE_FAIL,"文件写入失败","Memeroy"},
{CM_ARRAY_BEYOND,"数组越界","Memeroy"},
{CM_PARAM_BEYOND,"参数越界","Memeroy"},
{CM_OPEN_DATABASE_FAIL,"数据库打开失败","Memeroy"},
{CM_OPEN_TABLE_FAIL,"数据表打开失败","Memeroy"},
{CM_TABLE_BEYOND,"数据表会见越界","Memeroy"},
{CM_CREATE_DSN_FAIL,"建设数据源失败","Memeroy"},
{CM_TABLE_EXIST,"表已经存在","Memeroy"},
{CM_DATABASE_NOT_OPEN,"数据库没有打开","Memeroy"},
{CM_CREATE_BMP_FAIL,"建设位图失败","Memeroy"},
{CM_THREAD_IS_LOCK,"线程背锁住","Memeroy"},
{CM_POINT_IS_INVALIAD,"点为犯科的点",""},
{DD_CREATE_DEVICE_FAIL,"建设设备失败",""},
{DD_DELETE_DEVICE_FAIL,"删除设备失败",""}
};
static char * GetChineseMessage(HRESULT lResult)
{
for(long lI=0;lI<lResultCount;lI++)
{
if(sResultInfo[lI].lResultNo==lResult)
{
return sResultInfo[lI].szResultMessageChinese;
}
}
return NULL;
}
static char * GetEnglishMessage(HRESULT lResult)
{
for(long lI=0;lI<lResultCount;lI++)
{
if(sResultInfo[lI].lResultNo==lResult)
{
return sResultInfo[lI].szResultMessageEnglish;
}
}
return NULL;
}
static void DisplayChineseMessage(HRESULT lResult)
{
MessageBox(NULL,GetChineseMessage(lResult),"错误!",MB_OK);
}
static void DisplayEnglishMessage(HRESULT lResult)
{
MessageBox(NULL,GetEnglishMessage(lResult),"error!",MB_OK);
}
#endif//__ERRORMATCH_H__