面向对象第三单元博客

测试数据

 在本单元的测试中,基本上采用的是基本功能测试+JML中的特殊情况测试+大数据随机生成测试。即先使用一些基本的数据进行测试,确保能满足一定的功能,之后再仔细阅读JML规格,看是否存在一些边界情况。如在第三次作业中的群发红包,当红包金额不能被群人数整除时,存在着结果可能不是相同整数的情况。最后再随机生成大数据进行对拍测试
(这里感谢一下群友,他们提供了很多无私的帮助)。

架构分析

  总体上的架构按照JML实现,故不赘述
  在一些函数的实现上,除了维护最基本的图的信息外,还额外建立了一些数据结构,如在判断是否连通时使用的并查集以及在对于某些比较复杂的查询的“脏位”,如果存储了最新的结果则直接使用,反之则计算。一定程度上提高了代码的效率

性能问题

  在最下面的学习体会也会提到这一点,由于直接按照规格写代码,导致我的性能很差,在之后也是不断的修改。第二和第三次作业在强侧中均有一个点超时。最后的处理方法为在理解JML描述上重新修改算法,并加入“脏位”

Network扩展

  对于这些不同的Person,其继承原本的Person类,之后新增一些额外的属性和方法

Advertiser:新增属性,准备打广告的产品,广告。新增方法,生成广告
Producer:新增方法,生产产品
Customer:新增属性,感兴趣的广告,准备购买的产品;新增方法:增加感情兴趣的产品

  相应的,其他的类也需要做出一定的修改

Message:新增生产产品消息,广告消息与购买消息
Network:相应的修改sendMessage的逻辑
Product:新增类,表示产品
Advertisement:新增类,表示广告

  具体的行为是
  1.Producer生产产品,之后发送信息给Advertiser。
  2.Advertiser获得产品信息并存入准备打广告的产品,之后其可以生成广告,并将广告信息发送给相应的Customer。
  3.Customer接受到广告信息后,会根据是否对产品感兴趣,决定是否产生购买意向。
  现给出生产产品,生成广告和增加消费者感兴趣产品的JML代码。

/*@ public normal_behavior
 @ assignable productsProduced;
 @ ensures productsProduced.length == \old(productsProduced.length) + 1;
 @ ensures (\forall int i; 0 <= i && i < \old(productsProduced.length);
 @          (\exists int j; 0 <= j && j < productsProduced.length; productsProduced[j] == (\old(productsProduced[i]))));
 @ ensures (\num_of int i; 0 <= i && i < productsProduced.length; productsProduced[i] == product) =
 @           (\num_of int i; 0 <= i && i < \old(people).length; \old(productsProduced)[i] == product) + 1;
 @*/
public void producing(Product product);


/*@ public normal_behavior
@ assignable products;
@ ensures products.length == \old(products.length) - 1;
@ ensures (\forall int i; 0 <= i && i < productsProduced.length && products[i] != product;
@          (\exists int j; 0 <= j && j < \old(productsProduced.length); productsProduced[j] == (\old(productsProduced[i]))));
@ ensures (\num_of int i; 0 <= i && i < productsProduced.length; productsProduced[i] == product) =
@           (\num_of int i; 0 <= i && i < \old(people).length; \old(productsProduced)[i] == product) - 1;
@ ensures  \result = Advertisement(product,...);
@*/
public Advertisement advertising(Product product);

/*@ public normal_behavior
  @ requires !(\exists int i; 0 <= i && i < interests.length; interests[i].equals(product));
  @ assignable interests;
  @ ensures interests.length == \old(interests.length) + 1;
  @ ensures (\forall int i; 0 <= i && i < \old(interests.length);
  @          (\exists int j; 0 <= j && j < interests.length; interests[j] == (\old(interests[i]))));
  @ ensures (\exists int i; 0 <= i && i < interests.length; interests[i] == product);
  @ also
  @ public exceptional_behavior
  @ signals (EqualGroupIdException e) (\exists int i; 0 <= i && i < interests.length;
  @                                     interests[i].equals(product));
  @*/
public void addInterest(Product product) throws EqualInterest;

学习体会

  就像课上诸老师提到的,希望我们在以后在回想这一单元时,是语言的规格,而不是社交网络的一些代码实现,我也在这里谈谈自己对JML的看法吧。

  第一点就是,虽然JML可能在某些方面看起来和java语言很类似,但是二者是有着很大的差异的。这个差异不是语法上的,而是动机上的。JML的目的是描述清楚其功能,而我们所使用的java语言的目的是实现其功能。换言之,一个的要求是看的明白,另一个的要求是实现的好。在本单元最开始的时候,我犯了这样的一个错误——模仿JML写代码,它用什么,我就用什么。这导致了最开始的是时候,我的代码了出现了很多不必要甚至是愚蠢的的多重循环,性能很差。比如说在已经实现了并查集的基础上,在查询图的连通分量的时候,还是按照规格要求的,进行两次循环,判断人与人之间的关系,而事实上完全可以直接判断顶级父节点的数目。

  第二点想谈一谈建模语言本身的一些东西。在这一单元的学习中,可以经常听到,我自己也有这个想法——学JML是有用的么?为了一门语言,而学习另一门语言,这似乎是一个愚蠢的过程。但如果抽象的看,为了编程,学习一种思想,即一种模型化的思想,一种目的导向的描述方法,这似乎就合理多了。从这个角度来看,JML没用,建模语言有用——那既然其有用,而我们又需要学习,不如就JML了。这是我个人的一点想法,如有谬误,欢迎斧正。
(不过我好像也没有查到什么CML之类的建模语言,不知道有没有QWQ)

  最后一点想随便谈一谈JML和UML以及其他的一些建模语言
image
  从本质上来说,建模语言是为了规范化表示某些特定的内容而产生的,而对于其他的一些相关的,最近也有所查阅。看了一些之后,第一反应就是繁琐,每种语言都有都有自己一套的表示规则,也确确实实有所长短,想了想,感觉人的交流真是充满困难,充斥着语言的二义性以及未提及的边界条件。如果真的要清楚表示一个意思,到真有可能变成自然语言的建模。
  这个单元的博客充斥着碎碎念,对自己的代码分析倒是较少,究其原因,可能是我真的是按照JML写的,没啥可分析的

posted @ 2022-06-05 10:49  荀彧1732  阅读(27)  评论(1编辑  收藏  举报