OO_JAVA_UML_单元总结

作业架构

第十三次作业

第十三次作业,由于课程组提供的UMLClass,UMLInterface等类缺少实现服务所必须的一些属性和方法,因此采用代理模式,为每个UML元素创建对应的代理类。

其次,由于类和接口需要有添加属性,添加方法,添加关联等方法,因此设置了AssociatedItem和Operable两个接口(现在看来,设置一个ClassOrInterface接口可能会显得意图更清楚一些,不过不是说要符合ISP接口分离原则么?所以但是还是分成了几个接口)。

另外为了提高查询效率(防止TLE从我做起),只要是用名字查询的,都采用了哈希链表,链表长度不为1,查询时就抛异常。另外也建立了HashMap<id, Object>存储暂时生成的代理类。

第十四次作业

第十四次作业,新增加了UMLStateMachine和UmlInteraction. 需要注意的是,State有三个UML元素type,分别是UmlState,UmlPsudoState,UmlFinalstate. 采用同一个代理类MyState。采用哈希链表对有名字的类进行管理,单独设置initState和finalState来表示起始和终止状态。

第十五次作业

第十五次作业时,发现此时MyUmlGeneralInteraction类已经过于臃肿,MyClass,MyStateMachine,MyInteraction数据已经解析各种输入模型的方法全部在MyUmlGeneralInteraction中。因此单独设置三个类ClassDiagram,SequenceDiagram,StateDiagram封装各数据和方法。MyUmlGeneralInteraction只是起一个代理的功能,负责对外交互。

四个单元中架构设计及OO方法理解的演进

UnitOne

第一次作业非常简单,直接用正则表达式暴力匹配。从第二次作业开始,我在实现时就考虑了第三次作业的扩展(括号嵌套)以及未来的一些其他需求如除法,(x+sin(x))**2等。

从第一次作业开始,本人意识到了输入,判断格式并解析表达式,表达式求导,化简,输出,应该是相互独立的几个部分。因此有专门Parser类,来解析表达式。但我并没有意识到,虽然Parser解析表达式时需要分为exp,Item,Factor三个函数递归调用解析,但是并不一定非要有Exp, Item, Factor这三个类,并且也构成递归包含的关系。

说来惭愧,其实本人一直到第四次作业结束后,抽空阅读了课程组的参考代码和lyj同学的优秀代码,才体会到表达式求导架构设计的奥义所在。参考代码并没有乱七八糟的Exp,Item,Exp等类,而是以一个Item类来代替它们,Item类的特性是可求导。这样一来,就极大地简化了架构,并提升了可扩展性。类图如下。

关于实现的一些细节,也想在此说一下(其实都是本人踩过的一些坑orz):

  • 单独提取出一个解析表达式的类Parser。但是本人又犯傻了,在Parser中将judge功能(判断表达式是否合法)和Parse功能(解析表达式并返回一个exp对象)分开,导致Parser臃肿,逻辑混乱不堪。比较好的设计是将judge和Parse放在一起,如果无法parse(match)自然就judge wrong format. 以及采用stack来判断括号是否匹配。
  • 关于多个正则表达式,可以单独建一个Patterns类,采用HashMap<name, pattern>来管理。
  • 为了考虑程序的求导的速度和化简的性能,可以将LinearItem(加法)和ChainItem(乘法)只有LeftItem和RightItem,改为List

UnitTwo

第二单元很强调对象的概念,只有各个类各司其职,输入进程负责处理输入,调度器负责产生指挥电梯的指令,电梯负责运人。当然,后来两次作业在电梯中加了内部调度器。

另外,对象的交互通过共享变量来实现,其实也就是指令的队列。因为是共享对象,所以要把指令队列设为线程安全对象。另外,采用Worker模式协调输入进程,调度器线程和电梯线程。

UnitThree && UnitFour

这两单元的架构助教大大们基本已经给好,因此就不多做分析了。

四个单元中测试理解与实践的演进

在第一单元,本人的测试方法主要是 手动构造有针对性的测试数据 + 自动测试(分为datamaker和judger两部分)。但是由于忘记测试输出样例格式的合法性(其实直接把输出再作为输入重定向到Java程序就可以),第三次作业优化产生了输出格式的bug,WA了五个点QAQ

在第二单元,手动输入样例不现实,因此以自动测评为主。但是这一次我结合了小黄鸭测试法。第二单元各个线程间的协调,已经调度算法,都可能有较多的逻辑分支。这个时候采用小黄鸭测试法,能减少逻辑上错误的发生。

第三单元,测试采用 手动构造数据 + 对拍 + 小黄鸭测试法。尝试了JUnit单元测试,虽然 分支全覆盖 这一点非常好评,但是由于还是需要手动构造Junit测试代码,显得很低效,因此没有过多的使用。

第四单元,测试基本同第三单元。

演进主要有两点。

一是小黄鸭测试法,本人觉得十分重要,可以帮助我们分支过多时的逻辑错误。

二是关于Junit单元测试,虽然本人目前觉得有点鸡肋(完全没有强力对拍机好用)。但是看了些资料,说是测试驱动开发在产品迭代的过程中尤为重要,有了之前的测试,能更大胆的迭代。因此,还希望有机会更进一步了解单元测试。

课程收获

第一单元锻炼了我用面向对象的思维方式逐层分解问题解决问题的能力。面向对象不仅是一种语言的特性,更是一种思维的方式,划清对象间的界限,合理表示对象间的关联和协同,寻找对象的共同性质,使用多态的特性来提高程序的可扩展性。

第二单元初窥多线程编程。目前本人关于多线程编程的感悟有以下几点。一是设置好线程间的共享对象,并要把共享对象设置为线程安全类。二是线程安全类并不能保证线程安全,最重要的是要做到对共享对象同一时间只有一个操作,一个操作完全结束后才能进行下一个操作(当然,为了提升效率的读者写者模式等略微有些不同)。三是把锁(临界资源)和临界区都要精心选取。临界区在保证线程安全的前提下要尽可能小。

第三单元契约式设计,JML语言。学习了契约式设计的思想。

第四单元UML语言。除了熟悉了UML语言工具外,其实也学会了一套分析自己架构的方法。我们可以从类图,状态转移图和交互图三个角度去分析我们的程序。特别是在第二单元(多线程,电梯有多种状态的情况下)能理清我们的设计思路。

三个具体改进建议

首当其冲的当然是实验。虽然实验的题出的很好(良心话),但是如果没有答案形成及时反馈,学习效果会大打折扣。建议每次实验结束及时发放参考答案。

第二点是建议在每次博客作业中要有与参考代码相关的内容,以此强迫同学们学习参考代码。参考代码其实很有学习的价值,但是懒狗比如我,是在考离散的前一天,实在不想复习了。才想起来把OO第一单元的几个参考代码看了一遍。在阅读优秀代码的过程中学习到了更优的架构设计,也学习到了很多具体细节的优雅实现。(另外一说,阅读缺少注释且水平不高的代码属实痛苦,我只有第一次作业的时候,在互测环节读过别人的代码。第二三次作业就直接拉到本地对拍了。后面六次作业,就完全没管互测了,别人没hack到我,我也不去hack别人。)

第三点建议是多线程单元的学习。建议课程组可以下发一些学习资料或者推荐一些资料。不然直接一开始就学习synchronized属实坡度有点大。不知道为什么lock会放在synchronized后面讲,还是建议lock先讲,这样容易接受些。

线上学习oo课程的体会

总的来说,线上学习对OO这种性质的课程几乎没有影响。这学期的OO体验非常好,特别是与同期某些其他课程相比,OO明显内容有用,助教负责,老师用心,制度清晰。十分感谢课程组和老师们的付出,让我们学习到了很多在以后工作中都会十分有用的知识。另外也很感谢优秀的同学们,阅读他们的优秀参考代码让我多方面都有所长进。我爱OO!

posted @ 2020-06-19 19:04  yueyang37  阅读(192)  评论(0)    收藏  举报