第三单元总结性博客
第九次作业
本次作业主要完成了一个社交网络的基本框架,主要包含以下三个部分:
Person
组成了社交网络中的“节点”,本身具有一定的属性,并且与其它的 Person
之间有熟人关系,形成了社交网络中的“边”。
Group
是一个 Person
群组,主要用于统计群组中的 Person
属性。
Network是我们建立的社交网络,相当于数据结构中的“图”,和后面的查询具有紧密的关系。
我们要完成的任务就是理解整体架构并实现JML的描述。
第十次作业
第十次作业主要完成了增量开发:
实现 Message
接口,并且修改原来的代码,实现消息的发送和接收。
实现新指令的增加,尤其注意的是指令queryLeastConnection
。
第十一次作业
第十一次作业主要完成的增量开发:
拓展 Message
类,实现其三个子类,以用来实现不同的功能。
实现新指令的增加,尤其注意的是指令sendIndirectMessage
。
测试数据的构建
针对本单元的需要,我主要采用了随机生成数据的方法,并且对于数据进行一定的限制,自动化对拍进行测试。
首先是常规指令的生成,在数据生成初期只生成ap
、ar
、ag
、atg
指令,并且尽量缩小数据的范围,并且保证数据的数量,来构建一个比较大规模的社交网络。
之后,随机生成各种查询指令,在最初,只是无规律的随机将作业中需要的二十余类数据进行生成并进行测试,但是这样的方法查询效果并不是很好,完全随机生成的数据让大多数指令的结果都是抛出某种异常,这样就很大程度丧失了测试的覆盖范围。
之后我们增加了相关部分的代码,通过添加一定数量的Person和Group,保证了后续查询指令的有效性。此外,对于一些相关规格细节和性能的测试,我们通过手动来构造,比如检查 qlc
指令的性能,通过添加足够的简单指令,在课程要求的范围内,增加足够的此指令,就能够检查出来一定的性能问题。
代码问题和修复情况
非性能问题
查询方法,当查询的某一个属性出现 null
时,应该要对其特别处理,比如我的代码中出现对 null
的对象使用了其它方法,这显然是不合适的。
性能问题
主要出现在 qci
, qlc
, sim
,方法的复杂度问题,在我的第一版代码中,并没有注意这方面的维护,因此除了很多问题。
修复情况
qci:使用并查集进行查询。这是本单元第一次作业中最困难的一个函数,之后根据讨论区中的帖子,改成使用并查集的方式实现。
qlc:由于以及实现并查集,我选择使用通过并查集来优化Kruskal算法在合并划分以及判断划分时的时间复杂度,从而实现优化的Kruskal算法。
Network拓展
首先,对于产品,设计一个接口Product,对于每一个产品,我们关心的是他的属性,在我们的要求中并没有体现出来价格,不过价格也是重要的因素。
price
:商品的价格,可能影响到客户能否购买,影响 Person
类的资金查询。
type
:商品的类别,可以设置为枚举类。
其次,对于 “Advertiser:持续向外发送产品广告” ,我们可以拓展自己的 Messgae
,增加新的商业广告信息 saleMessage
,对于此类增加的信息可以有:
toGroup
:除了之前直接发送给个人,或许可以直接发送给 Group
,比较贴近现实
对于 Person
类,题目中说明关注广告并选择和自己偏好匹配的产品来购买,那么就应该增加其它的属性:
首先是涉及的三类人可以通过继承Person接口实现。
Advertiser
:经销商。需要存储发送的广告信息saleMessage[]
,并负责发送推销消息;
Producer
:产品商。需要存储自己生产的products[]
,产品数目 nums[]
和收入inputs[]
,负责提供产品。
Costomer
:消费者。需要存储自己的需求types[]
和需求量demands[]
,已经拥有的产品。
Person
保持原状,不过也需要增加对相关属性的查询。
判断消费者是否会购买这个产品
/*
@ public normal_behavior
@ assignable \nothing;
@ ensures \result == ((\exists int i; 0 <= i && i <= types.length;
@ product.getType.equals(types[i]) &&
@ product.getPrice < money));
*/
public boolean checkDemand(Product product);
查询消费者是否购买此类产品
/*
@ public normal_behavior
@ assignable \nothing;
@ ensures \result == ((\exists int i; 0 <= i && i <=
@ products.length;
@ products[i].getType.equals(product.getType))
*/
public boolean checkProduct(Product product);
消费者购买产品
/*
@ public normal_behavior
@ assignable \nothing;
@ requires product.getPrice < money;
@ requires (\exists int i; 0 <= i && i <= types.length;
@ product.getType.equals(types[i]))
@ ensures money + product.getPrice = \old(money);
@ ensures (\forall int i; 0 <= i && i < \old(products.length); products[i] == \old(products[i]));
@ ensures products.length = \old(products.length) + 1;
@ also
@ public exceptional_behavior
@ signals (PersonNotPurchase e)
*/
public void getProduct(Product product);
心得体会
这一单元整体难度不大,但是我做的效果不好,究其原因,是对于 jml
规格的阅读不够熟练,对于复杂方法的 jml