BUAA OO 第四单元
前言
第三单元是根据jml描述进行程序的设计与实现,而第四单元则是根据uml相关图实现程序,两者有些相同,都是根据一种事先的设计来编写程序。但同时又有很大程度的不同,做个比喻,第三单元更像是给你一篇外语文章,让你将其翻译(你自己可以在某些地方添加润色),而第四单元像是给你建筑的设计要求与图纸,让你搭建整个建筑。我认为uml图更能让人理解程序的结构和整体框架与功能,而jml描述能对细节描述得更准确,不容易产生使用自然语言描述容易出现的歧义和限制不全的问题(第三单元诋毁jml,第四单元第一次作业质疑jml,第二次作业理解jml)
正向建模与开发
虽然名字听着很高端,但我觉得正向开发其实很好理解,具体来说就是在开始敲代码或者工作前,先想好需求并构思好设计与框架。第四单元的正向建模与开发,是先通过指导书理解题意与需求,先设计uml图(类图、顺序图、状态图),再根据自己的uml图编写程序。这很像中学时期老师要求作文下笔前要有提纲和文章整体构思一样,文章不能想到哪写到哪,程序也不能边写边想。如果没有事先考虑全面设计的需求,写到一半才发现还有功能没实现,或者已写的框架不容易处理后续的功能,那么重构是很痛苦的(每次新作业要重构基本也是这个原因,因为我在前面的作业不了解后续迭代要加什么离谱的功能)。
不过虽然课程组要求先画uml图再写程序,但我实际是先写的程序再画的图(纯偷懒,先画uml图后面还得不停改,太麻烦)。不过我这几次的作业其实仍是正向的开发,因为我事先根据设计需求自己画了框架、流程、状态转移的草图,效果其实跟uml画图建模一样(但随手拿个笔开画可方便多了,主要是StarUML用的不熟练,效率低)。根据我自己这几次作业的经历,正向开发确实帮助我减少了程序的重构和大改,最基础的核心功能类都在第一次作业开始前的建模确定,并在后续的迭代中没有经历大的改动。
使用UML进行正向建模与开发:类图、状态图与顺序图可以静态和动态地描述程序系统与功能。本单元进行正向建模与开发的第一步便是分析需求,然后根据需求用uml建模,具体的:
- 类图:根据程序中不同的功能部分设计程序的类(如拥有不同职责的各种管理员,给他们分别建类实现功能)、根据需求中各部分的交互设计对应类之间的联系(比如各种管理员的协同工作,其对应类间存在关联关系)
- 状态图:根据设计需求中的不同状态设计状态图的状态,并分析需求中状态改变的时机与条件,这些都需要在uml状态图中体现(有点像画一个状态机的状态转移情况)
- 顺序图:分析需求中完整处理某种情况或事件的流程,使用自己程序的类和方法描述其完整的处理顺序与流程(比如一个人还一本损坏的外校的C书,完整的经过流程是先到本校自助机器,再去借还管理员交罚款,然后回到自助机器还书,这天结束书由图书管理处运出,第二天到达外校的图书管理处。需要使用程序中的类和方法,通过发送消息的方式描述完整的处理流程)
架构设计
第3次作业完成后程序的完整架构设计如下图:
用一个类来分析输入的字符串中的信息,然后调用各个管理员类的方法进行处理。除了分析输入的类,其他类都是严格按照指导书中各个图书馆部门的功能实现的,一些处理的流程也是严格按照指导书的要求实现(实际上可以进行化简,比如还损坏的C书:直接先去借还管理员交罚款再去自助机器还书即可,其实不用先去自助机器。但是严格按照要求实现方便正向建模和开发,增强具体设计与需求的对应关系)。
由于程序的具体实现几乎是完全模拟了指导书中图书馆运作的所有细节,所以在后续迭代时并没有进行大规模的重构,因为指导书其实也是在上一次指导书的内容上添加新东西,所以里面一些旧的部分所对应的程序我并不需要改动。uml类图随着第2次作业中新加入的图书管理处,添加了一些新的相关类,其余均没有大改,有的只是一些方法的修改与增添。状态图和顺序图的内容可以说几乎是将指导书中的中文描述用我自己的方法和类翻译了一遍,我没有进行很大程度的设计精简与抽象(导致代码量很多),不过也正因如此,我的状态图和顺序图可能也更容易理解。
一本书的各种状态与状态转变:
预定新书并到手的完整流程:
架构设计思维演进
- 第一单元:根据递归下降的方法设计架构与程序处理的具体流程,根据表达式的形式化表达设计类
- 第二单元:学习并使用了生产者与消费者的多线程设计模型与框架
- 第三单元:纯翻译了一遍jml,但是学了一些关于图的算法,也学到了一些动态维护的思想(不是每次需要某个值的时候才去计算,而是在类里设置相关的属性,随着每次的调整与修改便对属性进行更新,当需要查时直接读即可,不用复杂地算一遍)
- 第四单元:学会正向开发的思想,敲代码前先全面地分析需求并进行相关建模
通过一学期oo的学习,我设计程序的思路逐渐由面向过程(大一敲的c语言代码,一堆自定义函数)转变到面向对象(一堆类),开始关注架构中类的内聚与耦合(这对程序的可读性、修改与迭代很重要,重构,血的教训),开始使用各种模式(如工厂模式等),开始注重将程序模块化与层次化,开始运用继承和接口来简化架构、提高设计的可读性与可维护性(并且学习了关于继承的相关限制与规则,怎么样继承才是安全的),开始在编写程序前进行需求的详细分析和对程序系统的事先建模。我自己认为我在架构设计思维上,确实有了不小的改变与进步。
测试思维演进
- 第一单元:单纯地手捏数据进行测试,尽可能地测试了程序的全部功能(但肯定没测完,只是测了最基础的功能,并没有覆盖复杂的情况)
- 第二单元:用测评机用大量的随机数据进行了测试,测试程序功能的正确性(性能摆了,也没测)
- 第三单元:穷举所有情况测试(Oktest),手捏极端数据进行边界情况的测试和进行压力测试(考查算法的时候),回归测试(因为不同次作业我改了不一样的算法,用回归测试验证迭代开发时之前功能的正确性)
- 第四单元:分别测试程序的各个功能(分别测借书、还书、预定书的各个功能),再统一测试程序(用测评机编的包含各种请求的数据进行测试,测试程序的所有功能和各个功能之间的相互联系的正确性)
总的来说测试思路其实就是黑箱测试、白箱测试、单元测试、功能测试、集成测试、压力测试、回归测试等等。
课程收获
首先,肯定是学到了很多知识(java语法、递归下降、多线程、jml、图的相关算法、uml、面向对象思想等等)。从这个方面来说,这一学期的oo课程我的收获挺多的,尽管有些许抱怨和不理解(jml感觉应用前景不是很广阔),但确实是会了很多之前不会的东西(毕竟以前的我连一个java程序都跑不通)。
除了学到知识以外,oo课程的体验也让我收获了很多,首先便是抗压能力。我在正式上课之前就在知乎上搜索了关于北航oo课程的评价,除了清一色的难,还有人说oo的教学方式与普通的大学课程有很大的不同,更像是进入企业工作后真正开始做项目的模式(根据需求设计程序,多次迭代增添和优化功能,进行测试确保程序的准确),我非常地同意,是不是可以说oo课程的学习为我增添了处理大型(也并不是很大,不过比我大一数据结构的大作业大)项目的经验?(所以我把代码贴在github上,能有加拿大企业来找我吗?)不过可以肯定的是,如果以后我遇见了学习上的困难和压力,要顶不住时,可以回想一下在每周日下午7点半疯狂debug的自己,说不定就撑过去了,oo课程前两个单元的难度确实是把我的抗压能力拉满了。
除了以上的收获,oo课程还告诉了我程序架构和测试的重要性。一个好的架构设计便于迭代开发和修改,这是我在好几次痛苦的重构经历中体会到的血的教训。而测试对程序太过重要了,我曾有过中测全过但又发现了2位数bug的情况。几乎每次作业我都没有认为我的测试已经足够完善了、程序没有bug了,时常是周日从下午一直测试到终止提交前几分钟才去吃饭(有好几次在下午7点极限修bug);总是到了每次互测结束,看见强测的全对和互测的0次被hack,心才放下了。不过也许正是因为我对测试过分在意,才能在最后碰巧捞到一个金身奖吧(拿着那个小金人,感觉之前所有的测试和debug都是值得的,感谢这次金身放水,因为我互测其实被刀中过一次)。
当然,也有些许遗憾,没能在性能方面尽全力,一是能力确实不够,二是时间有点少,基本拿去测试和debug了,三是因为改善性能程序会更复杂,害怕出错。
方面尽全力,一是能力确实不够,二是时间有点少,基本拿去测试和debug了,三是因为改善性能程序会更复杂,害怕出错。
不过总结来说,一学期的课程有收获,也有痛苦,有庆幸也有遗憾,有感动也有抱怨,我自己仍然愿意仍为oo是一门好课,也希望它越来越好,感谢各位老师与助教的一路陪伴与帮助。