欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SC_lab3 复用。。。

程序员文章站 2022-03-10 14:53:50
...

Lab 3实验报告

1 实验目标概述
本次实验覆盖课程第 3、5、6 章的内容,目标是编写具有可复用性和可维护 性的软件,主要使用以下软件构造技术:
子类型、泛型、多态、重写、重载
继承、代理、组合 常见的 OO 设计模式
语法驱动的编程、正则表达式 基于状态的编程
API 设计、API 复用 本次实验给定了五个具体应用(径赛方案编排、太阳系行星模拟、原子结构
可视化、个人移动 App 生态系统、个人社交系统),学生不是直接针对五个应用
分别编程实现,而是通过 ADT 和泛型等抽象技术,开发一套可复用的 ADT 及其 实现,充分考虑这些应用之间的相似性和差异性,使 ADT 有更大程度的复用(可 复用性)和更容易面向各种变化(可维护性)
2 实验环境配置
通过实验手册所给的url建立github的实验三的仓库,然后通过git将本地仓库与github上的远程仓库连接,配置完成;

3 实验过程
请仔细对照实验手册,针对每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
3.1 待开发的三个应用场景
首先请列出你要完成的具体应用场景(至少3个,1和2中选一,3必选,4和5中选一,鼓励完成更多的应用场景)。
 TrackGame
 AtomStructure
 SocialNetworkCircle
分析你所选定的多个应用场景的异同,理解需求:它们在哪些方面有共性、哪些方面有差异。

共性:全部是多轨道系统,其中trackgame没有中心物体,但可以把比赛种类抽象为一个中心物体。这样就可以把三个应用全部视为有中心物体的轨道系统。
则可以设计统一的接口和抽象类。根据应用的开发要求,三者的增删轨道,增删轨道物体,也具有相同性,所以这部分的gui具有共性。
差异:轨道物体和中心物体的具体属性不太相同,但不是太大的问题。针对每个应用,又多出一些特殊的操作,所以对接口的实现类,要在分为三个具体的实现类。同时,在可视化和设计gui时,三个应用也有很大的不同,这部分也要分开写。此外,api部分,只又部分的应用会用到api的功能。所以也需要特殊对待。
3.2 基于语法的图数据输入

  1. TrackGame部分的正则表达式输入
    String athletepattern = “^Athlete\s*::=\s*<\s*[A-Za-z]+\s*,\s*[0-9]{1,3}\s*,\s*[A-Z]{3}\s*,\s*[0-9]{1,2}\s*,\s*[0-9]{1,2}\.\d{2}\s*>”;
    String gamepattern = “^Game\s*::=\s*[0-9]{3}”;
    String numpattern="^NumOfTracks\s*::=\s*[0-9]{1,2}";

  2. AtomStructure部分的正则表达式输入
    String elementpattern = “^ElementName\s*::=\s*[A-Z]{1}[a-z]?”;
    String numpattern="^NumberOfTracks\s*::=\s*[0-9]{1,2}";
    String electronpattern="^NumberOfElectron\s*::=\s*(\s*[0-9]/[0-9]+\s*;)+\s*[0-9]/[0-9]+";

3. SocialNetworkCircle部分的正则表达式输入
String centraluserpattern = “^CentralUser\s*::=\s*<\s*[a-zA-Z0-9]+\s*,\s*[0-9]{1,3}\s*,\s*(F|M)\s*>”;
String friendpattern="^Friend\s*::=\s*<\s*[a-zA-Z0-9]+\s*,\s*[0-9]{1,3}\s*,\s*(F|M)\s*>";
String tiepattern="^SocialTie\s*::=\s*<\s*[a-zA-Z0-9]+\s*,\s*[a-zA-Z0-9]+\s*,\s*(1|0).?[0-9]{0,3}\s*>";

3.3 面向复用的设计:CircularOrbit<L,E>
3.3.1 接口CircularOrbit<L,E>
为三个轨道系统设计的统一的接口,具体方法如下

  1. public boolean addTheCenter(L theCenter);
    添加轨道系统的中心物体
  2. public boolean addTheTrack(Track theTrack);
    为轨道系统添加轨道
  3. public boolean addThePoint(E point);
    添加轨道物体
  4. public boolean setRelation(E obj1, E obj2,double tie);
    设置添加两个轨道物体之间的关系
  5. public boolean setCenterRelation(L theCenter, E point,double tie);
    设置添加中心物体额轨道物体的关系
  6. public boolean setTrackandPhy(Track track,E point);
    将轨道物体加入到轨指定轨道上去,形成(轨道,该轨道上所有轨道物体的集合)这种形式的集合。
  7. public double getObjectDistributionEntropy();
    计算该系统的熵值,将api中的方法移动到这里,更加方便计算。
  8. public Set<Relation<E, E>> getErela();
    get方法,返回所有轨道物体之间关系的集合。
  9. public Set<Relation<L, E>> getCrela();
    get方法,返回所有中心物体与轨道物体的关系的集合。
  10. public Set getPhy();
    get方法,返回所有轨道物体的集合。
  11. public Map<Track, Set> getTrack();
    get方法,返回 轨道和该轨道上的物体 的map类型集合
  12. public L getCenter();
    get方法,返回轨道系统的中心物体。
  13. public boolean removePhy(E e);
    删除制定的轨道物体,删除的意义包含:轨道上的该物体,轨道物体总集合中的该物体,该轨道物体和其他物体包括轨道物体与中心物体的所有关系。
  14. public boolean removeTrack(Track t);
    删除指定的轨道。其意义包含:删除改革轨道,删除该轨道上的所有物体 和 这些物体所具有的和其它物体的关系
  15. public boolean removeRelation(E point);
    删除中心物体和指定轨道物体的关系。

3.3.2 实现类ConcreteCircularOrbit<L,E>
该类是implements的CircularOrbit<L,E> 类。
方法上一部分已经介绍了。
区别是,实现抽象方法时,添加了5个域。

  1. private Set thePhysical=new HashSet();
    用来保存所有的轨道物体,没有进行轨道区分,方便便利查询。
  2. private Map<Track,Set> theTracks=new HashMap<Track, Set>();
    用来保存轨道,和在相应轨道上的轨道物体。
  3. privateSet<Relation<L,E>>theCenRelations=newHashSet<Relation<L,E>>();
    用来保存所有中心物体和轨道物体的关系。
  4. privateSet<Relation<E,E>>thePhyRelations=newHashSet<Relation<E,E>>();
    用来保存所有轨道物体之间的关系。
  5. private L theCenter=null;
    中心物体。

3.4 面向复用的设计:Track
针对 三个轨道系统,全部抽象为带个逻辑半径的物体。所以track类三者通用。只需添加radius域,还有get方法即可。针对实际应用情景,又添加了一个改动逻辑半径的方法。此方法便于在删除轨道操作时,实时完成对其他轨道逻辑半径的影响。例如,删除了2号轨道,那么3号轨道就变成了2号,之后以此类推,方便可视化绘图。
3.5 面向复用的设计:L
中心物体L,设计为了抽象类CentralObject,同时设置域nameString作为中心物体的名称(不一定用得到)。 设置了构造方法,和域的get方法(进行了防御性拷贝)。最后设置了重写equals的抽象类,便于之后的比较。接下来是实现类。

  1. Game
    作为trackgame的中心物体存在,虽然trackgame理论上没有中心物体,但我抽象出了这个东西作为中心物体存在,其记录的时比赛类型,即100,200,400米比赛。所以域为int stytle。同时创建了构造方法,get方法,重写了equals方法。
  2. Element
    作为atomstructure的中心物体。完全继承了central object,无需再添加其他的域。继承构造方法,重写equals方法就完事了。
  3. CentralUser
    作为Social Network Circle的中心物体(其实和轨道物体属性完全相同,我也很想直接不写它了,但如果这样,就没有抽象类存在的必要了)。域:int age,string sex,int mk=0;分别作为年龄,性别,和潜在的编号,方便后来的求取逻辑距离。然后写了构造方法,相应的get方法。
    3.6 面向复用的设计:PhysicalObject
    恕我直言,我所选取的三个轨道系统的轨道物体,实在没啥共性可言(我硬是写成了抽象类)。域设置为num,表示该物体存在的数量。这个域在赛跑和社交圈里是没有用的,但是可以在电子系统中用到。然后创建了构造方法,和equals重写的抽象方法。以下是继承实现类。
  4. Athlete
    按照要求设置了姓名,编号,国家,年龄,最佳成绩的域。设置了相应的get方法,同时重写了equals方法。
  5. Electron
    按照手册的要求,同轨道上的电子是没有任何区别的,所以一个轨道上只需存在一个电子,而这个电子记录了在这条轨道上有多少个相同的电子即可。所以抽象类中设置的num就用到了。
  6. Friend
    按照要求设置了和CentralUser一样的域,但便于绘图,又加入了坐标域。提供了相应的get方法,重写了equals方法。
    3.7 可复用API设计
    所选取的三个轨道系统,只有社交关系圈的物体之间会有联系,所以获取逻辑距离和物理距离的api只针对了社交关系圈系统。逻辑距离和物理距离的求取全部采用了dijkstra算法。由于写的比较粗糙,运行时会非常慢。
    获取系统熵值的api则是直接在系统里实现了,比在这里实现要简单好多啊。
    针对getDifference,设计了Difference类,域为两个string类型的arraylist,用来记录两个轨道系统各自的特殊之处。然后重写了toString方法,便于打印阅读。 而对getDifference的实现则是相当简单,两个轨道系统取出对应的轨道,一条轨道一条轨道的进行比较。
    3.8 图的可视化:第三方API的复用
    可视化主要用到了JFrame,JPanel,JTextField,JTextArea等API(貌似都是jdk自带的api),方法也很重复,jframe来构建窗口,重写jpanel的paint方法来进行画图。由于三个应用所要绘制的的轨道不太相同,所以写了三个helper方法(不要怪我,我真的不知道这三个怎么公用一个visualize)。除了社交关系圈的轨道物体采用了随机轨道位置,其它皆是均分。
    3.9 设计模式应用
  7. 采用抽象工厂方法,用工厂的静态方法来实例化相应的对象。比如在中心物体和轨道物体的创建上。
  8. 同上。
  9. 随机遍历,按照轨道的逻辑半径从小到大。
  10. 将所有方法放进一个方法中,调用api时挨个输出结果。
  11. 随机排序,顺序排序,并在窗口上打印出排完序的结果。
    3.10 应用设计与开发
    显示一个总的功能选择窗口

3.10.1 TrackGame
点击trackgame后,首先选择要输入的文件

,然后就会显示比赛图

还有功能选择窗口

选择排序的话就会显示排序结果。

在右侧提供了交换选手的功能选择。

3.10.2 AtomStructure
点击后和上面的一样,输入文件窗口
然后显示轨道图和功能选择

3.10.3 SocialNetworkCircle
社交网络相同,这里就放一下成果图就ok了

不同的是,电子系统的电子分布是均匀的,而社交关系圈上的朋友则是在该轨道上的位置随机的。
3.11 应对应用面临的新变化
以下各小节,只需保留和完成你所选定的应用即可。
3.11.1 TrackGame
在图像上每条轨道显示了四个运动员,排序列表也增加了每条赛道上的运动员情况。就不再放图了。

3.11.2 AtomStructure
直接重建了element类,增加了质子和中子数。
3.11.3 SocialNetworkCircle
(我一开始建立的就是单向关系)。所以针对反向的输入直接就忽视了。
(此外,medium规模的文件,有好几个tie=0的关系)。
3.12 Git仓库结构
请在完成全部实验要求之后,利用Git log指令或Git图形化客户端或GitHub上项目仓库的Insight页面,给出你的仓库到目前为止的Object Graph,尤其是区分清楚312change分支和master分支所指向的位置。

4 实验进度记录
请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。
每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。
不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。
日期 时间段 计划任务 实际完成情况
5.2 整天 能写多少是多少 还ok
5.3 整天 能写多少是多少 Ok
5.4 整天 完成部分可视化 完成
5.5 整天 完成剩下部分,spec,test,ri,af等 完成
5.6 3.00pm-6.00pm 写完报告 完成
5 实验过程中遇到的困难与解决途径
遇到的难点 解决途径
可视化完全不会

上csdn学习,慢慢摸索,然后学会了

泛型的传递问题

直接写三个方法就不用考虑这个了

命令行输入和可视化界面冲突,必须关闭一个另一个才能用

把命令行输入的功能写成按钮,加入到可视化界面中就OK了

6 实验过程中收获的经验、教训、感想
6.1 实验过程中收获的经验和教训
合理规划实验的时间,这个51假期,就51当天玩了一天(而且还是内心比较忐忑的完),其他时间全部在写实验,除了吃饭和上厕所就没出过宿舍。还有就是设计模式用的特别生疏,甚至不知道该怎么用,导致程序的总体结构比较乱。可视化真的有趣,这是我上这门课感到真正有趣的地方了(果然我想去搞第九艺术)。总之学习到了非常多的操作,希望降低下实验难度和任务量。
6.2 针对以下方面的感受
(1) 重新思考Lab2中的问题:面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?本实验设计的ADT在五个不同的应用场景下使用,你是否体会到复用的好处?
Adt的话只需要考略所要求的功能与需求,但是面向具体场景的话,就要自己去提炼出场景的共性来设计一套adt。说实话,这次试验我没怎么感受到复用的好处,看似都是轨道系统,其实差距挺大的,很多时候adt里的方法都是为某一特定的场景设计的,这种方法没有复用可言。
(2) 重新思考Lab2中的问题:为ADT撰写复杂的specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?你是否愿意在以后的编程中坚持这么做?
维护程序的安全性,你总不能希望自己的程序很简单就被别人给黑了吧。其实我还是愿意这么做的,但是能不能有一些af,ri的标准例子,每次写的都云里雾里的,可能是我没好好听课而且太菜了吧,
(3) 之前你将别人提供的API用于自己的程序开发中,本次实验你尝试着开发给别人使用的API,是否能够体会到其中的难处和乐趣?
没体会到乐趣,倒是感觉到了很多难处,特别是泛型的处理,这个我是不会,所以api写的特别冗余,网上查到的方法一大长串,看的有点懵,就没有用。
(4) 在编程中使用设计模式,增加了很多类,但在复用和可维护性方面带来了收益。你如何看待设计模式?
肯定是好的,但是我不太会用。还需要更加认真的去学习啊,必可活用于下一次。
(5) 你之前在使用其他软件时,应该体会过输入各种命令向系统发出指令。本次实验你开发了一个解析器,使用语法和正则表达式去解析输入文件并据此构造对象。你对语法驱动编程有何感受?
挺麻烦的,但是用起来很高效,而且感觉整个层面都上升了。但是一些时候要考虑的情况特别多,正则表达式会写的很长。匹配了后还要进行额外的处理,也挺麻烦的。
(6) Lab1和Lab2的大部分工作都不是从0开始,而是基于他人给出的设计方案和初始代码。本次实验是你完全从0开始进行ADT的设计并用OOP实现,经过三周之后,你感觉“设计ADT”的难度主要体现在哪些地方?你是如何克服的?
共性的提取。克服的方法…硬上。
(7) 你在完成本实验时,是否有参考Lab4和Lab5的实验手册?若有,你如何在本次实验中同时去考虑后续两个实验的要求的?
没有。
(8) 关于本实验的工作量、难度、deadline。
工作量太大了,难度适中(对比工作量,我感觉不时进行acm式的作业更有趣些),deadline幸好延后了一周,要不然就和考试撞了。所以我是希望避开考试,往后顺延的。
(9) 到目前为止你对《软件构造》课程的评价。
好难,感觉比csapp还难啊。学到的东西还是特别多的,不合理的地方我也没有太在意,希望以后多多改善吧。

相关标签: 软件构造