{name:"面向对象第四单元UML系列总结博客",type:"UmlBlog"}
面向对象第四单元UML系列总结博客
前言
经历了与OO相爱相杀的一个学期,真的是感慨万千。此时再读一读自己的博客和代码(可惜前面的代码已经看不懂了)还是很有成就感,这个学期开始的时候多多少少还是听到过OO的许多传闻,对这个新的学期感到有些害怕,不管怎么说自己还是坚持了下来。经历过深更半夜重构代码到两三点的折磨,也有着因为前面作业架构做好了之后顺风顺水的轻松与喜悦,也有五一假期作业轮空了一次身心的空虚与寂寞,课程的最后拿到了狼人奖(这个是真的没有料到,我感觉我还是非常人畜无害的^_^)和暖心分享奖,也是对自己的一种肯定。OO课教会了我如何高效自学新知识,如何设计架构,如何测试,以及保持良好的代码风格,这些训练都无形中教会我一个优秀的工程师应当具备的素质。
总结本单元作业的架构设计
本单元的架构设计比较清晰,都采用了层次处理的设计架构,即每一个层次只需要管理其直接下属的元素。本次作业的CPU时间放的比较宽,于是在提高性能上并没有采取很多的方法,基本上使用了缓存的思想和部分优化算法。
第一次作业
第一次作业是解析类图中的元素,本次作业中,针对其中的UmlXXX
的在Java中拥有实体的类创建了MyXXX
的类,共划分为三个层次:
Layer1 | Layer2 | Layer3 |
---|---|---|
MyClass,MyInterface | MyOperation,MyAttribute | MyParameter |
对于UmlAssociation、UmlGeneralization等表征类图中关联、泛化等关系的类,对这些关系类本身没有存储的必要,所以没有对其创建自己的类,只需要把这些类所表示的关系,记录到上表中相应层次的实体类中即可。本次作业相较于第三单元的最大不同是,图的构建和图的查询是时间上严格分离的,所以执行相应的查询时,递归的时候路径节点将本节点的查询结果缓存,方便再次查询时加快查询速度。
第二次作业
第二次作业与第一次作业架构基本相同,添加了时序图和状态图的部分元素,并且将状态图的解析与构建解耦成为一个单独MyParser
类,时序图与状态图的相关作业需求并不是很复杂,只需要严格按照UML的规则实现即可。
第三次作业
第三次作业是对UML模型进行简单的有效性检查,仍然按照从上到下的层次进行有效性检查,算法上在解决含有多继承的接口的循环链查找的问题中,使用了拓扑排序的算法。在有效性检查中,有许多关于重复的判断,由于之前的架构中,大量使用了HashSet和HashMap等的自动去重的容器,导致本次作业又使用ArrayList进行了大量的冗余存储,使得本次作业的架构并不是很简洁明了。
总结自己在四个单元中架构设计及OO方法理解的演进
虽然一个学期的课程结束了,但是如果让我仅仅抽象的说我对OO的理解,仍然感到还是有一定的困难,封装、继承、多态这些固定的说法并不能够体现出我对OO的理解,如果让我谈一谈我对OO的理解:抽象是重要的,迭代是必要的。实现对象化的方式并不复杂,更多的是让自己的实现能够为扩展预留空间,让自己的每一部分尽可能地为后面的部分所复用。宏观设计与具体实现要相互补充,宏观设计不一定要每个细节面面俱到,在具体的实现中随着自己对问题域的了解更加深入进而调整自己的结构设计。通过UML与JML,这个思维与实践交替的过程也被很好的解耦了,这是一种OO的很好的体现,通过UML在静态的模型层面进行严谨的描述,同时也能够暂时忽略一定的细节,在模型的指导下,根据需求设计出满足需求的规格,实现的时候只需要关注规格,这流水式的开发过程也是OO的非常生动的体现。
第一单元
第一单元初识OO,第一次基本上还是按照解决问题的步骤和流程,以过程式的思维来思考的,遇到哪些功能可以放到一个类,就把这些功能整合在一起,类仅仅是顺手将一些数据与函数放在一起的聚合体,没有数据或功能上的内聚。后两次作业,有所感觉,根据表达式的层次化结构,将各种运算抽象出来,将各种运算门抽象为类,每个运算的类只需要完成这个运算的求导操作。格式检查,求导,化简是比较独立的三个板块,所以应当为每个板块建立一个相对独立的层次,三个板块之间只需要共享部分数据。
本单元中每个对象要实现一定的功能与数据的内聚,不同的板块之间最好要有清晰的界限。
第二单元
第二单元电梯系列的线程安全是重中之重,我基于对共享数据的分析,对临界区代码都使用了synchronized()
进行同步互斥,采取了电梯执行与乘客调度分离的架构,电梯完成乘客的请求,调度器专门对乘客的请求进行分派,电梯线程使用了状态模式进行建模。
这一单元最重要的线程安全设计,在我看来线程安全是一个面向对象中一个不可避免的矛盾,每个类都假设自己独占数据,只关心自己的数据如何处理,不会主动关心整个环境所处的状态,而整体的功能正常实现却需要各个类的协作与交互才能够实现,这个矛盾的存在,使得程序员必须让不同的线程在时序上同步与互斥,确保按照一定的执行序列执行。线程安全设计相当于在对象化的世界中建立的一种法规,例如红绿灯的出现,正式为了保证行人和车辆只能互斥访问交叉路口,这样的规则的构建应该独立于对象,要在一个更高的层次上来规划与设计。
第三单元
第三单元的没有太多的宏观架构的考虑,更多地是如何选择数据结构将JML中的规格以更低的复杂度实现,在本单元,许多类的实现是为了方便建立某些特殊的数据结构,方便对数据进行管理。这一单元更多启发我规格的作用,本次作业中许多方法只需要按照规格就可以无脑地实现,这种方便与快捷也大大地说明了规格与实现分离是一种非常优秀的OO思想,能够让我在实现的时候能够更加专注于数据结构与算法的选择,而不同特别的关心架构问题。
第四单元
第四单元更多的是层次化处理,将UML的层次化结构在自己的代码中体现出来。在本单元中,我采取了独特的设计,每个类需要管理每个类所需要的数据之外,顶层类对于所有的对象的存在都是可监视的(上帝视角),但是顶层类对所有对象只读不可写,这样的好处是顶层类在实现不同层次的类的交互时可以起到桥梁的作用,但是对数据的实际管理还是落实到了每个具体的类。这也提示我们高内聚低耦合不是简简单单的内聚越高,耦合越少便是好的,适当的耦合可以使得交互更加方便,而且对整个程序的结构没有很大的破坏,在处理实际问题的时候,这些OO设计原则不应当生搬硬套,要与自己的业务逻辑紧密结合,达到最好的权衡。
总结自己在四个单元中测试理解与实践的演进
通过一个学期的课程,也提高了许多测试相关的能力,随着作业的演进,我学会了写数据生成器,对拍机,自动化测评工具,从一个人写到多个人协作开发,测试效率越来越高,对强测也越来越有信心。
第一单元
本单元主要采取手动构造极端数据,使用python进行正确性的判定。
第二单元
本单元通过按照一定策略生成乘客请求,并通过书写正确性判定逻辑进行正确性的判定。
第三单元
本单元通过一定策略生成数据,通过对拍进行正确性的判定。
第四单元
本单元主要通过手动构造UML模型生成数据,通过对拍进行正确性的判定。
测试虽然没有明面上在课程设置中体现出来,但是强测的高质量测试数据真正地驱动我们进行高质量的测评。测评从单打独斗到协作开发,也让我认识到真正的开发过程中团队协作的重要性,通过交流与合作,能够更好地对数据的极端情况进行挖掘,也减轻了个人的工作量,提高测试的效果。
总结自己的课程收获
能够熟练地使用Java语言进行一定规模的开发,学会了使用git进行版本管理(上个学期计组如果也使用git我也不会起那么多长长的文件名了......),学会了测评数据的生成与对拍机的实现。
OO课有很多交流,通过交流能够碰撞思维的火花,能够结交友谊。这个学期和许多同学讨论过一些作业的问题,虽然很多都是线上交流讨论,并没有见过面,但是不影响对技术进行深入的交流与探讨,从他人身上得到一些新的启发,或许以后见过面可能会说:“原来您就是xxx,幸会幸会(久仰久仰)——”。
OO课更多的是一门哲学课(好吧哲学课怎会会有WA和TLE呢),通过OO课掌握了对象化的编程思想,更多的教会了我一种认知与解决问题的方法论,层次化,模型化,并发设计这些思想不仅在程序设计上发挥作用,在生活的方方面面也能够找到影子。
OO的博客作业非常有意义,特别是对于我这种表达能力不是很强的人,通过博客不仅能帮我梳理自己的思路,总结教训,提取经验,也能够锻炼我的表达能力,如何让其他人通过你的博客了解的思想,在程序员世界这个高度开放的社区,写博客的能力非常重要,优秀的博客和代码一样,能够成为自己的一张名片,体现个人的能力。
立足于自己的体会给课程提三个具体改进建议
关于实验课
建议每次实验课前提前发布一下本次实验课的实验内容,这样课下能够做一定的准备,不至于实验课对着大量的代码发呆,例如GC的那一次课上实验,建议提前发布一个内容让我们先自学一下比如实现一个Demo,不至于课上只写了一个仅仅能够通过样例的代码就可笑地认为自己写对了。
关于课程节奏
一周的课程安排可以说是无缝衔接,体验非常良好,但是我认为还可以再改进一下,周一周二的互测阶段其实互测本身花费不了那么多时间,(卷王除外),互测阶段我都会根据我对本次作业的易错点的预判读一读代码,如果没有很明显的错误,剩下的就基本上交给测评机了,一个晚上的时间足矣,而且周三晚上才发布作业,周三白天的时间相当于闲置了,建议作业发布和互测同时开始,这样能够有更多的时间理解并实现作业。
每个单元最难受的基本上都是第一次作业,我在完成第一次作业的时候除了要关心架构设计,还要学一些本单元特有的基础知识,例如第二单元花了一整天的时间才理解了同步互斥的含义并学会实现一个简单的Demo,留给作业的时间就比较少了,感到比较吃力,建议把每个单元的第一次作业与上一个单元的博客作业同时发布,这样能够有更多的时间理解下一个单元的内容。
关于作业内容
JML和UML两个单元的作业难度相较于前两个单元确实小了许多,但是作业完成起来非常煎熬。JML要实时关注讨论区对代码和JML的修改,UML单元指导书有许多表意比较模糊的点都要通过讨论区来加以确定,总之一点都不干净利落,耗费了很多时间。
个人建议后两个单元指导书如果没有大幅的改动,前一届的讨论区可以整理成一份资料传给下一级,毕竟针对同样的表述,大家产生的疑惑也应该大致相同。JML和UML两个单元主要对JML和UML的理解做的比较多,并没有真正写JML,也没有用UML进行模型的设计,很难真正认识到JML与UML的威力,建议这两个单元可以淡化对算法的考察,增添一些对JML和UML本身的训练内容。UML单元可以训练一下用UML准确描述一个工程的模型,但是这一部分最大的难度是怎么给同学们进行考评。