BUAA-OO-Unit4 总结

正向建模与开发

所谓"正向建模与开发"是指,先使用UML等工具完成我们项目模型的构建,再去使用代码对着我们的模型设计进行实现。与此前仅仅确定架构不同的是,在正向建模与开发中,我们不仅仅要确定我们整个项目中的类与对应职能,更要通过类图、顺序图、状态图等工具,细化到具体的类的属性、方法,而非仅仅停留在架构设计层面的“抽象概念”。

此前的三个单元中,我们大多采取的都是逆向开发过程,在与前三个单元的开发感受与经验对比之下,本单元我的核心感悟主要为三方面。

一方面是和JML的相似,其实从本质上而言,UML和JML干了相似的事情,即提供了一种所谓"协议"或者说"规范",通过事先规范好类中方法的实现、类的数据管理职能与特性,来为我们的实现提供指导。同时,其实给定一个规范的同时,我们其实可以想象为一个虚拟的项目已经随着规范的制定被抽象地实现了,这一点为我们设计测试样例提供了一个很好的基础,同时,考虑到我们在实现的过程中其实往往处于一种"局部、短视"的状态中,规范使得我们仅仅需要考虑局部的问题、如何遵循好这样的规范,而不用去瞻前顾后考虑全局的影响,这必然会让我们能够safer from bugs。

一方面是局部与全局的问题,在逆向建模的过程中,我们其实往往仅能考虑到局部的问题,对于全局其实是盲目的,会陷入一种“局部最优解”,而忽视局部实现对于全局项目的影响,这往往会导致我们的系统出现各种各样难以预料的bug。而正向建模的过程中,我们将先从一个高位的、全局的视角去解析整个项目的运行流程,在全局的角度思考项目架构的设计。

最后一点其实是在正向建模中的一种“经验之谈”,其实往往我们在进行模型设计的时候,总会有种过于fancy的异想天开,但是真正到实现的阶段,我们难免发现在模型设计阶段的一些布置其实难以落地真正地实现。因而,即使在正向建模中,我们对于架构的设计仍应该给自己“留有余地”,通过仅给出部分必要方法,剩下的在实现中逐步扩展发挥,更为恰当。

架构设计

在这里插入图片描述
在本单元中,我的图书馆依赖一个Library类进行指令解析和调度其余各个类运行,如Shelf,AppointTable,DriftTableServeTable,将不同的只能拆散到不同的类中,进行一番解耦。

其实在UML和代码实现的真正实现架构之间进行了多次协调后才最终统一为以上所示,在代码实现的过程中,我常常会发现代码中有的方法不得不依赖另一个类的对象来实现,但是在最初的UML建模设计中,我并没有考虑到这样的关联。在将这样的关联一一加入UML类图中后,我又发现这样实现后,UML图中关联多了许多,类之间的耦合度过高,以至于为了降低耦合度需要重新设计改进方法进行迭代优化。

如此可见,对于更大的工程项目,其实希望一次性获得圆满无需改进的架构设计是非常困难的,迭代开发优化可能是难以避免的事情,因此,在设计阶段本身留有一定的实现灵活性是必须的。

四个单元的架构设计演变

Unit1的核心是层次化设计,其实在Unit1中,我明显感觉到依赖Java灵活的继承与接口实现,可以节省很大的Coding开销。因而,其实感觉第一单元的架构设计思路是如何通过多层次设计,设计接口与父子类关系去满足业务需求、灵活解决问题。

Unit2的核心是多线程模型,在Unit2中的架构设计其实主要是围绕着线程安全的模型展开的,一个最基本的概念就是“生产者 - 消费者”模型。在Unit2中,其实在架构设计层面让我最为苦恼的可以概括为对于“线程到底是怎样的身份的疑问”,最终,我经过思考确定了在生产者消费者模型中,线程实体应该作为一种“过程”存在(就像主类Main中仅仅有一个“main()过程”一样),线程通过调用一个“处理机对象”来实现对于“共享对象”的数据管理与操作,而非线程本身来实现这样的操作。第二单元中,我学会了如何在多线程这一特殊场景下进行架构设计。

Unit3的核心是JML语言,事实上第三单元的架构已经基本固定,我们的任务仅仅是对于JML描述的方法实现。然而,其实在实现的过程中,我们会依赖一些辅助类来辅助项目主干去进行一些数据管理与方法实现,在第三单元中,我学习到的更多是如何在架构主干已经基本确定的背景下,如何在主干上扩展架构。

Unit4的核心是UML建模,可以说本单元的核心就是架构设计与对UML的了解,但是其实由于业务流程较为简单,在设计层面并没有过多推陈出新的点,不过,在UML中引入关联、单向关联等内容后(此前的自动生成器往往仅包含继承与接口实现),在架构设计时,更能直观看出自身对于类的设计的耦合程度,是否满足OO设计理念的“高内聚,低耦合”在一张图上就能明显看出来,在本单元中,我更加深入的了解了“高内聚,低耦合”这一设计理念的内涵。

四个单元的测试演变

其实,从U1 ~ U4我都贯彻了单元测试 + 整体测试的思路。

btw感谢dpo的开源与测试平台搭建对于测试的辅助与自行开发评测机的启发作用。

在U1的表达式解析中,一方面自行构造单元测试样例,一方面我在前几次都使用了python自带的表达式解析包进行测试,然而,当面对函数时无能为力,就将评测机的搭建思路从依赖已有库变成数据生成器+对拍,也在这样的过程中发现自己和同学的bug,收获颇丰。

在U2中,由于多线程特性,测试这件事变得异常困难,举步维艰。鉴于多线程特性与实现方法差异无法对拍,评测机必须根据输入输出逻辑进行判断构造,以至于本单元的评测机搭建十分困难,单元测试成为了保证正确性的核心,在本单元中,我意识到当整体测试难以进行时,必须要重心放在单元测试上,依赖大量完备单元测试来保证实现正确性,当然整体测试与架构设计仍然必不可少。

在U3中,其实测试的困难程度回到了U1的水平,不过测试的思维有所差异。这一点主要是由于JML的原因,我们需要根据JML语言的描述对其条件与效果进行测试,其实这给了我们一些关于“测试与可靠性”的启发,在此前的单元测试中我们其实是盲目的进行测试,我们自己对于某个方法的实现功能其实是并不严谨的,我们并没能有一种“规范”来确认输入输出的逻辑,而有了JML的规范后,我们的测试变得有的放矢,并且可以保证在足量测试后,这个方法一定与JML描述维持一致。在本单元中,显然也是通过数据生成器 + 对拍的形式来进行整体系统的测试的。

在U4中的测试,其实我并没有写过多的单元测试样例,其实,我也在这单元感觉到,单元测试样例的必要性和系统复杂度是成正相关的,当系统的逻辑较为清晰简单时,写过多的单元测试其实有很强边际效益,收益甚微,而只需要较好的整体测试就足以保证系统运行的稳健性了。

就评测机搭建体验来说,难度大约可为 U2 >= U4 > U1 = U3

总结自己的课程收获

首先,最核心的当然是面向对象设计思维下的工程设计与开发,不仅仅是Java、在Python的评测机搭建中,我也使用了这样的思维。面向对象的思维从过程式编程中走出,为我们解决实际业务需求提供了新的视角与新的思路,为此后的工作奠定了基础。

其次,是关于开发、设计与测试的协调关系,其实这三件事情就组成了我们实现项目业务功能的全过程,在OO课程中,我深刻感受到了有“规范协议”下的编程有很大的优越性,以及在经总结中学习到了如何协调三者关系(Test-First Programing & Design Before Implements)来实现一个更加安全、稳健的系统。

以及,对于迭代开发的认识。在几单元的学习中,迭代式的开发总是难以避免的,不仅仅是简单的debug乃至重构,迭代的意义更包含了:将复杂业务逻辑拆分成子业务的“分而治之”,先实现一个baseline再进行优化的性能精进,在最初设计与真正实现之间的不断协调。

在为期一学期的OO课程中,支付了大量的精力与心血,哪怕过程中存在遗憾,但是在这3个月的学习中,我能够明显感觉到我代码能力的精进、思维的严谨化,实在收获颇丰。

  • 20
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值