零、前言
- 本次作業要求個人編寫程序,截止日期2019年9月25日23:00。
- 請先閱讀《構建之法》第一章至第三章的內容,並在下方作業里體現出閱讀后的成果。特別是第2章中的效能分析及個人軟件開發流程(PSP)。
一、編碼要求
- 在Github倉庫中新建一個學號為名的文件夾。
- 在開始實現程序之前,在PSP表格[附錄1]記錄下你估計在程序開發各個步驟上耗費的時間,在你實現程序之后,在PSP表格記錄下你在程序的各個模塊上實際花費的時間。
- 使用C++ 或者Java語言實現,C++請使用Visual Studio Community 2017進行開發,運行環境為64-bit Windows 10。
- 提交的代碼要求經過Code Quality Analysis工具的分析並消除所有的警告。
- 完成項目的首個版本之后,請使用性能分析工具Studio Profiling Tools來找出代碼中的性能瓶頸並進行改進。
- 使用Github[附錄2]來管理源代碼和測試用例,代碼有進展即簽入Github。簽入內容請注意測試須知的組織目錄,其余的文件(包括單元測試)不必上傳,使用.gitignore忽略。簽入記錄不合理的項目會被助教抽查詢問項目細節。
- 使用單元測試[附錄3]對項目進行測試,並使用插件查看測試分支覆蓋率等指標;並寫出至少10個測試用例確保你的程序能夠正確處理各種情況。
二、博客撰寫要求
- 在文章開頭給出Github項目地址。
- 給出PSP表格。
- 解題思路描述。即剛開始拿到題目后,如何思考,如何找資料的過程。
- 設計實現過程。設計包括代碼如何組織,比如會有幾個類,幾個函數,他們之間關系如何,關鍵函數是否需要畫出流程圖?單元測試是怎么設計的?
- 記錄在改進程序性能上所花費的時間,描述你改進的思路。
- 代碼說明。展示出項目關鍵代碼,並解釋思路與注釋說明。
- 結合在構建之法中學習到的相關內容,撰寫解決項目的心路歷程與收獲。
三、需求
實現一個命令行程序,不妨稱之為Sudoku。
百度百科簡介:
數獨盤面是個九宮,每一宮又分為九個小格。在這八十一格中給出一定的已知數字和解題條件,利用邏輯和推理,在其他的空格上填入1-9的數字。使1-9每個數字在每一行、每一列和每一宮中都只出現一次,所以又稱“九宮格”。
具體任務:
現在我們想一步一步來,完成從三宮格到九宮格的進階;完成三宮格和其他博客任務,就算過了初級考核,其他的算升級。具體各階規則如下:
三宮格:盤面是3*3。使1-3每個數字在每一行、每一列中都只出現一次,不考慮宮;
四宮格:盤面是2*2四個宮,每一宮又分為2*2四個小格。使1-4每個數字在每一行、每一列和每一宮中都只出現一次;
五宮格:盤面是5*5。使1-5每個數字在每一行、每一列中都只出現一次,不考慮宮;
六宮格:盤面是2*3六個宮,每一宮又分為3*2六個小格。使1-6每個數字在每一行、每一列和每一宮中都只出現一次;
七宮格:盤面是7*7。使1-7每個數字在每一行、每一列中都只出現一次,不考慮宮;
八宮格:盤面是4*2八個宮,每一宮又分為2*4八個小格。使1-8每個數字在每一行、每一列和每一宮中都只出現一次;
九宮格:盤面是3*3九個宮,每一宮又分為3*3九個小格。使1-9每個數字在每一行、每一列和每一宮中都只出現一次;
輸入:
輸入文件名以命令行參數傳入。例如我們在命令行窗口(cmd)中輸入:
Sudoku.exe -m 9 -n 2 -i input.txt -o output.txt
其中各參數一定會出現,意義如下:
- -m 宮格階級(3~9的整數)
- -n 待解答盤面數目
- -i 指定輸入文件
- -o 指定程序的輸出文件
輸入文件說明:
總共包含n個盤面,每兩個盤面間空一行,每個盤面中,每兩個小格之間有一個空格;待填入的格子用0代替。輸入保證有且僅有一個解,所編寫的程序不需要考慮無解時的輸出。
上面的命令行對應的輸入文件input.txt如下:
0 0 8 0 0 4 0 0 9
0 6 0 0 0 0 1 0 0
0 3 7 0 0 0 0 0 0
8 0 1 2 6 9 0 0 3
0 2 5 4 7 0 0 6 8
0 9 0 0 0 5 0 0 0
9 0 0 1 5 2 3 7 4
0 4 0 3 9 8 0 1 6
1 5 3 6 4 7 8 0 2
2 0 0 0 0 0 0 0 0
0 0 6 3 0 0 0 7 0
5 0 0 0 0 0 1 0 0
9 6 7 4 0 0 0 0 5
8 1 3 0 0 0 0 0 0
4 2 0 7 1 8 9 6 3
3 5 0 0 4 1 6 9 7
6 9 8 2 7 3 5 4 1
0 4 0 0 5 9 2 0 8
輸出:
輸出n個程序解出的盤面,每兩個盤面間空一行,每個盤面中,每兩個小格之間有一個空格。
上面的命令行對應的輸出文件output.txt組織如下:
5 1 8 7 2 4 6 3 9
2 6 9 5 8 3 1 4 7
4 3 7 9 1 6 2 8 5
8 7 1 2 6 9 4 5 3
3 2 5 4 7 1 9 6 8
6 9 4 8 3 5 7 2 1
9 8 6 1 5 2 3 7 4
7 4 2 3 9 8 5 1 6
1 5 3 6 4 7 8 9 2
2 7 9 1 8 4 3 5 6
1 8 6 3 2 5 4 7 9
5 3 4 9 6 7 1 8 2
9 6 7 4 3 2 8 1 5
8 1 3 5 9 6 7 2 4
4 2 5 7 1 8 9 6 3
3 5 2 8 4 1 6 9 7
6 9 8 2 7 3 5 4 1
7 4 1 6 5 9 2 3 8
四、測試須知
組織目錄
助教在測試時,將運行自動測試程序編譯源文件並運行,進行批量測試,因此請保證項目的組織目錄符合要求
Java
對於使用Java語言的項目有以下兩點要求:
- 【以學號為名的文件夾中】的目錄下必須有src文件夾
- 在src目錄下必須有名為Main.java文件,且Main.java中包含 public static void main(String[] args) 方法
一個Java項目的示例組織目錄如下所示:
031702188 (文件夾名字為學號)
|- src
|- Main.java(主程序,可以從命令行接收參數)
|- lib.java(包含其它自定義函數,可以有多個,對名字不做要求)
C++
對於使用C++ 語言的項目有以下要求:
- 【以學號為名的文件夾中】的目錄下必須有src文件夾
- 在src文件夾中是可在VS2017下編譯運行的解決方案,解決方案的名字必須為 Sudoku。
一個C++工程示例組織目錄如下所示:
031702188 (文件夾名字為學號)
|- src
|- Sudoku.sln
|- Sudoku
|- stdafx.cpp
|- stdafx.h
|- Sudoku.cpp
|- Sudoku.vcxproj
助教在測試時,將自動按照指定編譯環境編譯源代碼,並利用命令行進行批量測試。
錯誤處理
本次自動測試會加入各種各樣出錯情況的測試,要求開發者程序不能崩潰,並且能夠盡可能精確報錯。你可以有“容錯性”的出錯設計,但必須輸出必要的提示或說明。
五、評分規則
博客評分規則
以下可以作為同學們寫博客的提綱參考,具體分數可能會做修改,修改時再提醒。(40'+10')
- 在文章開頭給出你的倉庫的Github項目地址。(1')
- 在開始實現程序之前,在下述PSP表格記錄下你估計將在程序的各個模塊的開發上耗費的時間。(5')
- 計算模塊接口的設計與實現過程。 設計包括代碼如何組織,比如會有幾個類,幾個函數,他們之間關系如何,關鍵函數是否需要畫出流程圖?說明你的算法的關鍵(不必列出源代碼),以及獨到之處。 (20')
- 計算模塊接口部分的性能改進。 記錄在改進計算模塊性能上所花費的時間,描述你改進的思路。(3')
- 計算模塊部分單元測試展示。 展示出項目部分單元測試代碼,並說明測試的函數,構造測試數據的思路;測試數據有覆蓋到所有的代碼嗎?並將單元測試得到的測試結果,發表在博客中。 (5')
- 計算模塊部分異常處理說明。 在博客中詳細介紹每種異常的設計目標。每種異常都要選擇一個單元測試樣例發布在博客中,並指明錯誤對應的場景。(4')
- 在你實現完程序之后,在附錄提供的PSP表格記錄下你在程序的各個模塊上實際花費的時間。 (2')
- 完成三宮格之上的更高階級,並在以上各個條目體現出來。(10')
程序評分規則
正確性(20'+30')
- 完成三宮格(20')
- 之后的階級每完成一個(5')
六、附錄
1.PSP表格
PSP是卡耐基梅隆大學(CMU)的專家們針對軟件工程師所提出的一套模型:Personal Software Process (PSP, 個人開發流程,或稱個體軟件過程)。
PSP2.1 | Personal Software Process Stages | 預估耗時(分鍾) | 實際耗時(分鍾) |
---|---|---|---|
Planning | 計划 | ||
Estimate | 估計這個任務需要多少時間 | ||
Development | 開發 | ||
Analysis | 需求分析 (包括學習新技術) | ||
Design Spec | 生成設計文檔 | ||
Design Review | 設計復審 | ||
Coding Standard | 代碼規范 (為目前的開發制定合適的規范) | ||
Design | 具體設計 | ||
Coding | 具體編碼 | ||
Code Review | 代碼復審 | ||
Test | 測試(自我測試,修改代碼,提交修改) | ||
Reporting | 報告 | ||
Test Repor | 測試報告 | ||
Size Measurement | 計算工作量 | ||
Postmortem & Process Improvement Plan | 事后總結, 並提出過程改進計划 | ||
合計 |
一個功能完備的程序不是一蹴而就的。可將一個大任務划分為可操作的小任務,同時最好按照任務難度或緊急程度指定各個任務的完成次序。因此,在動手開發之前,要先估計將在程序各模塊開發所需耗費的時間,以及完成整個項目所需的時間,將這個[估計值]記錄下來,寫成PSP 的形式。
PSP的目的是:記錄工程師如何實現需求的效率,和我們使用項目管理工具(例如微軟的Project Professional,或者禪道等)進行項目進度規划類似。
有關PSP的更多內容,請自行閱讀鄒欣老師的博客:工程師的能力評估和發展
2.Github
請閱讀鄒欣老師的博客:源代碼管理,了解源代碼管理的10個實踐問題。
本次作業要求使用Github進行源代碼管理,代碼有進展即簽入Github。簽入記錄不合理的項目會被助教抽查詢問項目細節。
對代碼簽入的具體要求如下:根據需求划分功能后,每做完一個功能,編譯成功后,應至少commit一次。具體的功能划分,請自行定義,並在撰寫博客時體現出來,遵循自己對需求的功能划分來提交代碼即可。
對Commit不是很熟悉的話,請閱讀阮一峰的博客:Commit message 和 Change log 編寫指南,了解更多細節。
3.單元測試
請根據自己以往積累的測試經驗,在編碼完成之后,提交產品之前,設計測試用例,並編寫單元測試,對自己的項目進行測試。
首先,至少應采用白盒測試用例設計方法來設計測試用例,其他測試方法不限。其次,要設計至少10個測試用例,確保你的程序能夠正確處理各種情況。最后,結合測試評估的要求,對自己的測試設計進行評價,這些測試用例能滿足該程序測試的要求嗎?
另一個重要的措施是要把單元測試自動化,這樣每個人都能很容易地運行它,並且可以使單元測試每天都運行。每個人都可以隨時在自己的機器上運行。團隊一般是在每日構建中運行單元測試的,這樣每個單元測試的錯誤就能及時被發現並得到修改。
推薦閱讀鄒欣老師的博客:關於單元測試和回歸測試