OO - 第三单元总结

OO第三单元总结


要求

单元总结要求



第一次作业总结

分析

  • 在本单元我们的任务为需要完成的任务为通过一个实现简单社交关系的模拟和查询的例子以此达到学习入门级 JML 规格理解与代码实现的能力

  • 本次作业只需要读懂代码中的 JML 表示语言,并且按照其中的要求编写好代码即可,由于客户需求基本都已经表述的很明白了,所以留给你的实现空间挺少的

  • JML 表示语言中的伪代码只是给你实现的一种参考,仅仅是规格层次的描述,实际上并不需要严格按照其代码编写,只要你最后的代码能满足条件即可


基本思路

  • 虽然这次的代码框架和方法已经确定,我们只需要完成的任务只是代码填空,但分析清楚代码的功能和实现逻辑还是很有必要的

  • 本次作业为实现简单社交关系的模拟和查询,核心为 MyPerson 类,管理此类的数据结构分别为实现了对应接口的 MyGroup 类以及 MyNetWork 类,三者狗证了本次作业的基本框架,在这三类中实现了所需功能对应的各种方法

  • 本次作业新增了异常处理机制,在 JML 表示语言中表明了在方法中处于何种情况下需要抛出哪一种异常,并且实现异常的计数和打印的功能


具体实现

  • 人物接口 Person

    • 重写 equalcompareTo 方法
    • 编写 idnameageGetter 方法
    • isLinked : 查看两人物之间是否存在关系
    • queryValue : 查看两人物之间关系的权重

  • 人物类 MyPerson

    • acquaintance : 存储与该人有关系的人
    • value : 存储与人的权重,与 acquaintance 的下标相对应
    • link : 使两人建立关系的方法

  • 分组接口 Group

  • addPersondelPerson: 对分组中的人的增加与删除

  • hasPerson : 查询此分组是否存在该人

  • getValueSum : 返回与此人有关系所有人的权重的总和

  • getAgeMeangetAgeVar : 获得该分组的所有人年龄的平均值,方差

  • getSize : 获得该分组的大小

  • getId : 获得该分组的id

  • 分组类 MyGroup

  • people 存储所有该分组中的人

  • 网络接口 Network

    • contains : 此网络是否包含此人
    • getPerson : 根据 id 获取对应的人物
    • addPerson : 向网络中增加人物
    • addRelation : 让两个人产生关系
    • queryValue : 获取两个人之间关系的权重
    • queryPeople : 获取网络中人数的总和
    • isCircle : 判断是否可以通过此网络中的人来使两个人之间‘间接’建立关系
    • queryBlockSum : 获取关系网的数量
    • addGroup : 向网络中增加分组
    • getGroup : 根据 id 获取对应分组
    • addToGroup : 将人物加入到分组中
    • delFromGroup : 将人物移除出分组
  • 网络类 MyNetwork

    • getRoot : 并查集数据结构,获取一个人物的根结点
    • parent : 并查集数据结构,标记一个人物的父结点
    • people : 网络中存储人物
    • groups : 网络中存储分组

  • 人物Id重复抽象类 & 任务Id重复类 PersonIdNotFoundException & MyPersonIdNotFoundException


  • 分组Id重复抽象类 & 分组Id重复类 EqualPersonIdException & MyEqualPersonIdException


  • 未具有关系抽象类 & 未具有关系类 RelationNotFoundException & MyRelationNotFoundException


  • 关系已存在抽象类 & 关系已存在类 EqualRelationException & MyEqualRelationException


  • 未找到分组Id抽象类 & 未找到分组Id类 GroupIdNotFoundException & MyGroupIdNotFoundException


  • 分组Id相同抽象类 & 分组Id相同类 EqualGroupIdException & MyEqualGroupIdException



关键算法

并查集



基于度量的程序结构分析

  • 代码规模分析

  • 方法复杂度分析(部分)

  • 类复杂度分析



第二次作业总结

分析

  • 本次作业在上一次作业的基础之上新增了 Message 类,并且新增了关于其属性和其所在网络属性的一些查询方法

  • 根据第一次作业留下的可拓展接口进行迭代开发(虚假的迭代开发:根据官方包所给 Jml 注释填空,莫得感情的填空机器)


需求变更

新增内容:

  • Message

  • 多种查询方法

  • 两种异常处理函数

数据限制变更:

  • 最大指令数:1000 \(\rightarrow\) 10000

  • add_person 指令条数不超过 2500

  • query_circle 指令条数不超过 333

  • add_group 指令条数不超过 25

  • query_least_connection 指令条数不超过 100

  • add_message 指令:保证 type01socialValue 值在 [-1000,1000]

迭代开发

新增:

  • 消息接口 Message

    • 重写 equal 方法
    • 编写 idtypePerson1Person2namegroupget 方法

  • 消息类 MyMessage

    • socialValue : 存储两个人之间关系权重

修改:

  • 人物接口 Person

    • socialValueaddget 方法
    • Moneyaddget 方法
    • Messages 的获取方法
    • receivedMessages 的获取方法

  • 人物类 MyPerson

    • Messages : 存储消息
    • Money : 存储现有钱的数量
    • socialValue : 存储活动值

  • 网络接口 Network

    • query_group_people_sum : 获取组内人物数目
    • query_group_value_sum : 获取组内人物权重的总和
    • query_group_age_var : 获取组内人物年龄的方差
    • add_message : 加入消息
    • send_message : 给某人发送消息
    • query_social_value : 获取某人的活跃度
    • query_received_messages : 获取某人接受到的所有消息
    • query_least_connection : 获取最短连接人的通路

  • 网络类 MyNetwork

    • messages : 网络中存储消息
    • beginLines & endLines : 存储有关系的二人的结点
    • values : 存储两人关系的权重

  • 消息Id重复抽象类 & 消息Id重复类 EqualMessageIdException & MyEqualMessageIdException


  • 未找到消息Id抽象类 & 未找到消息Id类 MessageIdNotFoundException & MyMessageIdNotFoundException




关键算法

最小生成树算法



基于度量的程序结构分析

  • 代码规模分析

  • 方法复杂度分析(部分)

  • 类复杂度分析



第三次作业总结

分析

  • 本次作业在上一次作业的基础之上新增了 Message 类的各个子类:EmojiMessage 类、 NoticeMessage 类、 RedEnvelopeMessage 类,并且新增了关于其属性和其所在网络属性的一些查询方法

  • 根据第二次作业留下的可拓展接口进行迭代开发(虚假的迭代开发:根据官方包所给 Jml 注释填空,莫得感情的填空机器)


需求变更

新增内容:

  • EmojiMessage

  • NoticeMessage

  • RedEnvelopeMessage

  • 多种查询方法

  • 两种异常处理函数

数据限制变更:

  • add_person 指令条数: 不超过 2500 \(\rightarrow\) 不超过 5000

  • send_indirect_message 指令条数不超过 1000

  • emoji_id(int) 值在 [0,10000]

  • add_messageadd_red_envelope_messageadd_notice_messageadd_emoji_message 指令:保证 type01socialValue(int) 值在 [-1000,1000] 中, money(int) 值在 [0,200] 中, string(String) 长度不超过 100

迭代开发

新增:

  • 表情消息接口 EmojiMessage

    • socialValueget 方法

  • 表情消息类 MyEmojiMessage


  • 公告消息接口 NoticeMessage

    • 消息内容 Stringget 方法

  • 公告消息类 MyNoticeMessage


  • 红包消息接口 RedEnvelopeMessage

    • Moneyget 方法

  • 红包消息类 MyRedEnvelopeMessage


  • 最小堆类 MinHeap

    • add 方法 : 向最小堆中增加一个人及其权重
    • get & getDist 方法 : 从最小堆中取一个人并且获得其权重

修改:

  • 网络接口 Network

    • add_red_envelope_message : 增加红包消息
    • add_notice_message : 增加公告消息
    • clear_notices : 清除公告消息
    • add_emoji_message : 增加表情消息
    • store_emoji_id : 增加新的表情
    • query_popularity : 查询表情热度
    • delete_cold_emoji : 删除热度低的表情
    • query_money : 查询某人钱数
    • send_indirect_message : 发送间接消息

  • 网络类 MyNetwork & MyNetWork2

    MyNetwork2 类的建立纯属 MyNetWork 类超 500 行了……

    • emojiIdList : 存储表情的列表
    • emijiHeatList : 存储表情的热度
    • totalPath : 存储在计算最短路中已经求得最短路的结点
    • graph : 存储人与人之间关系及权重的图

  • 表情消息Id重复抽象类 & 表情消息Id重复类 EmojiIdNotFoundException & MyEmojiIdNotFoundException


  • 未找到表情消息Id抽象类 & 未找到表情消息Id类 EqualEmojiIdException & MyEqualEmojiIdException




关键算法

最短路径算法



基于度量的程序结构分析

  • 代码规模分析

  • 方法复杂度分析(部分)

  • 类复杂度分析(部分)



分析在本单元自测过程中如何利用JML规格来准备测试数据

  • 阅读 JML 规格代码,依据规格的不同边界条件特定的构造相应数据以验证正确性,并且进行覆盖测试以及随机测试来进一步确保我们程序的正确性;进一步可以构造数据以进行压力测试来确保我们代码的性能的完备


梳理本单元的架构设计,分析自己的图模型构建和维护策略

  • 架构设计(好像官方代码已经把架构定死了):每一个类都有对应的方法,对应问题中的一类操作

  • 图构建及维护策略:使用了邻接表来保存关系网中的图,使用了 Java 自带的 ArrayList 以及 HashMap 容器增加代码的可读性和维护性



按照作业分析代码实现出现的性能问题和修复情况

  • 第二次作业时,由于没有用图保存结点而是采用了遍历寻找节点的方式,导致在寻找最小生成树时运行时间超时,而后使用图存储结点并在图中寻找,修复了此问题


请针对下页ppt内容对Network进行扩展,并给出相应的JML规格

  • PPT 内容:

  • 假设出现了几种不同的 Person

    • Advertiser:持续向外发送产品广告
    • Producer:产品生产商,通过 Advertiser 来销售产品
    • Customer:消费者,会关注广告并选择和自己偏好匹配的产品来购买 -- 所谓购买,就是直接通过 Advertiser 给相应 Producer 发一个购买消息
    • Person:吃瓜群众,不发广告,不买东西,不卖东西
    • 如此 Network 可以支持市场营销,并能查询某种商品的销售额和销售路径等 请讨论如何对 Network 扩展,给出相关接口方法,并选择 3核心业务 功能的接口方法撰写 JML 规格(借鉴所总结的 JML 规格模式)
  • 生产产品:

  /*@ public normal_behavior
    @ requires !(\exists int i; 0 <= i && i < getPerson(personId).products.length; getPerson(personId).products[i].getId() == id);
    @ assignable getPerson(personId).products ;
    @ ensures (\forall int i; 0 <= i && i < \old(getPerson(personId).products.length) ;
    @          getPerson(personId).products[i].getId() == id );
    @ ensures getPerson(personId).products.length == \old(getPerson(personId).products.length) + 1 ;
    @ ensures getPerson(personId).hasProduct(id);
    @ also
    @ public exceptional_behavior
    @ signals (EqualAdvertiseIdException e) (\exists int i; 0 <= i && i < getPerson(personId).products.length;
    @                                     getPerson(personId).products[i].getId() == id) ;
    @*/

    public void addProduct(String personId, Advertisement id);
  • 购买
/*@ public normal_behavior
       @ requires (\exists int i; 0 <= i && i < advertisers.length;
       @ advertisers.get(i).equals(advertiser));
       @ ensures money == \old(money) - product.getValue();
       @ ensures production.length == \old(production).length + 1;
       @ ensures (\exists int i; 0 <= i && i < production.length;
       @ production.get(i).equals(product));
       @*/
     public /*@ pure @*/ void buy(Advertiser advertiser, Product product);
  • 给予生产建议
 /* @ public normal_behavior
    @ requires (\exists int i; 0 <= i && i < customers.length;
    @ customers.get(i).equals(customer));
    @ ensures customer.getAdvertisements.length ==
    @ \old(customer.getAdvertisements).length + 1;
    @ ensures (\exists int i; 0 <= i && i < customer.getAdvertisements.length
    @ customer.getAdvertisements.get(i).equals(advertisement));
    @*/
    public /*@ pure @*/ void sendAdvertisement(Customer customer, Advertisement advertisement);


本单元学习体会

  • 本单元学习了由契约式设计而延伸出来的 JML 代码,契约式设计是一种基于信任机制权利义务均衡机制的设计方法学, JML 源自于契约式设计的需要,并掌握了基于 JML 的规格模式及基于 JML 规格的测试与验证,受益匪浅

  • 由于本单元是根据 JML 代码规格而书写代码,所以并没有很好的锻炼我们的架构设计以及代码迭代设计的能力,只学会了如何阅读 JML 而不是如何书写 JML ,因此会觉得这个单元相较于两个单元学习的知识偏少,这是我觉得面向对象这个单元所缺失的地方



author: 20373864 谭立德

posted on 2022-06-06 13:23  master-Tan  阅读(25)  评论(0编辑  收藏  举报

导航