一個大氣又可愛的標題
一、預估與實際
PSP2.1 | Personal Software Process Stages | 預估耗時(分鍾) | 實際耗時(分鍾) |
---|---|---|---|
Planning | 計划 | ||
• Estimate | • 估計這個任務需要多少時間 | 20 | 20 |
Development | 開發 | ||
• Analysis | • 需求分析 (包括學習新技術) | 50 | 100 |
• Design Spec | • 生成設計文檔 | 20 | 30 |
• Design Review | • 設計復審 | 20 | 30 |
• Coding Standard | • 代碼規范 (為目前的開發制定合適的規范) | 60 | 100 |
• Design | • 具體設計 | 60 | 100 |
• Coding | • 具體編碼1 | 150 | 120 |
• Code Review | • 代碼復審 | 60 | 60 |
• Test | • 測試(自我測試,修改代碼,提交修改) | 100 | 150 |
Reporting | 報告 | ||
• Test Repor | • 測試報告 | 30 | 30 |
• Size Measurement | • 計算工作量 | 20 | 30 |
• Postmortem & Process Improvement Plan | • 事后總結, 並提出過程改進計划 | 30 | 60 |
合計 | 720 |
二、需求分析
我通過查詢小學教學大綱的方式了解到,小學一年級加減法有如下的幾個特點:
-
加法有兩種形式:
(1)個位數 + 個位數
(2)個位數 + 整十數 -
減法也有兩種形式:
(1)整十數 - 個位數
(2)個位數 - 個位數 -
結果不能為負數
經過分析,我認為,這個程序應當:
- 結果不能為負數,也不能大於100
- 被減數必須大於減數
- 形如 A + B,A和B都為個位,或其中之一為整十數
- 形如 A - B ,A應該大於等於B
小學二年級乘除法有如下的幾個特點:
- 乘法只有表內乘法
- 除法也是表內除法
- 除和商都是個位數
經過分析,我認為,這個程序應當:
- 除數不能為0
- 被除數應該大於或等於除數
- 積不能大於100
- 除和商都是個位數
三、設計
1. 設計思路
說明你如何設計這個程序
比如:
-
關鍵函數的流程圖是怎樣的?
-
算法的關鍵的關鍵是什么?
- 需要對用戶的“錯誤輸入”進行提醒,並結束程序。
- 需要根據不同的運算符號,制定不同的隨機數生成規則。
2. 實現方案
寫出具體實現的步驟
比如:
- 准備工作:先在Github上創建倉庫,克隆到本地,在本地新建PSP1302文件夾
- 技術關鍵點:
- 思考應該采用哪種設計模式,這種模式是否便於后續的功能擴展和修改。
- 代碼的結構該怎么構建
- 針對不同的運算符號,結合用戶需求,制定不同的隨機數生成規則
- 用正則表達式能更容易解決用戶的錯誤輸入
四、編碼
請說明你如何按照設計思路進行編碼,並記錄你在開發中遇到的問題,與解決過程
1. 調試日志
記錄編碼調試的日志,請記錄下開發過程中的 debug 歷程
比如:
-
由於用戶輸入的參數是輸入給主方法的args數組,則用戶輸入參數的個數不為2時,會拋異常。
解決方法:在主方法的開頭新增對“args.length"的判斷,若args不為“1”或“2”則提示用戶輸入錯誤。
-
除法運算中,因生成的除數為0,會拋異常。
解決方法:將代碼“random.nextInt(10)”修改為“1+ random.nextInt(9)”,這樣隨機數生成的范圍就從[0-9]變成了[1-9],就不會出現除數為0的情況
2. 關鍵代碼
//RandomNumber是父類,調用工廠的靜態方法,根據運算符號的不同,返回對應的子類對象
RandomNumber ran = RandomNumberFactory.createRan(bean.getSymbol());
ran.createRandomAandB(bean);
public class RandomNumberFactory {
public static RandomNumber createRan(String symbol) {
//根據不同的運算符號,返回對應的“隨機數生成”子類
RandomNumber ran = null;
switch (symbol) {
case "+":
ran = new RandomOfAdd();
break;
case "-":
ran = new RandomOfSubtract();
break;
case "*":
ran = new RandomOfMultiply();
break;
case "/":
ran = new RandomOfDiv();
break;
}
return ran;
}
}
RandomNumber是父類,它有四個子類,分別是“加減乘除”的隨機數生成類,有着各自的隨機數生成規則。“RandomNumberFactory”是工廠類,該段代碼運用了“簡單工廠”的設計模式,工廠類可以根據運算符號的不同,實例化出合適的對象,通過多態,返回相對應的子類對象。
“簡單工廠”的特點:專門定義一個類來負責創建其他類的實例,被創建的實例通常都具有共同的父類。
主要優點:將對象的創建過程進行了封裝,用戶不需要知道具體的創建過程,只需要調用工廠類獲取對象即可。
3. 代碼規范
請給出本次實驗使用的代碼規范:
- 第一條:不使用“Magic Number”,都用有意義的英文名進行變量的命名
- 第二條:不使用拼音進行命名
- 第三條:采用駝峰式命名規則,類名以大寫字母開頭,變量名和方法名以小寫字母開頭
- 第四條:代碼中的命名均不能以下划線或美元符號開始,也不能一下划線或美元符號結束。
- 第五條:左小括號和字符之間不出現空格;同樣的,有小括號和字符之間也不出現空格。
並人工檢查代碼是否符合規范
五、測試
測試用例 | 預期結果 | 實際結果 |
---|---|---|
dfsfh 1 | 輸入有誤,程序結束! | 同預期結果 |
10 a | 輸入有誤,程序結束! | 同預期結果 |
-123 2 | 輸入有誤,程序結束! | 同預期結果 |
001 2 | 輸入有誤,程序結束! | 同預期結果 |
34567 | 輸入有誤,程序結束! | 同預期結果 |
10 1 | 生成10道題的txt文本,並且是一年級的加減題 | 同預期結果 |
100 | 生成100道題的txt文本,並且是一年級的加減題 | 同預期結果 |
10 2 | 生成10道題的txt文本,並且是二年級的加減題 | 同預期結果 |
六、總結
請總結過程中的教訓和經驗,思考
-
是否使用了“軟件開發的基本策略:分而治之”,是否需要重構
采用了分而治之的策略,基本做到了”一個類只實現一個功能“,將各個類的功能細分,這樣對代碼進行修改或者擴展時可能會相對容易些。
對於重構了解的不多,但本程序的中類分的較細,避免了過大的類和過長的方法,代碼的耦合性較低,並把大部分的成員變量都存儲在Bean類中,並且都設為private,一定程度上提高了封裝性。
-
“高質量的設計、規范的編碼以及有效的測試是保證軟件產品質量的三個重要方面”,你是否采用了相關的手段,是否需要重構
-
采用了“簡單工廠”,在於重構方面的理解還需要加強
-
在測試方面,對於用戶的錯誤輸入,應該給更詳細的提示,告訴用戶到底哪輸入錯了
-
在“高質量的設計”方面,測試了代碼的運行時間,經測試,出一萬道題(暫時撤銷了題目數的限制)所花費的時間為2000ms,最后發現其實大部分時間都花在了字符串拼接上,因為我的代碼中每生成一道題,就會執行一次
-
String s1 = s1 + “新增字符串”;
由於String帶有final的關鍵字,所以程序把大部分時間浪費在字符串的創建和銷毀上。當我用StringBuffer代替String后,發現出一萬道題代碼的總時長從2000多毫秒降低到了40毫秒,如此恐怖的效率提升確實讓我震驚。如此清晰地認識到StringBuffer和String在“拼接字符串”上效率的差別也許就是我這次編程的最大收獲。
-