《构建之法》

读书笔记

娄雨禛 PB16060356

第一部分 关于结对编程的体悟与实践

  在结对编程这一部分我曾讲过很多的注意点,比如代码变量命名风格、缩进风格、注释风格,前后语句次序风格,等等。然而这里还有一些新的东西。代码风格这个老掉牙的话题咱们先搁置不谈,而说说在结对编程中同样重要的其他注意点。

  代码复审

  代码复审是一门学问。良好而有序的复审将帮助我们快速排查问题和增进代码可读性,而低劣的复审则纯粹在浪费时间。这里拿我在个人项目中的代码举一个例子。

  1 void anothermain(char *fileString)
  2 {
  3     char *offset = fileString;
  4     char move;
  5     char temp;
  6
  7     int count;
  8     do
  9     {
 10         if(temp = *offset)
 11         {
 12             if(temp >= 32 && temp <= 126)
 13             {
 14                 Characters++;
 15                 if(temp >= 65 && temp <= 122)
 16                 {
 17                     if(temp >= 91 && temp <= 96)
 18                     {
 19                         offset++;
 20                         continue;
 21                     }
 22                     else
 23                     {
 24                         offset++;
 25                         word[0] = temp;
 26                     }
 27                 }
 28                 else if(temp >= 49 && temp <= 57)
 29                 {
 30                     offset++;
 31                     while(*offset >= 49 && *offset <= 57)
 32                     {
 33                         Characters++;
 34                         offset++;
 35                     }
 36                     while((*offset >= 49 && *offset <= 57) || (*offset >= 65 && *offset <= 90) || (*offset >= 97 && *offset <= 122))
 37                     {
 38                         Characters++;
 39                         offset++;
 40                     }
 41                     continue;
 42                 }
 43                 else
 44                 {
 45                     offset++;
 46                     continue;
 47                 }
 48             }
 49             else
 50             {
 51                 if(*offset == 10)
 52                     enterNum++;
 53                 offset++;
 54                 continue;
 55             }
 56         }
 57         else
 58             break;
 59         if(temp = *offset)
 60         {
 61             if(temp >= 32 && temp <= 126)
 62             {
 63                 Characters++;
 64                 if(temp >= 65 && temp <= 122)
 65                 {
 66                     if(temp >= 91 && temp <= 96)
 67                     {
 68                         offset++;
 69                         continue;
 70                     }
 71                     else
 72                     {
 73                         offset++;
 74                         word[1] = temp;
 75                     }
 76                 }
 77                 else if(temp >= 49 && temp <= 57)
 78                 {
 79                     offset++;
 80                     while(*offset >= 49 && *offset <= 57)
 81                     {
 82                         Characters++;
 83                         offset++;
 84                     }
 85                     while((*offset >= 49 && *offset <= 57) || (*offset >= 65 && *offset <= 90) || (*offset >= 97 && *offset <= 122))
 86                     {
 87                         Characters++;
 88                         offset++;
 89                     }
 90                     continue;
 91                 }
 92                 else
 93                 {
 94
 95                     offset++;
 96                     continue;
 97                 }
 98             }
 99             else
100             {
101                 if(*offset == 10)
102                     enterNum++;
103                 offset++;
104                 continue;
105             }
106         }
107         else
108             break;
109         if(temp = *offset)
110         {
111             if(temp >= 32 && temp <= 126)
112             {
113                 Characters++;
114                 if(temp >= 65 && temp <= 122)
115                 {
116                     if(temp >= 91 && temp <= 96)
117                     {
118                         offset++;
119                         continue;
120                     }
121                     else
122                     {
123                         offset++;
124                         word[2] = temp;
125                     }
126                 }
127                 else if(temp >= 49 && temp <= 57)
128                 {
129                     offset++;
130                     while(*offset >= 49 && *offset <= 57)
131                     {
132                         Characters++;
133                         offset++;
134                     }
135                     while((*offset >= 49 && *offset <= 57) || (*offset >= 65 && *offset <= 90) || (*offset >= 97 && *offset <= 122))
136                     {
137                         Characters++;
138                         offset++;
139                     }
140                     continue;
141                 }
142                 else
143                 {
144                     offset++;
145                     continue;
146                 }
147             }
148             else
149             {
150                 if(*offset == 10)
151                     enterNum++;
152                 offset++;
153                 continue;
154             }
155         }
156         else
157             break;
158
159         if(temp = *offset)
160         {
161             if(temp >= 32 && temp <= 126)
162             {
163                 Characters++;
164                 if(temp >= 65 && temp <= 122)
165                 {
166                     if(temp >= 91 && temp <= 96)
167                     {
168                         offset++;
169                         continue;
170                     }
171                     else
172                     {
173                         offset++;
174                         word[3] = temp;
175                         for(count = 4; isLetterOrNum(*offset); offset++, count++)
176                         {
177                             Characters++;
178                             word[count] = *offset;
179                         }
180                         word[count] = '\0';
181                         NumOfWords++;
182                         SolveTheWord(word);
183                     }
184                 }
185                 else if(temp >= 49 && temp <= 57)
186                 {
187                     offset++;
188                     while(*offset >= 49 && *offset <= 57)
189                     {
190                         Characters++;
191                         offset++;
192                     }
193                     while((*offset >= 49 && *offset <= 57) || (*offset >= 65 && *offset <= 90) || (*offset >= 97 && *offset <= 122))
194                     {
195                         Characters++;
196                         offset++;
197                     }
198                     continue;
199                 }
200
201                 else
202                 {
203                     offset++;
204                     continue;
205                 }
206             }
207             else
208             {
209                 if(*offset == 10)
210                     enterNum++;
211                 offset++;
212                 continue;
213             }
214         }
215         else
216             break;
217
218
219     }
220     while(*offset != '\0');
221 }

  这是我在进行匆忙的数据结构转型时书写的非常潦草的代码。虽然潦草,但还是包含了我的很多想法,比如,进肯能利用“流式操作”减少机器的循环流程,提高代码效率,尽管这样会使代码变得非常难读。很快,我就意识到了,这样的操作虽然节省了机器执行的时间,却大大浪费了我自己的时间。这段代码的可读性非常的差,以至于我自己常常被绕晕。其中杂乱的命名方式就不多说了,简直不忍卒读。由于是一次个人作业,又到了马上要提交的截止日期,我只关心这段程序的执行结果是否正常(作用是判断是否为一个单词并进行储存),因此在最后输出结果正确之下,我就没有再对它进行优化和修改。

  而如果这换成一次结对编程,将会怎样呢?

  是的,代码复审就登场了。那么下面,我就结合这个例子,简要说说应该怎样利用复审,改进代码。

  Step1:“自己改+你说我看”:不符合共同协定的编码风格的地方,一律修改

  我们需要在一开始就商定好代码风格,比如哪些地方需要换行,变量的命名规则等等。

  然后,先过自己这一关——自己对代码进行修改。比如在上面的例子中,函数名为anothermain,这是什么鬼意思?这种根本不知其所以然的命名,必须根除。还有像enternum这样的变量,也会让人摸不着头脑,应该改为characterNum这种规范的命名。

  在自己认为没有大毛病之后,还需要对方对自己进行挑错。在这里,挑错要注意一个原则:不要在鸡蛋里挑骨头,要本着找出有意义的错误的原则,认真查错。比如,“这样的函数命名会不会和以后的命名冲突,从而引起歧义?”

  Step2:探讨潜在的逻辑问题,预防“逻辑灾害”的发生

  上面这段代码的逻辑完全是给机器看的,对于人类阅读者来说,几乎看不下去。这时候,虽然程序在执行的时候结果没有问题,代码还是得改。把从头执行到尾的“流式操作”改为稍微慢一些却容易阅读地多的代码,我们可以增加一些执行很小功能的函数,然后反复调用它们。这样,将得到容易阅读得多的代码。

  Step3:修改完后也不松懈,继续进行经验总结

  总结这个步骤,是让我们“事半功倍”的不二捷径。它不容忽视

  在修改之后,代码变成了下面这样。

 1 void WordCheck(FILE *fp)
 2 {
 3         bool stop = false;
 4         bool isEmpty = false;
 5         char ch;  // ch gets the character one by one
 6         short check = 0;  // to check if the first four characters are letters
 7         short i = 0;
 8
 9         ch = fgetc(fp);
10         if(ch == EOF)
11                  isEmpty = true;
12
13         for(; !stop; ch = fgetc(fp))  // if it is not the end of the text
14         {
15                  if(ch >= 32 && ch <= 126)
16                          characterNum++;
17                  if(ch == '\n')
18                          lineNum++;
19
20                  if(check < 4)  // to check the first four characters
21                  {
22                          if(ch == EOF)
23                          {
24                                   stop = true;
25                                   if(isEmpty == false)
26                                           lineNum++;
27                          }
28
29                          else if(IsLetter(ch) == true)
30                          {
31                                   ++check;
32                                   tempWord[i] = ch;
33                                   ++i;  // search for the next
34                          }
35                          else
36                          {
37                                   i = 0;
38                                   check = 0;
39                                   ClearTemp();
40                          }
41                  }
42                  else  // first four characters are all letters, ready to store
43                  {
44                          if(IsSeparator(ch) || ch == EOF)  // have met a separator, store the word
45                          {
46                                   i = 0;  // roll back to the beginning in the next search
47                                   check = 0;  // roll back to the beginning in the next search
48
49                                   wordNum++;  // have found another word
50                                   StoreWord();  // store the word
51                                   ClearTemp();  // prepare for the next search
52
53                                   if(ch == EOF)
54                                   {
55                                           stop = true;
56                                           if(isEmpty == false)
57                                                   lineNum++;
58                                   }
59                          }
60
61                          else  // have not met a separator, keep searching
62                          {
63                                   tempWord[i] = ch;
64                                   ++i;  // search for the next
65                          }
66                  }
67         }
68 }

  根据运行结果显示,修改后的代码运行时间是原来的两倍,但我们却获得了清爽得多的函数。这应该是一个好的结果,至少在对速度的要求不高的情况下。

  然而,如果我们进行过程序优化,就会发现,这是一个很令人诧异的结果——代码的运行时间变成了原来的两倍!这究竟是怎么回事呢?

  原来,在新的函数中,我采取了反复调用子函数的措施来精简代码。而在我的子函数中,我为了继续精简代码,又套用的新的子函数,这里进行了两次的套用。而在判断是否为一个单词并进行储存的时候,这种层层调用的次数是超乎想象的。正是这里头的反复嵌套,大大拖慢了程序的运行速度。

  接下来是进行修改,在不损失代码简洁性的前提下进行代码优化,其中主要是性能优化。我首先要做的是把两层的函数嵌套改为一层

  注意,在这里我并没有把子函数放上来,是出于阅读的简洁性和直观性——直接把我的实践结论告诉大家,而不是用代码和大家继续兜圈子。

  通过将两层的函数嵌套改为一层,我的子函数从原来的16行变成了42行,可以说复杂了不少,但接下来我们看一下运行效率。

  代码的运行时间大约是最初运行时间的 1.4 倍

  这个结果比第一次优化的结果好了不少,但没有达到本次代码优化的最终目的——在不损失性能的前提下进行感官上阅读体验的提升。当然,我也已经知晓了代码变慢的原因——函数嵌套和函数调用花去了太多无用的时间,接下来的优化步骤也明晰了。

转载于:https://www.cnblogs.com/RainLou/p/9008681.html

《构建之法》 读书笔记相关推荐

  1. 读书笔记 | 墨菲定律

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  2. 读书笔记 | 墨菲定律(一)

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  3. 洛克菲勒的38封信pdf下载_《洛克菲勒写给孩子的38封信》读书笔记

    <洛克菲勒写给孩子的38封信>读书笔记 洛克菲勒写给孩子的38封信 第1封信:起点不决定终点 人人生而平等,但这种平等是权利与法律意义上的平等,与经济和文化优势无关 第2封信:运气靠策划 ...

  4. 股神大家了解多少?深度剖析股神巴菲特

    股神巴菲特是金融界里的传奇,大家是否都对股神巴菲特感兴趣呢?大家对股神了解多少?小编最近在QR社区发现了<阿尔法狗与巴菲特>,里面记载了许多股神巴菲特的人生经历,今天小编简单说一说关于股神 ...

  5. 2014巴菲特股东大会及巴菲特创业分享

     沃伦·巴菲特,这位传奇人物.在美国,巴菲特被称为"先知".在中国,他更多的被喻为"股神",巴菲特在11岁时第一次购买股票以来,白手起家缔造了一个千亿规模的 ...

  6. 《成为沃伦·巴菲特》笔记与感想

    本文首发于微信公众帐号: 一界码农(The_hard_the_luckier) 无需授权即可转载: 甚至无需保留以上版权声明-- 沃伦·巴菲特传记的纪录片 http://www.bilibili.co ...

  7. 读书笔记002:托尼.巴赞之快速阅读

    读书笔记002:托尼.巴赞之快速阅读 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<快速阅读>之后,我们就可以可以快速提高阅读速度,保持并改善理解嗯嗯管理,通过增进了解眼睛和大脑功能 ...

  8. 读书笔记001:托尼.巴赞之开动大脑

    读书笔记001:托尼.巴赞之开动大脑 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<开动大脑>之后,我们就可以对我们的大脑有更多的了解:大脑可以进行比我们预期多得多的工作:我们可以最 ...

  9. 读书笔记003:托尼.巴赞之思维导图

    读书笔记003:托尼.巴赞之思维导图 托尼.巴赞的<思维导图>一书,详细的介绍了思维发展的新概念--放射性思维:如何利用思维导图实施你的放射性思维,实现你的创造性思维,从而给出一种深刻的智 ...

  10. 产品读书《滚雪球:巴菲特和他的财富人生》

    作者简介 艾丽斯.施罗德,曾经担任世界知名投行摩根士丹利的董事总经理,因为撰写研究报告与巴菲特相识.业务上的往来使得施罗德有更多的机会与巴菲特亲密接触,她不仅是巴菲特别的忘年交,她也是第一个向巴菲特建 ...

最新文章

  1. ruby on rails_我成为了Ruby on Rails和React的贡献者,你也可以
  2. 2020图灵年度好书大赏 | 15周年视频纪念版
  3. 跨镜追踪“智”眼识人技术策略研究及实现
  4. Linux 之alias 命令别名
  5. Oracle 创建dblink
  6. 第十二届蓝桥杯JavaB组省赛H题 杨辉三角形
  7. 将winform窗体钉在桌面上
  8. PHP数组合并+与array_merge的区别分析 对多个数组合并去重技巧
  9. 符号库匹配不对的原因_整理了几种离合器打滑的原因,再安装调试时可别弄错了...
  10. 详细解读Python中的__init__()方法
  11. 三大代码审计工具对比
  12. 迅捷PDF虚拟打印机怎么保存文件
  13. 普元EOS7.x及以下版本升级Tomcat8
  14. 近期14个“AI产品经理”职位JD推荐(覆盖北京、上海、深圳、成都、重庆、杭州)
  15. 基于WebUploader的文件上传插件
  16. 将java 文件夹里面的.java 文件 拷贝到temp文件夹下,并且修改后缀名为.txt
  17. vue 动态修改页面的meta
  18. synchronizedReentrantLock乐观锁悲观锁(Java线程安全实现)JVM9
  19. locale 国际化配置(springboot)
  20. 为什么戴耳机听歌时候耳朵痛?那是你没用到对的耳机

热门文章

  1. java异常类层次结构图
  2. Java中三种Set的实现类的用法和区别
  3. 开发工具:收集12 个顶级 Bug 跟踪工具,值得收藏!
  4. horizon服务主要模块_Horizon Workspace 快速部署指南三(配置Workspace数据模块)
  5. python刷题用leet_GitHub - Yolymaker/leetcode-python: 利用python分类刷leetcode题目
  6. html ajax 数据传送,HTML AJAX 简单数据JS
  7. linux内核开发基础(linux内核源码、树莓派源码编译、SD卡挂载)
  8. mysql 多字节编码漏洞_phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)
  9. 远程控制工具_不要让您的工具控制您
  10. Github上最受欢迎的Python轻量级框架Flask入门