寒假第二次作業引導和提示
第二次作業涉及的面比較多,如果之前沒有自學相關知識可能會覺得無從下手,以下給大家分析一下這次作業
1. 該以怎樣的順序完成作業,側重點在哪
本次作業主要考察Git、GitHub使用,代碼規范意識,一定的程序設計能力(基於命令行),PSP,以及單元測試和性能分析改進。
在開始時建議先建一個空白文稿統計自己花在各個地方的耗時,方便到時候寫到PSP表格上(關於PSP表格,參考作業附錄)。
之后先別急着寫程序,先看一些Git、GitHub的教程,學會基礎使用之后,按照作業要求fork主倉庫,根據示例目錄結構建好自己的目錄。
建好目錄之后,便可以根據自己使用的語言,根據作業要求,制定代碼規范,代碼規范按照markdown格式,寫到codestyle.md中。
這時便可以開始分析需求、設計模塊。需求分析清楚后便可以開始寫程序。
當你有所產出之后,便可以進行commit,並push到github。作業要求commit 10次並不多,只是讓大家養成習慣。
對於你已經寫好的函數、類,要及時進行單元測試,此次作業要求最少10個測試用例。
單元測試記得滿足“FAIR”原則,即fast(快速)、automated(自動)、isolated(隔離)、repeatable(可重復)。具體使用什么框架並無限制。
單元測試應該隨着程序開發逐漸進行。確保你之后的修改不會導致單元測試的失敗。同時對錯誤情況和邊界條件也應給與測試。
本次作業采用自動測試,所以輸入文件和輸出文件都采用絕對路徑的方式傳入。在自動測試程序中,你們的程序會被當做一個新的進程啟動。
測試的命令和題目給出的並無太多區別。只是到時候日志會替換成更復雜的日志。
整個程序寫完之后,測試也全部完成之后。可以進行一些單元測試覆蓋率分析,性能分析。
這一切都完成后便可以在github 上pr(pull request)你的倉庫到主倉庫。
這次作業的目的是為后邊的“結對”、“團隊”編程打好基礎。這一切相關的技術也是貫穿軟件工程整個生命周期的。
如果你時間比較緊張,基礎較薄弱,建議你重點掌握好github、代碼規范、PSP、單元測試,程序力爭通過基礎測試(基礎list命令【30%】:僅僅攜帶-log、-out參數)。
如果你還學有余力,可以去學習如何使用構建工具進行項目的構建,如maven、gradle(但是確保你提交的倉庫符合作業要求)。
2、需求簡要分析
這次程序主要考察輸入輸出,文本處理。
文本處理推薦采用正則表達式的方式。如~/(\S+) 新增 感染患者 (\d+)人/
匹配福建 新增 感染患者 2人
。
對於模塊設計,應該小心。
雖然此次作業僅僅只需要完成list命令,但是從工程角度考慮,你應確保你的程序是可以擴展的。
你也許會用if ("list".equals(cmd)){}
這樣的方式來判斷命令是否正確,但它雖然簡單,卻不利於擴展。
嘗試使用設計模式中的命令模式。
此外如果你在處理日志時采用了正則,那么你是通過什么樣的方式來判斷日志符合那個正則表達式呢?
使用switch方式並不是好的方式。
嘗試使用設計模式中的狀態模式、責任鏈模式,將對應不同的日志和不同的操作集成到一個LogLine
中,並將他們鏈接起來。
以下可能是個提示:
/**
* 不同類型日志行
*/
class LogLine {
private Pattern reg;
private LogHandle handle;
// ...
}
此次作業的單元測試需要一些技巧,可以寄托於函數來測試,比如你測試list函數:public void list(String logPath, Sting outPath, Date date, List<String> province, List<ArgType> type)
這樣你可以將命令分析程序解構出來,同時方便進行單元測試。(當然這還不是好的設計,因為日志讀取不應該放進list,參數核驗也是)
但單元測試就會變的輕松一些:assertEquals(list(...), new File(...).text)
你怎么把它設計的更直觀?
將你的命令解析獨立出來,它提供一個使用字符串構造命令的方式(甚至可以從文件中讀取命令來執行):
/**
* 解析命令行參數
*/
class CmdArgs {
String[] args
/**
* 傳入命令行參數數組構造
* @param args
*/
CmdArgs(String[] args) {
//...
}
/**
* 傳入命令構造,可以設置無用的前綴,如`groovy Lib`
* @param argsStr
* @param noUseInStart
*/
CmdArgs(String argsStr, String noUseInStart = '') {
//...
}
/**
* 遍歷文件的命令,調用閉包
* @param fileName
* @param noUseInStart
* @param closure{ String line -> }
*/
static void eachLine(String fileName, String noUseInStart = '', Closure closure) {
//...
}
/**
* 獲取命令
* @return
*/
String getCmd() {
//...
}
/**
* 獲取某個命令行參數的值,多個值只會返回第一個
* @param key
* @return
*/
String argVal(String key) {
//...
}
/**
* 獲取某個命令行參數的值,返回列表
* @param key
* @return
*/
def argVals(String key) {
//...
}
/**
* 判斷該命令是否有對應的參數
* @param key
* @return
*/
boolean has(String key) {
//...
}
}
這是一個可能的流程:
SystemIn -> CmdArg -> CmdArgCheck -> LogParser -> DoCmd -> DoList -> FileOut
當SystemIn 換成 TestIn或者 GUI In它也能正常工作,而不需要做過多的更改。
3、IDEA簡要教程
-
導入github項目:
-
commit
-
github push
-
導入junit
之后設置你下載的junit包即可。 -
使用junit 進行單元測試
繼承TestCase即可。方法名需要滿足:1、public 2、返回值void 3、方法名以test開頭 -
代碼覆蓋率分析
-
Jprofiler性能分析
歡迎加入我的技術交流群: