面向对象 | 第四单元 | 总结
一、架构设计

上图是本单元第三次作业的UML类图。Graphic类用来管理三种UML图,Graphic类下面的三大部分各自管理一种UML图,从左往右依次是类图、状态图、顺序图,这三种图的管理基本采取同样的结构,即节点接口、节点实现类和边类。考虑到我们本单元的需求是完成一个管理UML图的程序,而无论是类图、状态图还是顺序图,其本质上都是基于图的结构,图由节点和边构成,对于不同的图,节点和边代表的具体含义各不相同,例如类图的边可以代表关联关系、接口实现关系或者泛化关系,而状态图的边则代表状态转移关系,Graphic类负责对UmlElement进行解析并生成相应的图结构,Graphic类也向上提供相应的查询方法和检查方法。考虑到状态图和顺序图都不止一个,所以有StateMachine类和Interaction来唯一的代表一个状态图或顺序图。在图结构解析并生成完成后,原始的UmlElement内容不再被需要,它们完全被封装到各自所对应的的节点或者边内部了。
回顾三次作业,本单元的结构设计的扩展性是做的不错的,第一次作业的Graphic类下面只有左三分之一,即类图的管理部分,第二次作业扩展时,几乎完全不需要接触任何与第一次作业有关的代码,只添加了右三分之二的内容,在第三次作业时,考虑到了效率的问题,在三种图结构的内部穿插了八个规则检查的方法,这是一个需要反思的地方,或许更好的办法是将第三次作业的功能代码也尽量独立出来,建立规则检查的类,从外部而非内部对三种图结构进行检查。
二、面向对象与架构设计
谈架构设计与面向对象是分不开的,因为好的架构设计,无时无刻不体现着面向对象的思想。其实我认为面向对象更多的是一种思想,数据与函数的封装、泛化、扩展等等,以对象与对象交互的角度来理解和实现一个程序,它不只是C++或Java,而是一种高于语言之上的思想。这一点我在一个个人项目中体会颇深,有一段时间我在设计一个C语言项目,希望能够尽可能实现卡西欧计算器的功能,在架构设计的过程中,我不断地在思考应该把哪些数据结构和哪些函数放在同一个头文件里,在实现的过程中也在不断调整,试图让代码结构显得清晰明了。我想,实际上我将面向对象的思想运用到了C语言的编写过程中,而Java给我们提供了一个更好的平台,它就是为面向对象而生的语言,如果我们写Java时,为什么不充分不利用面向对象的便利性呢?
再回过头来看整个学期的12次代码作业,在第一单元,我还没有学会用Java的各种容器,自己构造容器花费了一定的精力和时间,其实大可不必的,扩展性欠佳,在第三次作业时进行了整体的重构,那一周花费了大量的时间来进行重构、测试和漏洞修复,深刻体会到了因为代码设计扩展性差带来的问题。在第二单元,开始熟练使用Java容器,并且在代码架构上也下了很大的功夫,值得庆祝的是,第二单元的三次作业扩展是顺利的,虽然多线程是很大的挑战,也使得debug的难度增大了不少,但是在代码架构上的表现是不错的。在第三单元,让我意识到了一个我从未思考过的事情,“程序的真正难度不在于实现,在于效率”,如果只考虑实现,第三单元的作业只需要按照JML语言写代码就能够实现,但是问题出在效率上,每当我想要提高效率时,代码架构就开始变得混乱不堪,某些功能的代码因为效率的需要被打散分布在某个类的各个地方,导致代码维护和修复变得复杂。另外,JML语言所描述的需求,并不能代表代码的真正架构,这一点是需要明确的,如果把所有的实现都放在JML所描述的架构中去,代码将非常的冗杂。在第四单元,遇见了和第三单元类似的问题,即因为效率原因,不同功能的代码相互交织,显得混乱冗杂,但这次作业的优点是,实现了比较好的可扩展性,三次作业零重构。
三、测试
对我来说,代码测试是最头疼最花时间的一个环节,针对效率问题,我一般采用自动生成测试样例的方式进行测试,而针对程序bug,则采用手动设计特殊的测试样例来追踪bug位置。在第一单元,完全依靠手动设计测试样例的方式完成了测试,效果比较好。在第二单元,多线程程序的debug是一个头疼的问题,因为多线程程序运行具有随机性,无法进行单步调试,我所采用的方式是在程序内部添加大量的输出信息,尤其是线程添加、删除、共享访问这些容易出现bug的地方,同时针对每一处共享访问,进行了比较严密的逻辑分析,尽可能通过逻辑检查的方式来减少死锁等问题的发生。设计了自动生成测试样例的程序,但是自动生成的测试样例的测试效率并不高,不如手动设计的测试样例。在第三单元,运用了Junit进行单元测试,这是非常方便的,Junit可以为程序每个重要的方法提供测试凭条,静态测试代码被保存下来,当因为各种原因程序的一部分发生更改时,通过再次执行这些单元测试,可以保证更改不会导致其它地方出错,我认为用Junit进行测试的效率是比较高的,覆盖面广、粒度较细。设计了自动生成测试样例的程序,主要用来生成大规模的数据来测试程序的性能。在第四单元,测试方式与第一单元类似,完全依靠手动设计测试样例,这一次测试的效果是很好的,依靠绘制包含各种特殊情况的UML图作为测试样例,找出了程序绝大多数的bug,在强测中也获得了较好的分数。
四、课程收获
学习了一门语言。首先最直接的就是学习了一门语言——Java语言。最初认识Java是13岁开始玩一款叫Minecraft的游戏,需要安装Java环境才能够运行,18岁开始学习第一门程序设计语言C语言的同时,也认识到Java是另一种程序设计语言,如今我能够运用Java语言实现具有各种各样功能的程序,我能够熟练地运用容器构造各种数据结构,我能够使用多态、继承、接口等面向对象语言的特点来使得程序设计更加便利和快捷,我能够运用多线程程序来描述生活中更多的问题,那些单线程程序无法描述的问题。
学习了一种思想。学习了面向对象的编程思想。个人对于面向对象的理解在上面已经提到过了,与其说面向对象是一类编程语言,不如说它是一种编程思想,这种思想同样可以运用在C语言的编程上。把问题域拆分成对象,把问题域中元素之间的联系用对象之间的互相访问来描述,每个对象只关心自己内部的东西,程序变成了一种岛与桥的结构。面向对象的目的在于,更清晰的代码架构、更好的可替换性和可扩展性、更方便的分工与合作等等,在写程序的过程中,无论是使用什么样的语言,我认为都应该以这些目的作为要求。
提升了几种能力。首先是提升了高级语言程序代码编写的能力,这一学期的代码量是很可观的,而代码量是衡量编程能力的重要指标之一,因为只有亲自编写了足够多的代码,才会清楚地认识到什么样的问题应该用怎样的方式来解决,才能很熟练地运用各种设计模式与开发框架。其次是提升了程序框架设计的能力,架构设计的具体分析在上文中也总结过了,在大一学习C语言时,从来没有考虑过关于程序架构设计的问题,因为那时候一个程序的代码量并不大,而现在,面对复杂的需求,代码量上千行已经是家常便饭了,如何设计不同类、如何设计类与类之间的访问关系,是框架设计的核心之一。最后是提升了测试与bug修复的能力,关于测试上文也总结过了,测试是项目开发的重要环节之一,测试的核心问题在于,如何高效率地发现和解决尽可能多的问题,这学期我也在不断尝试各种各样的测试方法,而关于bug修复,我认为最重要的还是首先要思考错误输出的可能原因,有可能不需要单步调试就能找到bug的位置,熟练运用IDEA的单步调试工具,是快速定位bug的关键。
五、课程建议
我认为面向对象课程的设置还是挺不错的,唯一的不足是,理论课程与代码作业有些脱节,理论课程中讲的很多东西并不能体现在代码作业,而完成代码作业甚至不需要听理论课的内容,如果代码作业能够更加体现理论课上所讲的东西,我觉得会更好。
六、线上学习体会
线上学习总体上说还是不如在校学习好,虽然也有优点,比如说时间的安排更加自由、更大的书桌、独立的学习环境等等,但是缺点也很显著。PPT录屏课的感觉没有现场课的感觉好,老师始终按照自己的节奏讲课,无法与学生们进行互动,而学生始终盯着视频学习很容易思想跑毛;与同学的沟通交流不够方便,在学校里,遇到困难时可以第一时间与其他同学面对面进行交流和探讨,但是在家里只能通过微信的方式,而微信是延后的、低效的、容易误解的。

浙公网安备 33010602011771号