OO_第四单元总结
架构设计
第一次作业
主要实现对UML类图的解析和查询。
解析:
UML图的.mdj
文件经由官方提供的jar包可以转换为多个UmlElement。由于输入的json数据无序,因此需要通过三个循环来根据元素的type分层解析。同一层的元素解析顺序不会影响结果,而下一层的元素会依赖上一层解析完毕的元素。
第一层:UmlClass
, UmlInterface
第二层:UmlAttribute
, UmlOperation
, UmlAssociationEnd
,
UmlGeneralization
, UmlInterfaceRealization
第三层:UmlParameter
, UmlAssociation
自己设计了MyUmlClass
、MyUmlInterface
、 MyUmlInteraction
、MyUmlOperation
包装了对应的类并添加了新的属性和方法。例如MyUmlClass
增加了父类、attributes
、operations
、implementInterfaces
、associations
等属性以及相关方法。在解析时,将关键信息提取并存储。
查询:
在顶层类MyUmlInteraction
中实现存储并分配解析到的数据,以及根据相应的查询操作调用自定义类实例的方法从中获取相应的数据。
第二次作业
新增解析并查询状态图和顺序图的功能。
顶层的MyUmlGeneralInteraction
将所有元素按照类别划分给类图交互模块、顺序图交互模块、状态图交互模块。注意UmlAttribute
这一元素在类图和顺序图中均存在,因此需要分配给两个模块令其自行判断是否为自己的attribute。
MyUmlStateChartInteraction
负责解析并查询状态图。MyUmlCollaborationInteraction
负责解析并查询顺序图。
与解析类图思想相似,在解析状态图和顺序图时,我们仍然分层解析,并在statemodel
包下自定义普通状态、起止状态、状态转换等类,在collaborationmodel
包下自定义EndPoint
、Interaction
、LifeLine
等类,用于包装对应的UmlElement并新增属性和方法。
第三次作业
新增对解析格式规范的检查,若有错误格式需要抛出异常。架构与第二次作业基本相同。
架构设计及OO方法理解的演进
第一单元
第一单元中切实体会到了面向过程到面向对象的转换。在此之前所写的代码还是算法题居多,读取输入、存到数据结构中,经过特定的算法得到结果,简短的程序代码量一般最多只有数百行。此外用python跟着书做过几个小项目,的确实现了面向对象思想的运用,但许多地方只是跟着书实现,并不了解为何要如此设计,做完之后仍对于面向对象的理解尚浅。
在本单元第一次作业中,思维还只是像做算法题一样,局限于“完成本个任务”,没有考虑后续迭代的可扩展性、可维护性,所以只是用一个大正则表达式来循环提取表达式的项,甚至用了replaceAll
来预处理加减号,这种解析方式太依赖于具体场景,可扩展性弱,因此在第二次作业需要表达式支持()
后,便不得不重构。
第二三次作业中需要表达式增加支持三角函数以及括号嵌套的求导,那么将因子、项、表达式等实际模型设计成类,而后根据形式化表述,从顶向下递归解析。每一层的导数都是下一层导数的乘积、加减的组合。
第一单元的设计偏重于多种类的组合,通过自行设计架构,也确实对OO的理解以及优势更进一步。因此本单元对于OO的理解更侧重于“封装”这一维度,可以划分为一个模块的代码设计成一个类,高内聚,将细节封装在类内部,对外暴露方法,实现特定功能。类之间松耦合,可以通过提取抽象成接口,减少类之间相互之间的依赖,实现未来需要对某个类改动时,对其他的类影响尽量小。
第二单元
第二单元引入了并发的设计,需要我们建立线程安全的协作结构。
主要是输入线程+调度器线程+电梯线程三类之间的协调配合。采用生产者-消费者模式,通过wait
和notifyAll
操作实现线程配合,将请求队列设置为线程安全类,就可以更加妥善管理锁的分布,使得锁不会杂乱。
本单元的实践带着入门了线程并发,在一次次与死锁、轮询、无法正常结束等情况打交道之后,也对线程安全的设计与debug有了一定的经验。在大规模应用系统中,高并发是一个十分重要的问题,在本单元的入门引领下,个人也出于兴趣对多线程进一步了解了一些,正在阅读《图解java多线程设计模式》,并打算在暑假读完。
第三单元
本单元主要侧重对JML规格的阅读理解与实现。通过阅读了大量JML规格语言,对于JML的理解由初始的晦涩逐步熟练。对OO 的理解更加开阔,可以为对架构进行设定,可以为需求做模型,提高pm与实现人员的交互准确程度。
此外,本单元涉及到了比较多的图论算法,通过JML语言,我们要尽量去理解其表达的核心实现需求,将其抽离并通过较好的算法实现(连通块、最短路、缓存等),如果只按照JML中的多重循环,时间复杂度无疑是很高的。
第四单元
本单元主要通过对UML图元素的解析以及建模,对UML图进行一个更深刻的了解。架构在前文已有表述。本单元对于OO认知的进步主要体现在对于UML图的认识、熟悉到可以自己作图。通过UML图我们可以直观的理解陌生项目的架构与设计,也可以方便地对别人表述自己项目的设计。
测试理解与实践的演进
第一单元中黑盒测试运用较多,通过形式化表述来递归生成随机数据,构造数据生成器,将个人标准输出与标准库的正确输出对比,初步了解了自动化测试的思想与实践。此外学习到了构建“常量池”等方法来针对性生成满足条件的数据(小数据、爆int的数据、爆long的数据)。
第二单元中,生成随机数据比较容易编写,但难点在于如何测试输出的正确性,毕竟如果采用的调度策略不同,那么输出也并不相同,无法采用对拍的形式来验证结果。这就需要我们自己构建规则,检查输出的合法性(是否运送完所有乘客、是否到达指定楼层等等)。除了输出的合法性,死锁、线程未被唤醒等造成的程序无法正常结束的问题也需要重视,这种bug无法复线,需要通过检查程序逻辑、打断点测试等白盒测试方法来修复bug。
第三单元中,主要运用的是图论的算法,我们可以采用类似第一单元的自动测试的黑盒方法。此外,首次接触JUnit单元测试,单元测试能够检查我们在迭代之后是否对原功能造成了影响。是一个良好的测试习惯。在大型项目中,我们没有标准库提供标准数据,也没有同功能项目来和我们对拍,此时单元测试便显得十分重要。此外,由于方法均有完善的JML规格表述,因此重新阅读JML、检查对比代码逻辑也是一个良好的测试方法。
第四单元,主要通过手动在startUml中搭建UML图,将.mdj
文件通过官方jar包转换为输入数据来观察输出。当输入数据构建逻辑比较复杂时,手动构造边界数据也是一个良好的测试方法。
可以说,测试是我们编写代码十分重要的一环,在参与一些团队项目、开源社区项目中,自己能够编写的代码可能并不会很多,但一定要经过一系列测试确保功能正确,才能merge到项目当中。
课程收获
- 面向对象思想
之前对于面向对象的理解局限于一个class
,通过课程教学,也逐渐扩充了对面向对象思想的认知,封装、多态、继承体现了面向对象的特征,但OOP的核心在于这种思想,即隐藏细节、状态通过消息传递的方式来修改等,从而为编写庞大、复杂的系统而服务。
- Java基础的熟练
大量的代码练习,夯实了个人对于java基础的认识与理解。现在回顾廖雪峰的Java教程,许多之前感到晦涩难懂的地方,都有一种拨云见日豁然开朗的感觉。
- 自主设计较大规模程序结构的经验
在设计程序结构时,有时能够将一些学习到的设计模式的思想融入其中。也逐渐明白了一个良好程序架构的重要性。
- 引路人
多线程单元的设计编写,引导设计一个初具规模的多线程项目,同时也为大家打开了多线程的大门。通过个人探索,也了解到高并发对于大规模企业及应用的重要作用,或许之后会找一找相关方面的源码来读一读。
JML规格语言,初窥团队开发规范的表现形式。之后如果参与到大规模团队开发中,相信会大有裨益。
UML图,通过解析的实践的形式,更容易对UML图印象更深刻,了解更充分。因为之前阅读一些项目的设计文档,也会见到UML图的形式的解析,可见能够对UML图有一个良好的理解熟练度是十分重要的
- 博客
能够写出一篇逻辑清晰、深入浅出的好博客并不容易,同时这样一个输出过程也很重要。自己之前的博客多是笔记性质的文章,个人输出很少。课程组要求的博客也算是令本人体验了原创博文的感觉,但总体感觉写出的文章还是处于胡言乱语的状态。希望自己之后能够有能力写一些逻辑清晰、文笔细腻、深入浅出的文章,做一些输出。
- 讲座
在两场讲座中的收获还是很不错的,但感觉麦和音响设备有待提升,不坐前排大部分分享都听不清。讲座相当于开了几个与工业界的接口,从中得以一窥工业界核心项目方向(阿里云这种toB型团队对于大规模数据的处理方式、中台成熟度,给中小企业提供轮子的情况等等)以及算法落地(CV/NLP/RI方向研究员/工程师在实际场景中需要处理的工作等)。相信大部分同学的目标还是工业界方面的发展,一些不同团队、不同方向的业界一线人员的分享总还是能带给大家一些视野的开阔,如果能找到自己感兴趣的方向,那自然是很好的。同时这也驱动着我对于开发/算法方向的发展做了一些更深入的了解,了解过程中也更新了我之前对于就业/读研方面的认知。之前觉得深度学习相关领域很高大上,很火,在6系all in ai的氛围下也跟着加了实验室,想着打打杂争取发个paper再申个霉国的ms/phd。但现在算法岗待遇基本和开发差不多竞争却激烈得多,并且硕士大部分拿到的算法岗也只是算法工程师,干的活和开发基本也差不多,和博士出来的研究员还是有很大差别的。而且开发也有很多值得研究的领域:分布式、高并发等等,目前开发岗大趋势是本硕同薪,这么一看国内3年读个研似乎很亏。而且现在签证政策很不友好,出国也不怎么打算了。(怎么写着写着写出了职业规划课的感觉...果然是最近这方面东西刷太多了吗)
改进建议
- 希望能够给出实验课结果。
虽然实验课大部分情况下偏简单,但确实有时候会有几个点不确定,还是希望看一下答案查缺补漏的。
- 讨论区发言的排布形式有待改进。
目前的排布应该是假设所有人都对发帖人做回复,但如果要对该帖下发言的其他人回复,就只能顺序排布到所有发言的最后,显的回复对象并不明确。如果帖子下发言多,就显得很乱,也不知道谁回复谁。或许可以考虑加一个层次化的回复结构?
- 难度安排与时间安排
实际开发过程中还是能明显感觉到某次作业相比于其他几次作业而言过于复杂。比较突出的是第一单元第二次作业、第二单元第一次作业。如果能将工程量匀给其他作业,体验应该会比较舒服。
以及整个时间流程,感觉对于其他课程排课时间考虑比较少,例如互测,周一晚开放,周二晚截止,但周二大部分人一天都是满课,并且周一的那段时间还要贡献给明天扎心的os上机,很难抽出什么时间读代码、hack(除非利用上课时间,不过不少人就是这么做的hhh)。然后任务量大的话,基本就是周六日杀器,现在回忆起来这学期的周六日基本都是在oo中度过的。
- 研讨课安排
研讨课的形式或许值得商榷,目前研讨课的知识传递效率可以说并不高,课堂状态怎么样或许大家也了解。以我不专业的眼光来看,一是语言信息获取密度低,二是讲述的形式天然提不起学生兴趣。窃以为,希望分享的同学将内容分享给助教/老师,由老师/助教挑选一些亮点内容,将所有班级的内容整合放到oo平台上,让学生坐到机房看这些内容,相信知识吸收效率应该远超这个。也可以加入一些互动元素,有什么问题去找分享者问,有什么新的思考可以实时发出。