摘要:本单元聚焦于UML类图顺序图与状态图,通过本单元学习,我强化了面向对象的结构知识,对面向对象代码中各个部分的内容及其之间的关系有了更深入的理解
一、作业架构设计
本次作业的核心之一在于类图、顺序图与状态图模型的构建。我采用的方法是用单例模式构造Constructor类专门处理三种图。首先要对输入的数组UmlElement进行分类。为了方便统一管理,我对每一种UmlElement都单独新建了Hw开头的对应类,例如UmlClass对应为HwClass。与Uml类不同,Hw类不仅有自身信息,还有自己管理的所有元素,以及与查询相关的方法。具体的构造如下:
其中的每个以Hw开头的类都是HwInfo的子类,受限于空间没有将泛化关系表示出来。
可以看到,与三种图关系最密切的类为类图的HwClass与HwInterface、顺序图的HwInteraction、状态图的HwStateMachine。
在构造整体关系时,我的方法是顺序处理类图、顺序图和状态图,再对每一种处理都按照上述UML图所示从低到高进行构造。以类图为例,首先处理Parameter,将其放置到对应的Operation中;其次处理关系(Generalization、InterfaceRealization),为HwClass和HwInterface设置相关的parentClass、kidsClass、realizedInterface和parentInterface、kidsInterface、kidsClass,方便之后进行关系相关的查询;之后处理AssociationEnd,根据U4T3的要求将Association对应的与类相关的UmlAssociationEnd加入HwClass中;最后将处理好的operation和attribute加入到对应的HwClass中,即可完成一个类的构建。通过类似的方法亦可以处理顺序图和状态图,其中注意到这里顺序图用的是interaction而非collaboration,主要是因为大部分顺序图的成员其parent都为interaction,只有attribute的parent为collaboration。我最终将collaboration以HwInfo的形式交给interaction管理,这样就可以很方便的构造顺序图了。
完成了构筑下一步就是进行查询。由于查询的方法都保存在MyImplement中,而构筑好的类图、顺序图和状态图都保存在Constructor中,故需要将Constructor这个单例类交给MyImplement管理,并从中获得构筑好的HwClass集合、HwInterface集合、HwInteraction集合、HwStateMachine集合,就可以进行查询了。
查询时,将分发给对应的类处理。例如查询方法的parameter名字是否为空,就需要先到HwClass中查询其下管理的所有HwOperation,再到每一个Operation中查询其下管理的所有Parameter,最后parameter调用自身从HwInfo继承的isNameEmpty方法就能完成查询。这样就能够让每一个自己设置的Hw类具有非常好的独立性和安全性,也让查询操作具有更好的逻辑性。
二、四个单元中架构设计思维及OO方法理解的演进
第一单元:混沌黑暗的起步期
在完成第一单元的作业时,仍然大量使用了非面向对象的思考方式。虽然尝试着根据运算类型和多项式的层次关系设置了各种类,但是每个类管理的属性和方法都有些不甚合理,导致很多函数的功能冗杂,逻辑上有较大的缺陷性。这也给第一单元的三次作业造成了很多困难,进行了多次重构。
第二单元:突飞猛进的上升期
第二单元的电梯作业由于比较具象,构筑出的类也更加清晰明了。特别是在生产消费者模型的知道下,我能够很清楚的想明白每个类所需要具备的属性和方法(这也说明了诸如工厂模式、单例模式、生产消费者模型的基本构造方法与关系思路对于面向对象中明确类的功能上有着非常巨大的帮助作用),所以在整体架构的设计上有着非常好的逻辑性。具体体现为在本单元的三次作业中,我每次都只需要进行少量的删改就
能完成任务。其中比较关键的一点我认为是我在第一次作业中就意识到调度器也需要设置为线程,这样当数据从输入发送到电梯,就需要经过一段流水线的结构。这对于我本单元的设计帮助非常大。
第三单元:改良改进的进步期
由于第二单元带来的面向对象思路的极大进步,第三单元作业处理的也就更轻松(当然很大原因是架构部分已经被官方包建立完毕,自己只需要实现多个接口即可)。不过第三单元仍然带给我了很多收获。在第三单元中由于主要实现接口,故需要处理的主要对象为方法(即函数)。经过了第三单元,我对于方法的设计有了长足的进步。在jml的指导下,我明白了每一个方法都仅仅需要完成部分特定的功能即可,不需要贪心想着让一个方法实现更多种的功能。简洁和高效是方法设计最重要的核心。
第四单元:逐渐成型的稳定期
第四单元对UML三图的学习,不仅加深了我面向对象的构成理解,也在作业中辅助我进行更好的架构设计。在最后的三次作业中,我设计了Constructor单例下的构造类,将构造与查询分离,使其各司其职;我对类的属性和方法都有了细致和严谨的考虑,让每一个类的属性都与类本身紧密相连、让每一个类的方法都仅仅针对自身完成有限且充分的功能。通过多个方法的组合调用实现具体的功能;同时我还尽可能在算法上进行优化,以实现整体程序的性能优化。
三、测试理解与实践的演进
测试问题贯穿程序设计的任何时期,好的测试策略和方法能大大提升对程序的验证能力,对让自己的程序有更好的安全性、稳定性、高效性发挥着建设性的作用。
在课程初期,我的测试都依赖于官方给出的数据点,因此遇到问题时往往有些手足无措,像无头苍蝇一样误打误撞地对bug进行查找。一段时间后,我发现同学们会分享自己构造的样例,在这个时期我将这些同学们的样例也加入到了测试的方法中。后来由于作业的难点通常集中于某些特定输入,我因此开始针对代码的特点,设计简短而具有针对性的测试样例,进行高效的测试。最后到了第三单元,由于开发作业程序的难度有所下降,我的开发效率也提升了,因此得以有多出来的时间尝试编写测试样例生成器。当然我生成的测试样例强度还并不是很高,但是胜在量大,所以还是能够很好的帮助我发现并修改问题。我认为测试生成中,最难的是为样例生成器设计每个样例对应的参考标准输出。我看到有许多同学都实现了相关的功能,但是我尝试了数次仍然无法保证标准输出的结果一定正确。这也是我目前有待学习和改进的地方。
四、总结自己的课程收获
第一单元:我学习了多项式化简求和的一般思路,掌握了递归下降的处理方法,实现了对表达式进行的抽象化处理;
第二单元:我学习了多线程任务的一般处理流程,学习了多线程程序线程间交互的多种模式,并且着重掌握了生产者-消费者的架构模型。同时我了解了多线程程序存在的线程安全问题,了解了多种多线程的上锁方法以及各自的优势,学习并掌握了死锁的触发机制与解决方法。当然还学习了很多非常重要的设计模式,例如工厂模式、单例模式等。其中,我个人在作业当中多次使用了单例模式,对于这种设计模式有了更进一步的理解与掌握;
第三单元:我学习了JML语言,掌握了契约式编程的流程与方法,并学会了自己在写方法时撰写相应的JML规格。同时,我学习并掌握了异常抛出的理论和方法,抛出异常可以让程序出错的概率大大降低,在实践中我体会到了异常的抛出非常有利于程序的安全和可靠。最后第三单元的练习很大改善了我对于函数的处理,使得我在之后的函数撰写中都会仔细考虑函数的设计构造以防止其功能冗杂;
第四单元:学习了UML类图、顺序图和状态图,以及UML下mdj文件的阅读方法。我进一步强化了对面向对象组织结构的理解,也在最后的几次作业中实践了前三个单元掌握的一些内容。第四单元作业也对我的架构设计能力进行了进一步的强化。
总而言之,我最大的收获就是掌握了面向对象设计与构造的基本思想和方法,对象是属性及其方法的封装体,其属性和方法需要与自身紧密联系,并具有和外界互动的能力。面向对象将程序模块化和结构化,使得程序设计以工程化的形式进行处理,有助于提升了程序设计的效率。通过oo课的学习,我掌握了工程化编写程序的方法,我会将一个程序的完成分为架构设计、各部分功能设计、面向对象细节设计、算法设计、构造程序架构、构造属性方法、填写方法具体内容、检查和测试、bug的修正与程序的改良九大步,这个流程可以非常好的辅助我完成每一次oo作业。
五、改进建议
1、由于之前对于java语言不够熟悉,我即使经过了pre的训练,在真正进入第一单元学习之后还是因为不熟悉语言遇到了巨大的学习阻力,完成作业时压力很大。我希望之后课程组能在pre与第一单元之间加一堂衔接课,带领同学们复习pre的知识,学习java的语言使用特点,让同学们对java语言有更好的熟悉度;
2、第一单元我认为是对于认识面向对象而言非常重要的一单元,在本单元中需要逐步理解面向对象的思维与方法。然而我个人在第一单元作业中,还是会为了完成特定的去括号任务而采用面向过程的思想方法。我认为一单元如下改进会很好:
第一次作业:
a、主要内容和要求:让同学们在第一次作业中先解析表达式,构建出项、系数、多项式、三角函数的类,给出这些类的一些方法或属性的要求,并可以根据输入的式子进行元素查询。
b、输入输出样例:输入样例可以设计为一个多项式、一个项或一个三角函数,之后输入查询总次数,最后输入具体查询内容,比如查询三角函数的系数和、x次数最高项的系数等。
例如:输入了多项式4x**2+(3x-8*sin(x**2)+2cos(x)),然后再输入查询总次数2,最后两次查询:0(x次数最高项的系数);1(三角函数的系数和);
输出:4\n -6\n;
第二次作业:引入括号、求和函数,要求可以对系数为1的括号项去括号、对同类项进行加减法的合并、对求和函数进行化简;
第三次作业:引入乘法、幂运算和自定义函数,要求可以进行括号项间乘法运算、括号项的幂运算和自定义函数的化简运算。
在这个作业方案中,我们首先关注的是对象的构成,其次再是对象间的互动,我认为更能体现出面向对象设计与构造的思维特点,同时也让大家在一单元开头就有一个较好的架构,减轻同学们重构的压力。
3、在阅读指导书时,我会很容易遗漏指导书中的某些要求或提示,在某些内容上的理解也可能与指导书有出入。我认为可以再在每次作业中单独设置一个疑难解答板块,首先官方整理一下本次作业中的所有要点和提示,将其置顶于该板块中;其次同学们如果对指导书的内容有疑问可以在该板块下提问,由助教、老师们优先解答;最后助教可以从微信群中找出一些大家提出的共性问题,单独在板块下写帖子解答。为了防止信息冗杂,可以对疑难解答板块下的每一个帖子都设置一个标签,标签可以以目录的形式进行访问。例如在U4T3作业中我对R002的操作有疑问,那我发求助帖时就可以写标签为R002,而这个R002标签将在疑难解答板块的标签目录中进行显示。当其他同学也对R002操作有疑问时,就可以点击R002标签,快速访问该标签下所有的提问。
最后非常感谢本学期为oo课辛勤工作的每位老师和助教。