衡与墨
Quiet inside.

寒假第二次作业作业引导和提示

寒假第二次作业引导和提示

第二次作业涉及的面比较多,如果之前没有自学相关知识可能会觉得无从下手,以下给大家分析一下这次作业

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简要教程

  1. 导入github项目:

  2. commit

  3. github push

  4. 导入junit

    之后设置你下载的junit包即可。

  5. 使用junit 进行单元测试

    继承TestCase即可。方法名需要满足:1、public 2、返回值void 3、方法名以test开头

  6. 代码覆盖率分析

  7. Jprofiler性能分析

欢迎加入我的技术交流群:

posted @ 2020-02-08 13:09  衡与墨  阅读(893)  评论(1编辑  收藏  举报