301
社区成员
发帖
与我相关
我的任务
分享在本单元中,我们所学习的重点就是正向建模与开发。正向建模与开发的关键在于自顶向下的设计和实现过程,从需求到设计,再到编程和测试,逐步细化和具体化。
正向建模与开发首先要对需求进行分析,了解系统的功能需求和非功能需求。这一步就是我们的指导书。第二步就是系统设计,根据需求分析的结果,画出uml类图,时序图等,接下来就是具体的实现过程,在这一过程中,我们还需要对图进行进一步的补充。在完成编程的工作之后,我们需要编写测试用例并进行测试,以确保系统按照需求正常工作。最后是维护工作,但在我们这一单元的作业中省略了这一步。
正向建模要求我们进行透彻的需求分析并通过 UML 可视化模型呈现,学习模型化设计思维方式,有助于我们理清需求、设计、实现层次的结构和行为:通过类图按数据和行为提取抽象形成抽象层次结构,通过顺序图确定哪些对象参与交互及对象需提供的操作从而识别类之间的关联关系,通过状态图进一步完善类的行为,在这个过程中建立了关联层次,实现层次设计。
类图、状态图和顺序图一致十分重要,它们从不同的角度描述系统的需求和行为,保持一致性有助于确保系统在各个层面上都准确反映需求。类图定义了系统的静态结构,而状态图和顺序图描述了系统的动态行为,保持一致性有助于避免设计上的冲突和不一致,有助于确保系统各个方面都经过充分验证。

第一次作业需要完成的是借书,预约,取书等流程。为此,我设计了图书馆类,借还处类,预约处类,学生类。图书馆类负责管理所有的学生和预约处以及借还处。每次遇到新的学生就把这个学生加入到图书馆所管理的学生中。能否借书和预约书由学生自己管理(学生根据自己借的书判断),借还处保留借阅失败和还到借还处的书,并且及时送回图书馆。

第二次作业增加了图书漂流功能以及图书借阅期限限制。
对于新增的图书漂流功能,我们需要新增一个图书漂流角的类,管理被送到图书漂流角的图书。对于新增的图书借阅期限限制,我们需要在学生类中记录借到书的时间,对于不同种类的书籍给出借阅限制。

第三次作业增加了信用分,需要在学生类中加入信用分属性以及各种修改信用分的方法。需要注意的是修改信用分的时机,由于有积分上限的限制,修改积分的先后顺序会影响积分的最终值。在学生类中新增了一个标记是否被扣过分的标记位。由于图书馆不是每天都开门,但是我们规定必须在逾期当天扣学生的信用分,所以加入标记位避免学生被重复扣分。
在第一单元,我们需要完成的是表达式的计算和化简。此时在上学期面向对象先导课的帮助下,我们已经初步建立了面向对象的思维,而第一单元是利用这种思想最深刻的一个单元。第一单元是利用递归下降的算法处理表达式,利用指导书中给的形式化语言描述,形成抽象的结构描述。在第一单元中,项由因子组成,因子又包括常量因子、变量因子,表达式因子等,表达式由项相加,项由因子相乘,我们利用递归下降的算法解析表达式,再利用表达式,项,因子之间的关系进行计算与化简,在解析时,我们给定一个表达式,自上而下地使用递归下降法得到一个个元素,获得表达式树。然后在计算的过程中我们采用“基本项”架构,利用每一层级的toPoly方法自下而上地得到最终的结果。通过形式化描述设计架构时,抽象层次结构利用继承和接口,通过对一组类共性行为的抽取结果使行为设计和行为实现相分离,减少代码冗余性。
第二单元通过电梯作业考察多线程编程,以及多线程编程中的一些设计模式。在这一单元中,最重要的设计模式就是生产者消费者模式,电梯请求作为生产者,我们设计的调度器作为托盘,电梯作为消费者。我们需要精心设计代码架构,仔细编程,以保证这三个部分协调工作。而线程、共享、交互形成了面向并发和协同抽象的层次结构,通过 synchronized 关键字、读写锁等线程互斥方式,保证线程安全,通过 wait、notify、join 等线程协作方式保证并发行为的协同和效率。这也是整个第二单元最麻烦的一部分。在第二单元中,架构设计的重要性不像第一单元那样体现得那么明显,但是也是十分重要的,我的体会就是单一职责。除此之外就是“谁管谁”,输入线程为主请求添加请求,调用调度线程的重置方法,调度线程管理主请求和所有电梯,电梯负责运人和重置……最后是运行和策略分开,所以专门设置策略类,根据电梯的状态为电梯的运行提供策略。
在第三单元中,我们通过jml学习契约式编程,或者叫规格化设计。在这个单元中体会最深的就是规格与实现分离,这是指将规格说明与具体实现分开,以实现更好的灵活性、可维护性和可扩展性。在第三单元中,给了我们规格,要求我们对其进行实现,但是实现并不是完全照着规格来,规格只是对数据和方法进行了及其严谨的描述,而实际的实现与规格是分离的,规格并没由限制模块内部细节设计,所以数据容器的选择、中间数据的存储和检索、规格的层次化以及算法的选择依然是需要在实现中思考的问题。就比如第三单元中的所有people全部都是list形式,而实际实现的过程中,使用 HashMap 进行存储显然是一个更好的办法。
模型化设计指先使用系统化的模型语言来表示设计结果,进而开展设计与实现,通过类图按数据和类提取抽象形成抽象层次,通过顺序图完善类的职责和关联关系,通过状态图完善类的行为规格设计,进行正向建模。第四单元的作业整体还是不算太难,但是其中的正向建模思想是我们需要掌握的。实际上,越是大型的项目和工程,正项建模的方式越能体现出优势,而我们的几次作业的规模都比较小,时序图和状态图元都比较简单,所以这样的实现方式体现不出优势,但是其中的思想是我们需要掌握的。事实上,这一单元的实现思路是最接近实际的软件开发的。
最后,我想说,面向对象这门课,只有最后全部经历过一遍,才能明白课程这样安排的深意。第一单元的主题是"表达式展开",通过这一单元的学习,我们更进一步体会面向对象的思想,第二单元的主题是"电梯调度",要求我们将关注点从"对象的行为"转移到"对象的交互",开始学习多线程编程,理解对象之间的协作和时序关系,以高效地完成任务,第三单元的主题是"JML规格",通过这一单元的学习,我们掌握了契约式编程,了解实际工程,尤其是高精尖项目中的编程方法,通过规格实现代码,第四单元的主题是"UML建模语言",作为最后一个单元,更加接近实际的编程,也通过建模语言更加深刻了解了面向对象的思想。回顾四个单元的学习,实际上先是打基础,之后越来越接近于实际工程的开发模式和思想。
测试的实现比较简单,python 库中有 sympy, 直接调用即可,关键是要保证测试的全面性,这就要从指导书中的数据范围入手,观察数据范围,测试边界情形。
多线程的程序 bug 复现具有偶然性,这使得找bug的难度比较高,实际上在第二单元,通过走读代码发现的问题反而更多。第二单元的测试重点是高并发请求场景,例如所有人同时请求从1层到11层,这种类似的数据往往能找到bug.
第三单元的整体测试思路还是边界数据,大量数据。但是不能盲目,如果只是单纯增加人数(点的数量)而不是关系的数量(边的数量),那么测试的效率就比较低。就比如有的测试点,虽然看起来指令不少,但是实际上这个数据点所构建出来的图是非常稀疏的,这就会导致很多情况测不到。所以我们需要精心设计规模庞大稠密图,以保证测到所有的方法(这就是中测的Junit测试考察的内容)。当然,正确性是一方面,性能也是比较重要的一方面,为此,需要考虑大量的某一指令同时发出的情况
第四单元的测试思路也是一种正向建模,需要我们考虑各种场景以及边界情况构造数据(逾期当天,信用分在20附近……)
OO课还是十分充实的,在写代码的过程中会面临不少问题,在解决问题的过程中会收获不少知识,也能在实际编程过程中提高自己的能力。在课程结束之际,我自认为很难的编程工作最后都完成了,回过头来看不由得感到收获满满。