一次CodeReView讲解

CodeReView

目录

一、 CodeReview目的
二、 CodeReview内容
三、 代码分析
四、 总结

一、CodeReview目的:

  1. 分析代码中的问题,不仅限于bug,主要包括:代码规范、代码逻辑、代码设计等方面
  2. 相互学习,共同进步
  3. 提升团队开发共识,增进团队工作默契

二、CodeReview内容

  1. 代码编码逻辑和效率
  2. const 类型使用
  3. 头文件包含顺序

三、代码分析

  1. 代码编码逻辑和效率

设计一个创建目录函数

/*
* CreateDir: 传入一个目录字符串,判断其是否存在,存在则返回,否则创建该目录并返回
* return value: FALSE: 目录没有创建成功,TRUE:目录本来存在或重新创建成功
*/
bool  createDir(const char* pDir);

应该怎么写呢,首先想到系统的 _mkdir函数。 但这个函数使用过程中需要注意的是: - 不能创建多级不存在的目录 - 不能识别 '/'(右斜杠)

_mkdir 的返回值说明

    Return Value
    Each of these functions returns the value 0 if the new directory was created. On an error, the function returns –1 and sets errno as follows. 
    EEXIST
    Directory was not created because dirname is the name of an existing file, directory, or device. 

    ENOENT
    Path was not found. 

1.1 目录创建函数:

// 假定使用左斜杠, 从左往右,依次创建所有目录
bool createDirNormal(const char* pDir)
{
    int start = 0;
    std::string dir = pDir;
    int pos = 0;
    int lastpos = 0;

    while(  pos != std::string::npos)
    {
        pos =  dir.find_first_of("\\",start);
        if(pos != std::string::npos)
        {
            std::string path = dir.substr(0,pos);
            start = pos+1;
            _mkdir(path.c_str());
        }
    }
    if(_access(dir.c_str(),0) == 0)
        return true;

    return false;  
}

以上函数要求,路径末尾要以"\"结尾,否则最后一级目录无法创建,为了修正该问题,可以在一开始追加"\":

// 处理最后一个目录 if(dir[dir.size()-1] != '\') dir += "\";

如果需要混合处理左右斜杠,可以在处理之前,将"/"替换为"\":

    // 修正斜杠方向为左斜杠
    for(int i = 0; i < dir.size(); ++i)
    {
        if(dir[i] == '/')
        {
            dir[i] = '\\';
        }
    }

添加这些,我们程序是否还有改进的地方?

首先,程序在最开始,要验证参数是否正确:

// windows 平台下的创建目录,包括级联目录(中间目录也不存在,需要级联创建)
    if(pDir == NULL)
        return false;

其次,为了提高程序执行效率:可以执行一次创建目录:

    // 尝试创建
    if(_mkdir(pDir) == 0)
        return true;

第三,程序创建所有的目录结构,是否有些不太优雅?(是否可以先检测目录是否存在,找到不存在的目录,从此处开始创建):

while(  pos != std::string::npos)
{   
    pos =  dir.find_first_of("\\",start);

    // 路径循环,发现已经到了结束位置(目录末尾有"\",此时找pos无效,
    // 说明已经创建完毕,检测是否创建成功并返回
    if(pos == std::string::npos)
    {
        if(_access(dir.c_str(),0) == 0)
            return true;
        else 
            return false;
    }
    std::string path = dir.substr(0,pos);
    start = pos+1;

    if(lastpos  == pos -1) // 相邻的两个"\",如:F:\d\\test\1
    {
        lastpos = pos;
        continue;
    }
    lastpos = pos;

    // 判断当前路径是否存在,不存在创建
    if(!bFindMiddle && _access(path.c_str(),0) != 0)
    {
        bFindMiddle = true;
        if(_mkdir(path.c_str()) != 0)
            return false;
    }
    else if(bFindMiddle)
    {
        if(_mkdir(path.c_str()) != 0)
            return false;
    }

    if(pos == dir.size()-1) // 末尾包含"\"或"/"的路径,已经创建完毕,函数正确返回
    {
        if(_mkdir(dir.c_str()) == 0)
            return true;
        else
            return false;
    }
}

对于查找到不存在的目录,然后从此目录开始创建以后的所有目录,这种方式与不检测目录是否存在直接创建,两者的效率,取决于: 访问目录所消耗的操作是否小于创建目录所消耗的时间
经过测试,检测文件是否存在要不创建文件快得多:

  1. const 函数的使用: 声明:

        std::string getName();
    

定义:

    std::string Item::getName()
    {
        return m_name;
    }

修改后:

    const std::string& getName() const;

    const std::string& Item::getName() const
    {
        return m_name;
    }
  1. 代码规范

  2. 头文件顺序:

    #include <string>
    #include <osg/Drawable>
    #include <osg/Geometry>
    #include <osg/NodeCallback>
    #include <osg/Camera>
    #include <osg/Vec3d>
    #include <functional>
    
    #include <assert.h>
    #include <typeinfo.h>
    #include "Export.h"
    

对于头文文件,应该按照一定的顺序进行包含,否则卸载一堆中,显得不叫混了,有时出现同时将一个头文件重复包含。

修改后顺序:

#include <assert.h>
#include <typeinfo.h>

#include <string>
#include <functional>

#include <osg/Camera>
#include <osg/Vec3d>
#include <osg/Drawable>
#include <osg/Geometry>
#include <osg/NodeCallback>

#include "Export.h"

一般的头文件包含顺序: 
c库头文件: #include <assert.h>
c++库头文件 #include 
sdk库头文件 #include <directx.h>
第三方库头文件 #include <osg/Notify> 
本项目中的库头文件 #include <VRFeatureBase/LayerClass.h>
本模块中的头文件 #include "MapLayerManager.h"

四、总结:

  1. 写代码是一件精益求精的细活,我写这个CreateDir,也是经过反复修改和测试而逐步完善的,当然不敢说已经没有bug,没有可以改进的余地,所有的代码,也要根据实际情况来区分(如我对右斜杠进行替换,如果所有人都约定,使用左斜杠,这样的话,执行斜杠替换就是多此一举)。

  2. 逻辑处理的全面覆盖需要通过多角度的输入量进行测试:
    在最开始,我对mkdir函数的使用不是很清楚,以为它可以识别"/",包括msdn说也可以,但测试结果是不行(msdn是2008对应的版本,当前测试平台为win7,时过境迁,不同也不足为奇。所以所有的代码,只有真真正正去验证一遍,才有说服力)

  3. 要提高写代码,就要勤动手,多谢多练,自然会不断提高写代码的质量

猜你喜欢

转载自blog.csdn.net/kasteluo/article/details/81358103