作业1: 多项式运算
第一次写JAVA程序。 这次作业要求写两个版本, C版本和JAVA版本, 于是很自然而然的先写了C版本。 写C版本的时候主要麻烦在处理输入的地方, 和各种错误的报错。 C语言写了就差不多一天, 各种递归处理读入的字符串并且各种处理什么的, 很是麻烦。 后来想JAVA可不能这样, 于是根据指导书上的强烈推荐, 学了一手“正则表达式”, 真可谓如鱼得水, 写起来比C语言舒服多了。 对于类的设计也就是多项式和项式这两个类, 主要的处理字符串的部分写在了构造函数里, 把字符串穿进去就用正则表达式把各种想要的东西提出来了。 在度量看来的话, main函数的圈复杂度比较高, 这里主要是正则表达式处理输入和判断各种非法的部分, 由于没什么好分割的, 就都写在一坨, 写得也挺面向过程的。 这一段的代码质量较低维护起来困难。
也许是刚开是太过于顺利, 最后在截止的倒数第二天, 测试自己的JAVA程序的最后一步, 边界测试给我来了个Crash。 当时也是感觉莫名其妙, 后来各种百度, 发现正则表达式爆栈了。 网上还有类似这么一句话“当你使用正则表达式解决一个问题时, 你会发现你需要解决的问题变成了两个”。 虽然不知道正则表达式内部是怎么实现的, 自己想了想确实也挺有道理。 于是乎根据网上的建议, 把最外那一层正则表达式重写, 降低其复杂度, 勉勉强强逃过一劫。 最后还是有点后怕还给自己的程序上了一个try catch保险。 也正是因为这个意料之外的错, 那天晚上奋斗到了2点。。。。 虽然公测的时候自己还是错了一个点, 事后发现是自己输出处理的时候出了个小错误,明明自己写C语言版本和写生成随机数据的程序时都是考虑的, 就算是一时手抖吧。。。
到了最后互测的时候, 那个人公测全对, 自己也就只是把自己的出给自己的数据给那个人跑了一遍, 看了一遍Readme没什么问题, 自己也没被对面挑出什么错, 于是乎这次作业就这么平平稳稳的过去了。
作业2: 单部电梯考虑同质
这一次作业可以说才是真正意义上进入了面向对象, 第一遍看完指导书就是一阵迷迷糊糊的, 感觉有很多东西都不清晰, 自己完全下不了什么手。 于是花了一整天把在指导书和答疑区中不断穿梭, 看了一个个问助教的样例, 才使得自己的思路逐渐明了。 再根据指导书上要求的那么几个类和推荐设计思路, 自己在构思了一下后, 写程序到是只花了半天不到就写完了, 而且粗测没有测出什么错。 虽然感觉自己写得还是挺面向过程的, 这几个类设计的有点强行。 从类图就能看出来请求类十分臃肿, 干了不少事, 请求队列类什么的也就不过是一个请求类的数组, 打了个包罢了。 然后整个程序的主体, 调度器类, 看似只有一个方法void run(), 其实这个有个快百行, 就是一堆for循环什么的, 干一些扫描队列判同质走电梯等等主要的事。 这回相比上次多会了个东西, 那便是static属性, 把某些类里的成员变量设成了静态的, 这样即使再不同的类里new了不同的对象, 由于这一部分是公共, 所以各种修改与访问就相当于是对同一个对象操作一样, 也是方便了那么一点点吧。。。。从度量来看的话, 由于延续了上次作业正则表达式的提取输入方法, main函数那块依然圈复杂度很大, 请求类的参数个数偏多也是非常明显的。
不过这一次作业我出了个大疏忽---Readme没有交上去。 当时也是自己对这个评测平台的拉取了解不是很清楚, 以为这个评测平台只要手动拉取程序, 这次程序又是写得很顺, 写完程序再写个readme就没在改过自己的程序。 于是readme就只是交到gitlab上就没管了。 后来才知道oj是把你选择的最后一次提交时整个gitlab上的东西打个包收上去, 也算是吃一堑长一智了。 就这样, 公测全对的我被对面挑了一堆由于没有readme的错, 那些指导书里不清不白的东西就可以各种拿出来挑错, 没有一个什么正经的真正意义上错的。 我也没什么办法, 这里就不提了。。。。
伤心的我开始找我拿到的那个人的错, 一看那个人公测错了一个点, 还是第一个点, 挺傻的一个点。 当时也是觉得纳闷, 于是把数据拷下来给他本地跑发现是对的, 在oj上新增测试样例跑他还是对的, 这就很奇怪了。 于是反复确认之后把他那个错给改对了。 最后到了真正给他找错的时候发现自己的数据他也是全过的, 再挑挑readme也没挑出错。 于是乎这一次作业就以自己被挂了一堆有苦说不出的错和自己给对面改对了一个点这么一个结局结束了。。。
作业3: 单部电梯考虑同质与捎带
当时拿到指导书时, 脑子里对指导书上捎带指令的这个描述比上次作业的同质指令更加一团浆糊。 继续选择去畅游答疑区答疑群指导书一天再说。 好在这次开始做的比较晚, 20多条答疑足够解决我心中的疑问了。 不过剩下困扰自己的就是实现了。 这个捎带会影响一个指令的结束时间, 无论是对于去捎带别人的主指令还是对于被捎带的指令来说, 这样也会影响同质的判断, 而同质指令又是不能被捎带的, 可谓这两个性质相互影响, 纠结得要命。 不过纠结了大半天之后自己还是纠出来了。 大致的框架跟上次作业区别不大, 按照指导书的要求搞了个借口和继承, 请求类新增了捎带指令的标记, 调度器里的调度方法基本都重写了, 为了方便判断, 这次是让电梯每爬一层楼就判断捎带判断开门, 每当一个指令结束的时候就扫描整个队列标记同质, 写完之后也没什么错。这一次基本上是延续上次作业的部分, 而且调度器里的run方法写得更复杂了, 圈复杂度依旧高亮, 而且块嵌套层数过高。 请求类的参数还是老问题。
鉴于这次感觉特殊情况容易错的情况特别多, 自己构造了许多测试数据后还是各种不放心, 于是把答疑区答疑群里各种例子也走了一遍, 可以说对整个电梯运行的过程很熟练了。 在数百组测试数据的锻炼下, 自己最终的程序可谓是天衣无缝了, 公测没有出错, 对面的测试者也没挑出什么错。(其实挑出了一个错, 是我没有上传最新的版本,怕是我那次改完bug后忘记交了。。。即使这样这个老一个的版本也出了那个错没什么问题的)。 然后我匹配到的这个人也是个大佬, 在我的数据下屹立不倒(似乎这三次作业我的数据都没有hack到一个人。。。), 照例挑readme, 看看代码, 都是那么的严谨, 代码还写的挺专业的, 就放弃挑刺了。。。
心得&体会
- 一定要记得提交最新的readme与最新的代码!!!十分重要!!!
- 仔细阅读指导书与逛答疑区比写程序本身更加重要。
- 避免写冗余重复的代码, 减少类与类之间的耦合, 不要让某一个类过于臃肿, 要细分各个模块干的事。
- 测试数据一定要做得足够充分, 不要偷懒, 自己多画画错误分支树, 每个情况都检测到。
- Readme也要认真写, 模糊的地方都要说清楚。