四則運算器實現
這個作業屬於哪個課程 | 軟體工程 |
---|---|
這個作業要求在哪裡 | 四則運算 |
這個作業的目標 | 總結成敗得失,分享經驗,總結教訓 |
你可以在GitHub上找到本專案並下載所有的演算法和檢視日誌
Slave
使用手冊
計劃
第二次使用PSP方法進行軟體實現,本次程式設計吸取上一次的經驗,在實現一個模組,立即生成測試檔案對模組進行測試,可以降低後期bug修改成本
開發
需求分析
功能需求:使用者需要一個四則運算生成器
開發環境:Python3環境下進行開發
產品功能:可以使用-n來控制題目生成個數
-r可以控制數值範圍
可以對比題目與答案對錯
開發須知:生成的題目中計算過程不能產生負數
生成的題目中如果存在形如e1÷ e2的子表示式,那麼其結果應是真分數
每道題目中出現的運算子個數不超過3個
程式一次執行生成的題目不能重複
特色說明
專案基本實現了所有要求
1.其中真分數和假分數的實現及其複雜,我能查到的方法也只是在每次計算把假分數轉換為真分數的表示,在列印的時候又轉換回去
2.實現了簡單的UI介面,這部分花了不少時間學習如何使用tkinter庫
3.實現了對比器和生成器的功能,只是簡單呼叫了之前實現的邏輯
4.使用中文除號代替了英文除號,這使得每次運算都要轉換回去
5.可以支援生成10000及以上的題目數量
6.還可以自定義範圍(可以不指定預設為10)
7.在異常操作後都會有彈窗提醒使用者
介面設計
考慮到需求主要有兩個:生成隨機四則運算和對比題目與答案
此處僅給出介面大致使用,具體程式碼和難點分析請檢視另一個手冊
生成器介面設計
1.用於傳入範圍隨之生成隨機數
generate_number(min_num, max_num):
2.透過接受題目數量和範圍,呼叫隨機數生成函式來進一步生成表示式
generate_exercises(num_exercises, min_num, max_num):
3.對傳入的表示式字串進行轉換計算得到答案,從而把表示式和答案都寫入檔案中
write_to_files(exercises):
對比器介面設計
1.將假分數的形式轉換為普通分數的形式
convert_mixed_fraction(fraction):
2.將表示式中的每個運算元都轉換為普通分數的形式
convert_mixed_fraction_in_expression(expression):
3.對比函式主實現,具體邏輯參考另一個手冊
compare_answers(exercise_file, answer_file, output_file):
UI設計
嘗試以圖形化替代命令列
第一部分:生成器的設計
主體函式
open_generator():用於構建一個圖形化介面,並且實現生成器的呼叫
go_back():使用者按下返回按鈕可以實現返回主介面操作
display_answers_and_notify():實現了將答案檔案讀取並列印在圖形化介面的操作
generate_and_display_exercises():實現了對錶達式檔案讀取並列印的操作
第二部分:對比器的設計
主題函式
open_comparator():用於構建一個圖形化介面,用於對比器的呼叫
go_back():使用者按下返回按鈕可以實現返回主介面操作
run_comparator():使得使用者能透過OS的操作選擇輸入的檔案,省去了對絕對或相對路徑的轉換判斷
open_file_dialog():會被run_comparator()函式呼叫來處理選擇的檔案路徑,便於對比
測試執行
僅僅針對圖形化之前進行測試,圖形化測試沒有意義,此處僅給出一個測試程式碼
其他測試可以在手冊中找到
這個測試是針對compare函式中用於處理真分數與假分數的兩個函式,其對compare函式有很大影響
import unittest
from compare import convert_mixed_fraction, convert_mixed_fraction_in_expression
class TestConversionFunctions(unittest.TestCase):
def test_convert_mixed_fraction(self):
self.assertEqual(convert_mixed_fraction("1’1/2"), "(1 + 1/2)")
self.assertEqual(convert_mixed_fraction("2"), "2")
def test_convert_mixed_fraction_in_expression(self):
self.assertEqual(convert_mixed_fraction_in_expression("1’1/2 + 2"), "(1 + 1/2) + 2")
self.assertEqual(convert_mixed_fraction_in_expression("2 - 1’1/2"), "2 - (1 + 1/2)")
if __name__ == '__main__':
unittest.main()
結果如下:
效能分析
這個部分很難做,我一開始考慮如何將兩個UI放在兩個檔案中,再在主檔案中呼叫,我發現這樣做使得主檔案呼叫附檔案,附檔案再呼叫主檔案,這樣會產生巨大延長以及無法啊正常顯示UI的bug,於是我將UI的實現都放入一個檔案中
更改前
兩個檔案儲存兩個UI,之後在一個檔案中呼叫使得UI出現問題即無法正常返回主介面
更改後
給出函式耗費時間
可見主函式使用時間最長
給出函式呼叫圖
這次專案各處執行很快,便沒有使用模組測試耗費時間和最佳化執行效率
PSP表
*PSP2.1* | *Personal Software Process Stages* | *預估耗時(分鐘)* | *實際耗時(分鐘)* |
---|---|---|---|
Planning | 計劃 | 60 | 30 |
· Estimate | · 估計這個任務需要多少時間 | 160 | 140 |
Development | 開發 | 500 | 360 |
· Analysis | · 需求分析 (包括學習新技術) | 200 | 300 |
· Design Spec | · 生成設計文件 | 60 | 60 |
· Design Review | · 設計複審 | 20 | 30 |
· Coding Standard | · 程式碼規範 (為目前的開發制定合適的規範) | 5 | 5 |
· Design | · 具體設計 | 60 | 80 |
· Coding | · 具體編碼 | 200 | 150 |
· Code Review | · 程式碼複審 | 60 | 30 |
· Test | · 測試(自我測試,修改程式碼,提交修改) | 120 | 160 |
Reporting | 報告 | 60 | 40 |
· Test Repor | · 測試報告 | 20 | 15 |
· Size Measurement | · 計算工作量 | 5 | 5 |
· Postmortem & Process Improvement Plan | · 事後總結, 並提出過程改進計劃 | 30 | 10 |
· 合計 | 1560 | 1415 |