作業三: 代碼規範、代碼複審、PSP
代碼規範
代碼規範的重要性
一、規範的代碼可以促進團隊合作
一個項目大多都是由一個團隊來完成,如果沒有統一的代碼規範,那麼每個人的代碼必定會風格迥異。且不說會存在多個人同時開發同一子產品的情況,即使是分工十分明晰的,等到要整合代碼的時候也有夠頭疼的了。大多數情況下,并非程式中有複雜的算法或是複雜的邏輯,而是去讀别人的代碼實在是一件痛苦的事情。統一的風格使得代碼可讀性大大提高了,人們看到任何一段代碼都會覺得異常熟悉。顯然的,規範的代碼在團隊的合作開發中是非常有益而且必要的。
二、規範的代碼可以減少bug處理
很多IT人士将程式員比做民工,這也的确非常的形象。就像剛才提到的,複雜的算法或邏輯隻占項目中很小的比例,大多僅僅是壘代碼的工作。可是越是簡單,測試的bug反而是越多,而且是無窮無盡的bug。這裡很大的程度上是由于代碼不規範所緻。沒有規範的對輸入輸出參數的規範,沒有規範的異常處理,沒有規範的日志處理等等,不但導緻了我們總是出現類似空指針這樣低級的bug而且還很難找到引起bug的原因。相反,在規範的開發中,bug不但可以有效減少,查找bug也變得輕而易舉。規範不是對開發的制約,而确實是有助于提高開發效率的。
三、規範的代碼可以降低維護成本
随着我們項目經驗的累積,會越來越重視後期維護的成本。而開發過程中的代碼品質直接影響着維護的成本。是以,我們不得不從開發時便小心翼翼。在第一點中曾提到,規範的代碼大大提高了程式的可讀性,幾乎所有的程式員都曾做過維護的工作,不用多說,可讀性高的代碼維護成本必然會大大降低。但是,維護工作不僅僅是讀懂原有代碼,而是需要在原有代碼基礎上作出修改。我們可以先想像沒有統一風格的情況下,A完成開發以後,B進行維護加一段代碼,過一段時間C又加一段代碼。。。。。。直到有一天X看到那一大堆亂碼想死的心都有了,維護也就進行不下去了。是以,統一的風格有利于長期的維護。另外,好的代碼規範會對方法的度量、類的度量以及程式耦合性作出限制。這樣不會出現需要修改一個上千行的方法或者去擴充一個沒有接口的類的情況。規範的代碼對程式的擴充性提高,無疑也是對維護人員的一個獎勵。
四、規範的代碼有助于代碼審查
我個人是比較贊同進行代碼審查的,這樣可以及時糾正一些錯誤,而且可以對開發人員的代碼規範作出監督。團隊的代碼審查同時也是一個很好的學習機會,對成員的進步也是很有益的。但是,開發随意,加重的代碼審查的工作量及難度,并且使得代碼審查工作沒有根據,浪費了大量的時間卻收效甚微。代碼規範不僅使得開發統一,減少審查拿督,而且讓代碼審查有據可查,大大提高了審查效率和效果,同時代碼審查也有助于代碼規範的實施。一舉多得,何樂而不為呢。
五、養成代碼規範的習慣,有助于程式員自身的成長
即使明白代碼規範的好處,但是有的迫于項目壓力,有的因為繁瑣的規範作出很多額外的工作,更有的不重視維護的問題,而很難貫徹代碼規範。那麼,我們需要了解,規範開發最大的受益人其實是自己!你有沒有花費很多的時候查找自己的代碼呢?尤其是出現bug的時候需要逐行的debug?自己寫的代碼亂了頭緒的确實也見了不少。我們應該做的就是規範開發,減少自己出現的錯誤。很多時候項目的壓力一部分也是由于前期開發中遺留的衆多的問題。還有的人覺得自己可以完成高難度的算法,就認為自己能力很強,不把規範放在眼裡。很多人确實是這樣,追求個性,大概讓别人看他的代碼一頭霧水更覺得得意。殊不知複雜的算法确實可以展現你個人的邏輯能力,但是絕不代表你的開發水準。我們知道一些開源項目,一些大師級人物寫得程式都是極其規範的。并非規範了就代表高水準,實際上是規範的代碼更有利于幫助你了解開發語言了解模式了解架構,能夠幫助你快速提升開發水準。不明白這點,即使你寫的再高明的算法,沒準哪天也被當作亂碼别處理掉。記住!每天壘亂碼(或許你不覺得,但是大多時候在别人眼中确實就是亂碼)并不能使你獲得更多的進步,相反要達到高水準的程式員,養成良好的開發習慣是絕對必需的。不要沉迷表面的得失,看似無用的東西要經過慢慢的累積由量變達到質變的時候,你才能感受到其價值所在。
代碼複審
和我搭檔的是林吉慶同學,以下是他上次作業階段三的代碼,讓我們邊看邊發現問題。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace 随機生成_控制台
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 Console.Write("請選擇模式(1、分數 2、整數 3、混合):");//模式選擇
14 String numType = Console.ReadLine();
15 switch (numType)
16 {
17 case "1": Fraction(); break;
18 case "2": Integer(); break;
19 case "3": Mixture(); break;
20 default: Console.WriteLine("輸入有誤!");break;
21 }
22 Console.ReadLine();
23 }
24 public static void Fraction()//分數模式
25 {
26 Console.Write("請輸入生成題目數量:");
27 String strnum = Console.ReadLine();//接收字元
28 int num = Convert.ToInt32(strnum);//轉義
29
30 Console.Write("請輸入生成數字上限:");
31 String strmaxnum = Console.ReadLine();//接收字元
32 int maxnum = Convert.ToInt32(strmaxnum);//轉義
33
34 Random R = new Random();
35 int symbol = 0;//運算符
36 int n1, n2, m1, m2;//分數
37 for (int i = 0; i < num; i++)//循環輸出
38 {
39 n1 = R.Next(1, maxnum);
40 n2 = R.Next(1, maxnum);
41 m1 = R.Next(1, maxnum);
42 m2 = R.Next(1, maxnum);
43 symbol = R.Next(0, 4);
44 if (n1 < n2)
45 {
46 Console.Write(n1 + "/" + n2);
47 }
48 else if (n1 == n2)
49 {
50 Console.Write(1);
51 }
52 else
53 {
54 Console.Write(n2 + "/" + n1);
55 }
56 switch (symbol)
57 {
58 case 0: Console.Write("+"); break;
59 case 1: Console.Write("-"); break;
60 case 2: Console.Write("*"); break;
61 case 3: Console.Write("/"); break;
62 }
63 if (m1 < m2)
64 {
65 Console.WriteLine(m1 + "/" + m2 + "=");
66 }
67 else if (m1 > m2)
68 {
69 Console.WriteLine(m2 + "/" + m1 + "=");
70 }
71 else
72 {
73 Console.WriteLine(1 + "=");
74 }
75 }
76 }
77 public static void Integer()//整數模式
78 {
79 Console.Write("請輸入生成題目數量:");
80 String strnum = Console.ReadLine();//接收字元
81 int num = Convert.ToInt32(strnum);//轉義
82
83 Console.Write("請輸入生成數字上限:");
84 String strmaxnum = Console.ReadLine();//接收字元
85 int maxnum = Convert.ToInt32(strmaxnum);//轉義
86
87 Random R = new Random();
88 int symbol = 0;//運算符
89 for (int i = 0; i < num; i++)//循環輸出
90 {
91 Console.Write(R.Next(1, maxnum));
92 symbol = R.Next(0, 4);
93 switch (symbol)
94 {
95 case 0: Console.Write("+"); break;
96 case 1: Console.Write("-"); break;
97 case 2: Console.Write("*"); break;
98 case 3: Console.Write("/"); break;
99 }
100 Console.WriteLine(R.Next(1, maxnum) + "=");
101 }
102 }
103 public static void Mixture()//混合模式
104 {
105 Console.Write("請輸入生成題目數量:");
106 String strnum = Console.ReadLine();//接收字元
107 int num = Convert.ToInt32(strnum);//轉義
108
109 Console.Write("請輸入生成數字上限:");
110 String strmaxnum = Console.ReadLine();//接收字元
111 int maxnum = Convert.ToInt32(strmaxnum);//轉義
112
113 Random R = new Random();
114 int symbol = 0;//運算符
115 int n1, n2, m1, m2;//分數
116 for (int i = 0; i < num; i++)//循環輸出
117 {
118 if (i < (num / 2))
119 {
120 Console.Write(R.Next(1, maxnum));
121 symbol = R.Next(0, 4);
122 switch (symbol)
123 {
124 case 0: Console.Write("+"); break;
125 case 1: Console.Write("-"); break;
126 case 2: Console.Write("*"); break;
127 case 3: Console.Write("/"); break;
128 }
129 Console.WriteLine(R.Next(1, maxnum) + "=");
130 }
131 else
132 {
133 n1 = R.Next(1, maxnum);
134 n2 = R.Next(1, maxnum);
135 m1 = R.Next(1, maxnum);
136 m2 = R.Next(1, maxnum);
137 symbol = R.Next(0, 4);
138 if (n1 < n2)
139 {
140 Console.Write(n1 + "/" + n2);
141 }
142 else if (n1 == n2)
143 {
144 Console.Write(1);
145 }
146 else
147 {
148 Console.Write(n2 + "/" + n1);
149 }
150 switch (symbol)
151 {
152 case 0: Console.Write("+"); break;
153 case 1: Console.Write("-"); break;
154 case 2: Console.Write("*"); break;
155 case 3: Console.Write("/"); break;
156 }
157 if (m1 < m2)
158 {
159 Console.WriteLine(m1 + "/" + m2 + "=");
160 }
161 else if (m1 > m2)
162 {
163 Console.WriteLine(m2 + "/" + m1 + "=");
164 }
165 else
166 {
167 Console.WriteLine(1 + "=");
168 }
169 }
170 }
171 }
172 }
173 }
在看到他的代碼的第一眼給我的感覺就是格式相當的整齊,使讀者可以很好的了解程式員想要表達的思想,而且在有的地方還加上了一些注釋。但是在對他的程式進行運作測試後也發現了一些問題,這個混合模式為既有全為整數也有全為分數的,但沒有一個式子中分數和整數并存的,而且也沒有做出答案判斷,還需有待加強。
PSP四則運算耗時
PSP2.1 | Personal Software Process Stages | Time(min) |
Planning | 計劃 | |
|
| 180 |
Development | 開發 | |
|
| 20 |
|
| 15 |
|
| |
|
| 5 |
|
| 60 |
|
| 30 |
| | |
|
| |
Reporting | 報告 | |
|
| |
|
| 10 |
|
|