寒假第二次作业引导和提示
第二次作业涉及的面比较多,如果之前没有自学相关知识可能会觉得无从下手,以下给大家分析一下这次作业
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性能分析
欢迎加入我的技术交流群: