这几章从注释、程序格式、对象与数据结构的规范以及错误处理四个方面介绍了如何使代码变得简洁易懂。不同于上次摘抄的方法,这一次我会结合第一次个人作业的代码进行分析。

第四章  注释

这一章告诉我们,好的注释要满足以下三点要求:

  • 尽量避免用注释解释程序意图
  • 注释要精练简洁
  • 注释要明确,不能给人误导

好的程序往往通过代码就能告诉程序员这段代码要做什么,注释只能出现在可能出现歧义的地方以及需要特别注意的地方。当你想通过添加注释来解释意图的时候,不妨先想一想将功能分块、修改函数名、封装类等方法能不能帮助你更好地表达。万不得已必须要加注释的话,那你一定要注意注释的简洁性与明确性。下面我分析一下第一次个人作业中Linux平台下遍历文件夹的程序注释部分。

 1 void traverseFileandCount(char* path, struct alphaArray* dictionary)
 2 {
 3     DIR *pDir; //定义一个DIR类的指针
 4     struct dirent *ent=NULL; //定义一个结构体 dirent的指针,dirent结构体见上
 5     int i = 0;
 6     char childpath[512]; //定义一个字符数组,用来存放读取的路径
 7     pDir = opendir(path); // opendir方法打开path目录,并将地址付给pDir指针
 8     memset(childpath, 0, sizeof(childpath)); //将字符数组childpath的数组元素全部置零
 9     while ((ent = readdir(pDir)) != NULL)
10         //读取pDir打开的目录,并赋值给ent, 同时判断是否目录为空,不为空则执行循环体
11     {
12         if (ent->d_type&DT_DIR)
13             /*读取 打开目录的文件类型 并与 DT_DIR进行位与运算操作,即如果读取的d_type类型为DT_DIR
14             (=4 表示读取的为目录)*/
15         {
16             if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
17                 //如果读取的d_name为 . 或者.. 表示读取的是当前目录符和上一目录符,
18                 //则用contiue跳过,不进行下面的输出
19                 continue;
20             sprintf(childpath, "%s/%s", path, ent->d_name);
21             //如果非. ..则将 路径 和 文件名d_name 付给childpath, 并在下一行prinf输出
22             //printf("path:%s\n",childpath);原文链接这里是要打印出文件夹的地址
23             traverseFileandCount(childpath, dictionary);
24             //递归读取下层的字目录内容, 因为是递归,所以从外往里逐次输出所有目录(路径+目录名),
25             //然后才在else中由内往外逐次输出所有文件名
26         }
27         else
28             //如果读取的d_type类型不是 DT_DIR, 即读取的不是目录,而是文件,
29             //则直接输出 d_name, 即输出文件名
30         {
31             //cout<<ent->d_name<<endl; 输出文件名
32             //cout<<childpath<<"/"<<ent->d_name<<endl; 输出带有目录的文件名
33             sprintf(childpath, "%s/%s", path, ent->d_name);
34             //你可以唯一注意的地方是下一行
35             //目前childpath就是你要读入的文件的path了,可以作为你的读入文件的函数的参数
36             count(childpath, dictionary);//这里就是你的处理文件的接口!,
37         }
38     }
39 }

声明一点:这位同学加这么多注释并不是他的编程习惯,只是为了其他使用这段程序的同学更好懂。

我们来看一看这些注释,很明显,介绍这段程序功能的是注释而非代码!而且,每一句都有注释,降低了程序的可读性和简洁性。如果这段程序出现在我的代码当中,估计助教会疯掉。下面我稍微修改一下这个程序。

#define childPathLength 512//tranverse file recursively
void traverseFileandCount(char* path, struct alphaArray* dictionary)
{DIR *filePoint;struct dirent *fileInfo = BULL;char childPath[childPathLength];filePoint = opendir(path);memset(childPath,0,childPathLength);//init the childPath array with 0while((fileInfo=readdir(filePoint)) != NULL){if(isDirectory(fileInfo)){if(isPresentOrPriorDirectory(fileInfo))continue;sprintf(childpath, "%s/%s", path, ent->d_name);//create new path
            traverseFileandCount(childpath, dictionary);}else{sprintf(childpath, "%s/%s", path, ent->d_name);//create new path
            count(childpath, dictionary);}}
}bool isDirectory(struct dirent *fileInfo)
{return fileInfo->d_type&DT_DIR;
}bool isPresentOrPriorDirectory(struct dirent *fileInfo)
{return strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0;
}

View Code

首先,变量命名上我使用filePoint来表示指向文件的指针,使用fileInfo表示读取的文件信息。这样即使读者不知道DIR和dirent究竟是什么,也可以通过变量的名字猜出来变量的作用。如果此处使用注释,那么当读者看到下面的程序的时候(比如ent->d_type),可能会疑惑这个ent是什么,为了弄明白这个变量的意思,读者不得不返回定义的地方去看。相比之下,filePoint和fileInfo则清楚许多。

接着,我将ent->d_type&DT_DIR和strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0两句比较难懂的话包装成了两个函数,通过函数名来解释它们的作用。当读者读到isDirectory(fileInfo),更容易想到这个函数是用来判断这个文件路径是否是目录的,读到isPresentOrPriorDirectory(fileInfo)的时候,也会大致知道这个函数是判断这个文件路径是否是当前目录或者上一级目录。这样的做法虽然多出了两个小函数,但是省掉了文字注释,提高了程序的可读性,我觉得更好一点。

其他地方,我保留了初始化子路径数组的注释和创建新路径的注释,因为memset和sprintf这两个函数可能有些人不知道。我也试图将其包装成一个函数,但是由于要传输3个参数,这样很大的降低了可读性,所以没有这么做。

第五章  格式

这一章从垂直格式和水平格式两方面告诉读者如何构建一个良好的程序格式。

  • 垂直方向,采取从上到下的编程模式。被调用函数紧跟在被调用函数后面。
  • 水平方向,注意缩进要清晰,变量定义无需对齐,一行代码不要过长

下面看一下第一次个人作业我的主函数。

int main()
{char filePath[filePathLength];struct alphaArray dictionary[alphabet];struct wordStatisticsResult topFrequencyWord[topFrequencyWordNum];struct phaseStatisticsResult topFrequencyPhase[topFrequencyPhaseNum];dictionaryInit(dictionary);getFilePath(filePath);traverseFileandCount(filePath, dictionary);outputResult(dictionary);topFrequencyWordStatistics(dictionary, topFrequencyWord);topFrequencyPhaseStatistics(dictionary, topFrequencyPhase);outputToFile(filePath,topFrequencyWord, topFrequencyPhase);dictionaryDestroy(dictionary);return 0;
}

View Code

我现在很喜欢这种编程方法:在主函数里面将不同的功能分块,然后逐个实现,实现过程中不断细分功能模块。这样从上到下的编程很高效,很清楚,而且程序阅读起来也有条理。垂直格式上我自认为做得不错,可是水平格式上就丑了许多。

(page->wordArray + hash)->wordStr = (char*)realloc((page->wordArray + hash)->wordStr, sizeof(char)*((page->wordArray + hash)->strlength) * 2);

View Code

很丑是吧。(page->wordArray + hash)->wordStr实在是太长了,为什么不用tempWordStr代替呢?第一次作业时间有点紧张所以没有优化,下次我会注意的。

良好的垂直和水平格式会使你的代码更清晰美观。试想一下有良好格式的代码是一位三围比例合适的美女,你忍心自己写出的代码是一位身体比例不协调的丑女吗?所以,一定要在这方面下功夫,你的程序会因此赏心悦目。

第六章  对象和数据结构

由于Java还不怎么会用,所以这一部分也是囫囵吞枣的读了一遍。大致意思就是,尽量抽象类的接口,将类内部的情况隐藏起来,问了同学,说这样做可以减少耦合。

第七章  错误处理

同样,在c里面没用过try/catch进行错误处理,所以这一部分也不是很明白。只记得里面说先写try/catch语句定义好范围,然后编写细节部分。

:以上代码以及修改只是我现在能做到的水平,如有不足欢迎指点!

转载于:https://www.cnblogs.com/ustckx16/p/8719697.html

代码整洁之道读书笔记(Ch4-Ch7)相关推荐

  1. 代码整洁之道读书笔记——第一章:整洁代码

    软件质量,不仅仅依赖于项目架构和项目管理,同样重要的是代码质量!!! 序 神在细节之中,其实干什么事都一样,从小到大,一直明白一个道理:细节决定成败! 软件架构在开发中占据重要地位.其次,宏达建筑的最 ...

  2. 代码整洁之道-读书笔记之整洁的代码

    1.整洁代码 阅读本书有两个原因,第一,你是个程序员,第二,你想成为更好的程序员 1.1 要有代码 有人认为随着时代的发展,写代码不再是问题,我们更应该关注建模和需求 这句话后半句没有问题,因为语言在 ...

  3. 代码整洁之道 读书笔记

    第1章 整洁代码 1.1 要有代码 1.2 糟糕的代码      稍后等于永不 1.3 混乱的代价 假设前期不注意.后期的加入代码.改动效率都很低 1.3.1 华丽新设计 1.3.2 态度 1.3.3 ...

  4. 代码整洁之道-读书笔记1

    第一章 整洁代码 1.2糟糕的代码 糟糕的代码会毁掉一个公司,但是为什么会出现糟糕的代码? 可能是因为赶时间,如果花时间重构或者清理以前的代码,老板就会大发雷霆. 勒布朗法则:稍后等于用不. 1.3混 ...

  5. 代码整洁之道----读书笔记

    一.有意义的命名规则 二.优雅的函数 三.良好的注释 四.整齐的格式 转载于:https://www.cnblogs.com/k5bg/p/11063235.html

  6. 什么是好代码-代码整洁之道阅读笔记

    根据我所阅读的书<代码整洁之道>里的一句话: "衡量代码质量的唯一有效标准: WTF/min" 从哲学的角度讲,不得不说这真的很客观!!! 毕业不久的我也没有太多关于好 ...

  7. 不能将紧实的字段 绑定到_代码整洁之道【笔记】

    一.整洁代码 A.混乱的代价 1.有些团队在项目初期进展迅速,但有那么一两年的时间却慢去蜗行.对代码的每次修改都影响到其他两三处代码 2.花时间保持代码整洁不但有关效率,还有关生存 3.程序员遵从不了 ...

  8. 写好代码的注意点(代码整洁之道学习笔记)

    原则 写代码时注意,写好代码后,优化优化优化.重构重构重构 稍后等于永不(Later equals never) 命名 名副其实 避免误导 做有意义的区分 使用读的出来的名称 使用可搜索的名称 避免使 ...

  9. 软件架构整洁之道-读书笔记(3)

    第五部分:软件架构 第十五章:什么是软件架构 1.架构师是什么样的人? 首先软件架构师必须是能力最强的一群程序员,他们的代码产量可能不是最多的,但是他们必须不停的承接编程任务.如果不亲自承受因系统设计 ...

最新文章

  1. hdu2412 Party at Hali-Bula
  2. 皮一皮:顶尖黑客技术,10秒教学,不会你打我!
  3. 如何调用别人提供的API?
  4. Windows下Git上传项目代码记录
  5. Java里的容器存放的元素必须是1个对象.
  6. 【完结】12篇GAN的优化文章大盘点,浓浓的数学味儿
  7. Java如何解决mysql读写延迟_java中延迟任务的处理方式
  8. Cell|严景华/齐建勋首次发现新冠病毒进入细胞的详细分子细节
  9. 手写 Promise.race
  10. WPF中应用字体图标
  11. 如何测试并调试基于 NDK 的 Android 应用
  12. 【兼容】----常见浏览器兼容性问题与解决方案
  13. C#从入门到精通之第一篇: C#概述与入门
  14. 转【测试基础】测试计划如何编写
  15. AI Driven Testing的成熟度分析
  16. plt.text函数用法
  17. Kubernetes之secrets使用
  18. zfs编译之后,内核模块没更新的解决方案
  19. 【Excel】如何使用RegexString正则表达式
  20. python京东预约抢购_Python实现京东秒杀功能代码

热门文章

  1. 实习与就业--软件外包公司(一)
  2. 如何以创新驱动增长战略
  3. 大力金钢机器人_大力金刚机器人(威海)有限公司
  4. 基于 Amazon Amplify 构建自己的首个 iOS 应用程序(一)
  5. 怎么让游戏强制窗口化_游戏防上瘾,趁父母午睡时拍照片让你玩不成!
  6. 爬虫利器 xpath 实践案例
  7. windows phone7 mango 多人在线游戏
  8. 哈工大深圳计算机学院蔡聪怀,哈工大(深圳)计算机学院第一届光熙杯篮球赛圆满落幕...
  9. Qt实现计算器(包含算术运算和逻辑运算),纯干货,一步步超详细过程
  10. 从实验到投稿录用的一次经历(历时小半年)