TakiP

导航

BUAAOO 第三单元总结

BUAAOO 第三单元总结

前言

逻辑实现前的规格设计,是逼迫程序员带着镣铐跳舞的桎梏吗?在此之前从未有过规格设计、契约式编程的概念与经验的我,初识JML指导下的工程设计,心情是复杂的。

一方面,写代码的过程因为有了规格的指引,剥离了需求逻辑整体设计的不可名状的云雾,代码的编写仿佛成了单调直接的翻译工作——比起镣铐与桎梏,规格仿佛是将程序员向头脑简单四肢发达的方向驯化的外骨骼;另一方面,规格又确实地显示出它的掣肘之处,逻辑的具体实现因为外赋的不可改变的躯壳,成为了无法逾越的空气墙。作为程序员——逻辑的具体实现者,如何与基于特定形式化语言的规格契约协作?

 

戴着镣铐的 Gymnopédies.

迭代开发的三周很快驱除了规格的镣铐之形,也把我从自铸的桎梏中解放。


 

实现规格要求的设计策略

细读卖身契。

规格是什么?规格是要求,是约定,是条件一定、结果驱动的人为法则。规格,是逻辑实现者向需求提供者的卖身契——太糟糕了,让我们采用更加高情商的说法——是颇具骑士精神的一诺千金。

实现规格要求,首先需要解析规格要求——规格定义的是什么?理论课已经给出了这一问题的答案:外部可感知行为语义。封闭的、使用者无法观测的程序黑箱与外界的双向交互模式与约定,正是规格设计所先行定义的。具体到JML,以前置条件和后置条件分别对应抽象的“程序(方法、类...)输入”与“输出”,从而从两个方向阐明了行为逻辑结构设计者的期望。

然而,规格也留下了它并不试图解决的难题——程序的黑箱仍在,黑箱之中的运作机制仍需要逻辑实现者来选择和实现。阅读JML并实现的过程,重点在于牢牢把握需求的范围与本质,前者是“隐性的输入”,既包括时域上的限制,也包括空间上的制约;后者则是对抽象的具象化,是基于形式化抽象的无二义性而再建构的问题的实貌。

进行了如是的分析与重构,作为逻辑实现者的我们才能算是真正有效率地读懂了规格。

基于JML的测试方法和策略

以形式化逻辑抽象解决杂糅问题。

事实上,刚刚接触JML时我也有过疑问,既然人的思维天生就是具象而非抽象的,为什么不能将需求以其原样传递,而要经过形式逻辑抽象的二次中转呢?换句话说,形式逻辑的规格表示的优势在哪?

在尝试利用JML工具链进行测试时,优势的一大方面很直接的展示在我面前——做测试的难度大大下降了。

JML的形式逻辑规格表达,首先为静态的逻辑验证与语义检查提供了可能。虽然所限于相关工具链的发展和适配水平,生产环境仍难以使用,但对相关方法的学习和了解让我切身认识到了经过高级抽象后的编程语言仍然具有的坚实可用的数理逻辑基础——毕竟再怎么着也是跑在计算机上嘛。精确的定义与完全的定理证明或许还是不那么直接可达,但实现基础的逻辑验证已经具备了相当的可行性。

有了这样的基础,生成具有代表性的测试用例也就易如反掌了。

具体到本次作业的测试过程中,对部分关键部分使用JUnit进行了单元测试。即便如此,规格设计还是帮助我更好地把握了问题的范围,提供了对于测试Coverage的直观认识。

容器选择和使用的经验

需求给定的状况下,基于需求选择合理的数据结构就尤为重要。合理的数据结构不仅能够满足空间上的需求,也能满足时域上对性能的需求。具体到本次作业,虽然我完成代码时没有全部顾及到,但事后总结,主要在以下需求方面有针对性的数据结构需求:

大量查询

为实现较快的查询,HashSet应当是首选,本次作业中的实体又都具有易于生成Hash的特征量,使用基于Hash的数据结构应当是最佳实践。

关系映射需求

同前一点,为维护例如异常类、图类中的关系映射需求,应当采用HashMap进行维护。

最短路需求

由于采用了Dijkstra算法,使用优先队列维护小顶堆来优化性能就成为了刚需。

潜在性能问题及原因分析

路标后的危险。

需求的定义,如前述只是对结果的确证,并不约束,也并不指引具体行为。仿若告知方向却无法导航的指南针,逾越山海仍需旅行者自行考虑。

本次作业中主要隐藏着三个潜在性能问题,简析如下:

连通块计数

本次作业有统计社交网络中连通块数量的需求。如果使用遍历查询,时间复杂度将相当高。考虑到人与人之间的相连关系是双向且不会多次改变的,对于此需求,只需采用并查集即可维护整个社交网络图的上述关系。

集合值总计

本次作业中有对于值、年龄等的求和等需求。如果每次进行查询,会造成极大的性能开销。解决的方式是未雨绸缪地建立快照,在相关联改变发生时进行更新和维护,写时更新消解了查询开销,只剩下更新快照的时间开销。

最短路求解

本次作业中有对社交关系网络中最短路的求解。对于这一需求,考虑到社交网络中节点和边的总数,需采取堆优化的Dijkstra等最短路算法来压缩时间复杂度,才能避免过大的时间开销。

作业架构设计与心得体会

由于JML已经在相当程度上给定了数据与行为结构逻辑的限制与要求。本次的作业所需要我来设计的只有服务于需求的辅助数据结构——其一是并查集,其二是表征社交网络内人员社交关系的图结构。

关于本次作业中采用到的图模型构建和维护策略,对于并查集,采用了查询时的路径压缩优化,维护只涉及merge操作,总体时间复杂度大大降低;对于最短路,采用了另行维护小顶堆的方式,降低每次查询最近点的时间开销。

 

被学长们称作是“最轻松的一个月”里,从一开始“戴着镣铐跳舞”的理解,到逐渐将规格奉为“指路明灯”,再到被带入陷阱以后,终于从实践上认识到规格的本质。我意识到:规格,更像是一种“自然规律”,是不指引解决问题的方式,只指引解决问题的方向的“指南针”。和契约合作、和目的合作、与设计并行,正是程序员们面对复杂难测的需求之海,为自己立起的不移灯塔。

 

OO大冒险,堂堂连载,且待下周继续勇者斗恶龙!

posted on 2021-06-01 21:46  KumaXX  阅读(70)  评论(2编辑  收藏  举报