《構建之法》 讀書筆記

《構建之法》

讀書筆記

婁雨禛 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.pswp.cn/news/280378.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/280378.shtml
英文地址,請注明出處:http://en.pswp.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;則可以將這些…