BUAAOO_FINAL

BUAAOO_FINAL_BLOG

一 · 单元架构设计

第一次作业

国际惯例,先上类图。

在数据结构的设计上,我选择将UmlElement二次封装为树状节点UmlElmentNode,用数据结构UmlNodeSortList存储子节点,后者可以视为普通的UmlElement列表,支持通过指定类型导出。在MyUmlInteraction中,用两个HashMap分别映射:类名与类ID、所有元素ID与其对应节点,并用一个UmlNodeSortList存储所有节点用于分类检索。构造方法对传入的每一个元素,维护以上三个容器,这部分工作结束后重新遍历所有元素建立树形结构。

在方法的设计上采用了这样的思路:对于接口要求的public方法,只保留一些“搬运工作”,而将具体的实现逻辑全部放到private方法中实现。这样做的好处在于,接口方法是工作模块之间的联系,不存在任何“脏活”,可读性极强。

第二次作业

宇宙惯例,先上类图。

第二次作业采用继承第一次作业类的方式实现。

首先对第一次作业类做了一些改进。

  • 原本的树形结构遵循mdj文件的json父子结构,并不能很好的反映关联关系。现除json结构外,将AssociationEnd加入其reference节点的子节点列表中。严格来说对于改进后的结构,不能再称为“树”,但对本单元应用来说没有影响。如此改进后,所有工作都可通过“树形”结构完成,不再需要分类列表进行检索,简化了和工具类之间的依赖关系。同样与关联关系相关的private方法需要做相应修改。

  • 将构造方法中对类中数据结构的操作封装为若干protected方法,以便在子类中通过重写这些方法增加子类自身的数据结构维护工作。

  • 为子类的规则检查提供必要的接口。

子类需要实现的新工作包括新元素的查询、三条规则的检查。查询部分逻辑较为简单,维护了若干HashMap以完成检索。规则检查部分需要父类信息,使用上文提到的父类新接口实现。

待改进的点

  • 对树形节点类的实现较为随意,导致相关数据操作显得丑陋。意识到此问题时已经完成了上百行代码,从而出于正确性考虑没有进行修改。

  • MyUmlClassInteraction类过于巨大,甚至险些超过500行的限制。基于上文提到的方法设计思想,可以考虑将数据结构、构造方法、private方法全部放在一个“脏活”类当中,将private改为package-private或protected,然后将public方法放在子类中实现。

  • 第二次作业中两类新元素需要的数据关系其实存在很多共性,可以通过封装数据结构统一管理。

二 · 架构设计&OO方法

感受

个人认为,由于其纯粹的面向对象特性、以及程序包的组织方式,java是非常能够反映编程者架构设计能力的语言。回顾我这一学期的架构设计,最开始盲目乱搞,后来开始慢慢尝试精心设计,很多时候结果不尽如人意,但这些思考仍然带给我很多。

重构,重构,重构

课程的每一个单元都是渐进式的,在理想状态下,同单元前次作业应该可以作为后次作业的一部分。但这种理想状态对程序的拓展性要求很高,最终经常看完新指导书后掩面长叹:又又又要重构了!

第一单元我完全就是每次都重写。一方面是自己对架构懵懵懂懂,一方面这一单元后期的内容确实比前期多出太多,要做到良好的拓展性着实困难。

第二单元我开始有了预留拓展性的想法,但结果依然是看完新指导书,大呼:重写!重写!

第三单元作业渐进性尤为明显,这一单元我就几乎没有大面积重构了,前次作业的代码直接复制粘贴进新作业。

第四单元的重构是我最为满意的一次。通过继承、重写预留方法,实现了可完美兼容两次作业的程序。

类的抽象与设计

在面向过程的程序设计中,设计工作集中如何安排业务逻辑。而到了面向对象编程,首先要思考的则是如何把数据对象抽象为类并合理设计类之间的关系。

在类的设计中,我有两次印象较深的尝试。一次是在第一次作业时,我就为因子、乘法复合项、加法复合项分别设计了对应的类,这样的思想使得我对此后复杂任务的实现变得更为轻松。另一次是在JML单元,我使用泛型实现了一个具有适用性的图结构,体验极佳。

路漫漫其修远

架构能力的培养绝非一朝一夕之功,在OO课程中我无数次体会到精心设计架构却在实际操作中遇到问题而不得已推翻架构的痛苦。也许这种煎熬与折磨,恰恰就是通往优秀架构能力的必经之路吧。

最后附上昂神的几句话。

PS: 动画表情是

三 · 测试

前言

我在测试方面一直做的不是很好,数次因为测试不到位而翻车,所以本节不是心得而是血的教训……

测试数据的构造

测试数据一方面应包括针对自己程序逻辑而构造的边界数据,一方面也应生成一些随机数据,特别的对于像第一单元这样存在WF要求的作业,随机数据应将合法和非法数据都包含在内。

随机数据的生成

随机数据对于发现设计思路上的错误极为有效。因为手动构造数据与编写程序是基于相同的思路,如果自己最开始的理解就出了问题,那么再怎么构造也查不出错的。一般可以编写另外一个程序,采用正则表达式、随机数等方式生成大量随机数据。

对拍器的构建

对于大量随机数据,人工判断正确性绝不现实。可以采用编写对拍器的方式实现自动化验证,比较常用的工具有Python的subprocess模块和Windows的shell编程。

感想

老师总说,程序员永远不要相信别人。其实,程序员连自己都不能相信……很多时候在匪夷所思的地方手抖写错点什么,真的是非常难以发现,自己构造的测试用例也很难想到这种地方。所以,一方面构造用例时不要放过任何一种情况,想当然就会白给;另一方面随机数据对拍轰炸绝对是必不可少的环节!

四 · 课程收获

对java语言的熟练掌握

在OO课程之前,我能够使用C、java、Python三种语言,但都停留在最浅显的阶段,只能用来编写轻量程序。在OO课程中我使用java编写了多达11个较为大型的程序,经过这一番练习,我对java的掌握不再止步于语法层面,深入了解了java的特性、熟练运用数个官方轮子,已经具备了使用java开发大型软件的能力。

架构设计能力的提升

OO课程是我第一次接触软件工程领域。阅读指导书后自主设计程序架构,最终完成程序并提交测试,这对我的架构设计能力有很大的提升。更多相关内容在第二部分已经写了不少,此处不再赘述。

对测试工作的重视

课程中我有过数次强测天崩,而绝大部分bug都并非思路错误,而是一时疏忽。强测的失败和参与互测的经历都让我看出自己在程序测试方面的不足,需要在以后的学习中加以改善。

五 · 课程建议

适当提供java高级特性

虽说OO课程的重点不在于java语言,但既然使用了java,不妨给同学们介绍一些java语言高级特性。现行课程对同学们的语言功底持放养态度,这就导致了自主学习能力稍弱的同学难以在作业的重压之下再去学习java的高级特性,最终对java的掌握停留在“和C语法几乎一致”上。指导书曾经有过关于高精度数据类型、容器、变长参数等的提示,我认为这就是一种兼顾教学中心和额外引导的好方法。建议在每次指导书中提供一些可能会在本次作业中用到的“黑科技”,帮助更多的同学了解和掌握泛型、lambda表达式、匿名类等操作。

加强理论教学和课下作业的适配

个人感觉,理论教学和作业安排仍存在不一致的地方。PPT经常出现大量高深的理论知识,而并不能很好的反映在课下作业当中,导致课下作业并不能巩固理论知识,理论教学也无法帮助同学们更好的完成作业。以UML单元为例,课下作业绝大部分的工作是倒腾数据结构,我相信会有不少同学和我一样,在AC作业之后仍然对顺序图和状态图知之甚少。

公布互测中较强的测试用例

很多情况下互测都能找出强测未能发现的bug,如果同屋同学恰好没有提交这样的用例,bug可能就被深埋了。建议在每次bug修复结束后,公布全部或部分与强测bug非同质的测试用例,方便同学们进一步完善自己的程序。

猜你喜欢

转载自www.cnblogs.com/AbyssGazeaAlso/p/11070065.html
今日推荐