《构建之法》 读书笔记

《构建之法》

读书笔记

娄雨禛 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/280378.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

边缘服务网格 osm-edge

本文篇幅稍长&#xff0c;阅读本文将了解以下内容&#xff1a;•什么是 osm-edge 及其产生背景•边缘计算与中心云计算的差异&#xff0c;以及带来的挑战•osm-edge 的设计及采用的技术•5 分钟快速体验边缘服务网格关于 osm-edgeosm-edge 是针对边缘计算环境设计的服务网格&am…

powershell获取exe文件返回值

一、目的 1.powershell能简单写一些小脚本&#xff0c;不需要exe开发这么笨重。 2.在windows实现某个特定功能&#xff0c;做成一个exe能方便查看管理。 二、实现 1.C# code 运行结束加入返回值 Environment.ExitCode 1; //自定义数字 2.powershell 调用并获取 需要增加…

自定义ViewGroup实现仿微信图片选择器

先求一个windows版本的gif制作工具&#xff01;&#xff01;&#xff01; 这个代码只是做了简单的选择功能&#xff0c;图片的压缩与展示没做。可以自己在接口的方法中去实现。 写这个自定义view的初衷是为了学习LayoutParams&#xff0c;参考博客&#xff1a;http://www.jians…

[PHP] 多表外连接性能测试及优化

原文&#xff1a;https://blog.csdn.net/tang_huan_11/article/details/41925639 版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请附上博文链接&#xff01;转载于:https://www.cnblogs.com/0616--ataozhijia/p/10364188.html

活水亭观书有感其一_如何将iPad置于“信息亭”模式,将其限制为单个应用程序...

活水亭观书有感其一An iPad makes a great “kiosk” device–a tablet restricted to one specific app for your home or small business. You can create a makeshift kiosk using the Guided Access feature, or enable Single App Mode for a true kiosk environment. iPa…

Shell字符串

一 介绍 shell程序的字符串可以用单引号&#xff0c;也可以用双引号&#xff0c;也可以不用&#xff0c;字符串是最有用的数据类型。 二 单引号 单引号字符串的限制&#xff1a; 》单引号内的内容原样输出&#xff0c;单引号字符串的变量是无效的。 》单引号内不能出现单引号&a…

powershell 特殊符号处理

显示字符串有双引号 “ 两个双引号产生一个双引号&#xff0c;这里不包括最外层的双引号。 $a"PowerShell" """My name is $a"",this program said." 使用转义字符 转义序列由反引号定义&#xff0c;也就是键盘F1下面与波浪线同键…

如何使用 System.Text.Json 序列化 DateTimeOffset 为 Unix 时间戳

在 .NET 中&#xff0c;日期和时间通常使用 DateTime 或 DateTimeOffset 来表示。这两种数据类型都可以表示日期和时间&#xff0c;但它们之间有一些明显的区别。DateTime 是不带时区信息的&#xff0c;而 DateTimeOffset 是带时区偏移量的&#xff0c;可以用来表示一个特定的时…

IDEA 学习笔记之 安装和基本配置

安装和基本配置&#xff1a; 下载&#xff1a;https://www.jetbrains.com/idea/download/#sectionwindows 下载Zip安装包&#xff1a; 基础知识&#xff1a; Eclipse的工作区IDEA的项目 Eclipse的项目IDEA的模块 修改信息提示&#xff1a;Alt/ 关闭当前窗口&#xff1a;CtrlW 自…

大厂高级前端面试题答案

阿里 使用过的koa2中间件https://www.jianshu.com/p/c1e... koa-body原理https://blog.csdn.net/sinat_1... 有没有涉及到Clusterhttp://nodejs.cn/api/cluster.... 介绍pm2PM2是node进程管理工具&#xff0c;可以利用它来简化很多node应用管理的繁琐任务&#xff0c;如性能监控…

js app缓存自动刷新_如何通过清除缓存来刷新App Store中的内容

js app缓存自动刷新Are you finding that you’re not seeing new apps on the App Store, or that updates to apps won’t go away even after you’ve installed the updates? Here’s a simple fix. 您是否发现自己在App Store上没有看到新的应用程序&#xff0c;或者即使…

Office Web APP预览如何去掉顶部版权标志“Microsoft Office Web Apps”

在Office Web APP的预览会涉及4中类型的文 件&#xff1a;Word、Excel、PowerPoint、PDF&#xff0c;不同的类型在预览时调用的文件是不一样的&#xff0c;其中Word和 PDF调用的是同一个文件。每个预览的页面都有对应的CSS文件&#xff0c;如下&#xff1a;PowerPointC:\Progra…

ORA-01400: 无法将 NULL 插入 (CHARGE_WQRL.SF_JMQTFY_T.BH)

[ERROR] JmCheckManageDaoImpl:901 - java.sql.SQLException: ORA-01400: 无法将 NULL 插入 ("CHARGE_WQRL"."SF_JMQTFY_T"."BH") 这个问题很多时候是没有为该表建立触发器&#xff08;trigger&#xff09;导致的&#xff0c;或者是序列&#xf…

用最少的代码,写一个智能会议APP(MAUI)

Xamarin和MAUI移动开发是.NET核心方向之一&#xff0c;国外社区资源非常丰富&#xff0c;影响力挺大的。而国内则资源很是欠缺&#xff0c;GitHub上的国产开源案例太少了。随着小米/美的/碧桂园等WPF招聘大户开始要求移动开发&#xff0c;不少群友都在找相关资源。这里分享一套…

word多级列表修改编号_如何更改在Word中的编号列表中使用的数字类型

word多级列表修改编号By default, Word uses Arabic numbers (1, 2, 3, etc.) when you create numbered lists. However, you can change the numbers to a different type or to letters. The character after the number or letter can also be changed. 默认情况下&#xf…

微服务学习笔记

微服务是一种架构模式或者说是一种架构风格&#xff0c;他提倡将单一的应用程序划分为一组小的服务&#xff0c;每个服务运行在其独立的进程中&#xff0c;服务之间互相协调&#xff0c;互相配合&#xff0c;为用户提供最终价值。dubbo与spring Cloud之间的区别之一是dubbo基于…

Go语言实时GC - 三色标记算法

前言 Go语言能够支持实时的&#xff0c;高并发的消息系统&#xff0c;在高达百万级别的消息系统中能够将延迟降低到100ms以下&#xff0c;很大一部分需要归功于Go高效的垃圾回收系统。 对于实时系统而言&#xff0c;垃圾回收系统可能是一个极大的隐患&#xff0c;因为在垃圾回收…

每小时50哈希——看看一个内部员工是如何摧毁整个公司网络的?

本文讲的是每小时50哈希——看看一个内部员工是如何摧毁整个公司网络的&#xff1f;&#xff0c;我们以前曾调查过黑客会通过连接在USB端口的正在充电的手机实施攻击&#xff0c;在这项研究中&#xff0c;我们重新审视了USB端口的安全性。我们发现&#xff0c;手机充电时&#…

推荐一款 在线+离线数据 同步框架 Dotmim.Sync

移动智能应用可以分为在线模式、纯离线模式与“在线离线”混合模式。在线模式下系统数据一般存储在服务器端的大中型数据库&#xff08;如 SQL Server、Oracle、MySQL 等&#xff09;&#xff0c;移动应用依赖于稳定可靠的网络连接&#xff1b;纯离线模式下系统数据一般存储在移…

如何在Windows 10中将您喜欢的设置固定到开始菜单

If you find you’re accessing the same settings over and over in Windows 10, you can add these settings to the Start menu as tiles for quick and easy access. We’ll show you how to do this. 如果发现要在Windows 10中反复访问相同的设置&#xff0c;则可以将这些…