OO第四单元小结暨2019春季学期OO课程总结

目录:

  • OO第四单元总结

    • 一、总结本单元两次作业的架构设计

      • 第一次作业
      • 第二次作业
  • 学期最终总结
    • 二、四个单元中架构设计及OO方法理解

      • 2.1 第一单元作业
      • 2.2 第二单元作业
      • 2.3 第三单元作业
      • 2.4 第四单元作业
    • 三、四个单元中测试理解与实践的演进
    • 四、课程收获
    • 五、给课程组的建议
    • 六、总结致谢

一、总结本单元两次作业的架构设计

1.1 第一次作业

分析需求:需要实现的需求有,查询UML类图中模型中一共有多少个类、类中的操作有多少个、类中的属性有多少个、类有几个关联、类的关联的对端是哪些类、类的操作可见性、类的属性可见性、类的顶级父类、类实现的全部接口、类是否违背信息隐藏原则。

类图

基本想法:初始化遍历给定的UmlElement时,用HashMap进行存储,并且在初始化时实先class➡class,class➡interface,interface➡interface以及AssociationList的初始化,以方便后来使用。对于需要实现的方法,分为两类:一类是初始化MyUmlInteraction类已经存储好的结果,如类中的操作,直接查询HashMap;另一类方法均采用递归循环的模板,如类的顶级父类,用递归的思想重复调用自身,直到找到TopParent退出循环,详细代码如下:​

 
 1    public String getTopParentClass(String className)
 2             throws ClassNotFoundException, ClassDuplicatedException {
 3         checkClass(className);
 4         if (ansMap.containsKey(className)) {
 5             return ansMap.get(className);
 6         }
 7         UmlElement element = nameToClass.get(className);
 8         String re = className;
 9         while (true) {
10             if (!inheritClass.containsKey(element)) {
11                 re = element.getName();
12                 break;
13             }
14             if (!inheritClass.get(element).getElementType().
15                     equals(ElementType.UML_CLASS)) {
16                 re = element.getName();
17                 break;
18             }
19             element = inheritClass.get(element);
20         }
21         ansMap.put(className,re);
22         return ansMap.get(className);
23     }
24  

补充知识点:
  1. Java的类不采取多继承方式,但接口可以继承多个接口。类之间的单继承很好理解,是为了避免子类被引用的时候同一个方法无法判断应该使用哪个父类的方法;但是接口之间确实多继承的,因为接口下面的方法全部是抽象方法,没有任何的具体实现,即使继承的两个父接口包含同样的方法也没有任何影响。于是修改public List<String> getImplementInterfaceList(String className)函数如下:

  
 1   public List<String> getImplementInterfaceList(String className)
 2             throws ClassNotFoundException, ClassDuplicatedException {
 3         checkClass(className);
 4         UmlElement curInter = nameToClass.get(className);
 5         if (interMap.containsKey(className)) {
 6             return interMap.get(className);
 7         }
 8         ArrayList<String> result = new ArrayList<>(); //id
 9         //itself interface
10         if (curInter.getElementType().equals(ElementType.UML_INTERFACE)) {
11             ArrayList<String> result1 = new ArrayList<>(); //id
12             result1.add(curInter.getName());
13             return result1;
14         }
15         //interreals and father's
16         while (true) {
17             ArrayList<UmlElement> reals = classToInterReal.get(curInter);
18             for (UmlElement element : reals) {
19                 result.add(realToInter.get(element).getId());
20             }
21             if (!inheritClass.containsKey(curInter)) {
22                 break;
23             }
24             curInter = inheritClass.get(curInter);
25         }
26         //generalization
27         LinkedBlockingDeque<UmlElement> queue = new LinkedBlockingDeque<>();
28 ​
29         for (UmlElement element1:inheritInter.keySet()) {
30             HashSet<UmlElement> fathers = inheritInter.get(element1);
31             if (result.contains(element1.getId())) {
32                 queue.addAll(fathers);
33                 while (!queue.isEmpty()) {
34                     UmlElement element2 = queue.poll();
35                     if (!result.contains(element2.getId())) {
36                         result.add(element2.getId());
37                     }
38                     if (inheritInter.containsKey(element2)) {
39                         queue.addAll(inheritInter.get(element2)); }
40                 }
41             }
42         }
43         ArrayList<String> finalRe = new ArrayList<>();
44         for (String id :result) {
45             String tmp = idToElement.get(id).getName();
46             finalRe.add(tmp);
47         }
48         interMap.put(className,finalRe);
49         return finalRe;
50     }

1.2 第二次作业

分析需求:在第一次作业的基础上,多添加了UML顺序图、UML状态图。需要实现的新需求有给定状态机模型中一共有多少个状态等等,分为三个接口UmlClassModelInteractionUmlPreCheck`UmlCollabrationInteractionUmlStateChartInteraction

类图

基本想法:对于顺序图和状态图接口的处理,采取与第一次作业类似的方法,即初始化遍历给定的UmlElement时,用HashMap进行存储,并且在初始化时实现相应需求的存储。但存储方法有所改变,将需求边视为一个图加边存储。例如对于状态图,Transition即是state之间的边。那么例如寻找后继状态,即看两点可达与否即可,具体代码如下:

 1     public int getSubsequentStateCount(String stateMachineName,
 2                                        String stateName)
 3             throws StateMachineNotFoundException,
 4             StateMachineDuplicatedException,
 5             StateNotFoundException, StateDuplicatedException {
 6         checkMac(stateMachineName);
 7         checkState(stateMachineName, stateName);
 8         if (substateCountCache.get(stateMachineName).containsKey(stateName)) {
 9             return substateCountCache.get(stateMachineName).get(stateName);
10         }
11         UmlElement reg = macToRegion.get(nameToMac.get(stateMachineName));
12         UmlElement curState = nameToState.get(stateMachineName).get(stateName);
13 ​
14         ArrayList<String> result = new ArrayList<>();
15         HashMap<UmlElement,Boolean> visited = new HashMap<>();
16 ​
17         for (UmlElement ele:allState) {
18             visited.put(ele,false);
19         }
20         //dfs
21         LinkedBlockingDeque<UmlElement> queue = new LinkedBlockingDeque<>();
22         queue.add(curState);
23         int i = 0;
24         while (!queue.isEmpty()) {
25 ​
26             UmlElement element2 = queue.poll();
27             if (!result.contains(element2.getId()) && i != 0) {
28                 visited.put(element2,true);
29                 result.add(element2.getId());
30             }
31             if (stateTrans.containsKey(element2)) {
32                 for (UmlElement nextEle:stateTrans.get(element2)) {
33                     if (!visited.get(nextEle)) {
34                         queue.add(nextEle);
35                     }
36                 }
37             }
38             i++;
39         }
40         substateCountCache.get(stateMachineName).put(stateName,result.size());
41         return result.size();
42     }

本次作业中存在问题:

  1. UmlPrecheck中对于第二条规则的实现,在用DFS+染色方法寻找并打印环的时候,犯了一个低级的错误,取Arraylist的元素的时候忘记加index限制了。导致出错。这个错误应该是没有进行充分的测试导致的。


二、总结自己在四个单元中架构设计及OO方法理解的演进

2.1 第一单元

主题:正则表达式与多项式

这一单元主要围绕着这几个问题,正则表达式在JAVA中如何运用(并且注意避开stackoverflow)?JAVA中的封装、继承与多态?如何面对需求,剥离筛选出单一元素?

刚开始连JAVA编程都不熟悉,面对正则表达式确实有点懵。普通多项式的求导没有分离出多个类,直接按照C语言的面向过程的思想堆积到了一个java文件里,复用性与可扩展性都很差。第二次作业实现了三角函数类与多项式单项类,但对输入没有进行单独的处理;还有就是不正确性的判定,利用了长正则表达式,第三次作业完全没有办法使用。第三次作业难度陡然增大,于是新建了parser类,使用递归的思想,不断地对表达式进行剥离,并且在其中进行表达正确性的判断;当时没有好好理解继承的概念,也只抽取了几个基本元素的类,代码比较冗杂;另外,因为作业难度颇大,没有进行对于表达式的充分化简,只是求导出结果。

2.2 第二单元

主题:多线程与电梯

从单线程到多线程,多线程概念多而且难以理解,在上手打代码之前看了好几天的理论知识,也没太摸出头绪来。这一单元主要是有以下几点:

①.针对JAVA中多线程的使用,理解好经典的producer-consumer模式,其中线程安全与效率是最需要考虑的问题。关于线程安全,遇到的最多的问题是如何让线程正确停止执行。

②.观察者模式与工厂模式。观察者模式提供了一种对象设计,让主题和观察者之间耦合度降得很低,降低了需求与电梯之间的耦合关系。另外,第三次作业针对3部不同的电梯,可以进行注册再使用的方法。

第一次作业比较简单,因为单个电梯FCFS算法无需考虑效率问题,所以我只用了mainelevator两个线程,并且在后者内所有调用方法都加了synchronized前缀以保证线程安全。第二次作业我觉得应该是最难的,因为会涉及到线程安全的问题。好处在于实现了观察者模式,增加了调度池,避免了需求直接面向对象分配的尴尬场面。对于简单捎带的问题,我使用了mainelevatorschedulerrequestParser四个主要线程;在正确关闭elevator线程的问题上,我费了一些功夫,最后让三个线程共享一个reqList并在elevator中加入判断条件。如果第二次作业线程安全理解较为透彻,第三次作业其实大体框架并不难,尤其是对于我这种几乎没什么分配request调度的人(狗头)。对于电梯需求进行了朴素的拆分,然后查询与需求方向相同且可稍带的电梯,加入该电梯的等待序列。遗憾应该是没有实现很好的调度,并且没有通过Work Factory的方法对电梯进行注册,可复用性较差。

2.3 第三单元

主题:JML语言与地铁系统

相对于第二单元,这一单元就轻松了一点。这一单元的训练重点第一个是JML规格语言的理解,在此不赘述;另外,认为对于数据结构里图论的考察比较多?

前两次作业都比较简单,我也没有做太多的规格设计,只是单纯实现了需求接口;第三次作业复用代码时,才发现动不动就超过500行的checkstyle限制。并且对于最短路径直接套用dijstra算法,导致换乘出现问题。后来官方发布参考样例代码,才恍然大悟可以用工厂模式并且将图的算法提取成一个共通的计算类。对于图的拆点也觉得很巧妙,暴力选手留下了没好好学图论的泪水。

2.4 第四单元

主题:UML图

在代码架构上,私以为难度并不大。但是关于UML类图/状态图/顺序图的理解,starUML中的细节,JAVA中的继承实现机制等等细节问题要求较多。两次作业都比较简单,并且代码复用性也较好。


三、总结自己在四个单元中测试理解与实践的演进

前两个单元主要采取1/2的方式,通过大量的数据来发现bug。虽然可以测试出bug,但是不得不说对自己的程序却不适用,每次发现输出错误从头溯源debug的方式效率极低,这时候就引进了JUnit的测试方法。

测试方法1:构造边界测试样例并且实现对拍器

根据要求,自己脑洞构造边界测试样例然后肉眼debug,然后对拍就可以了。示例代码如下:

set addr="C:\Users\maltose\Desktop\result"
​
if not exist %addr% (md %addr%
)
​
for /l %%i in (1,1,1000) do (cd %addr%%build% >data_%%i.txt%correct% <data_%%i.txt >correct_%%i.txt%test1% <data_%%i.txt >test1_%%i.txt
fc test1_%%i.txt correct_%%i.txt >nul && echo >nul  || echo 1 not same %%i
​
%test2% <data_%%i.txt >test2_%%i.txt
fc test2_%%i.txt correct_%%i.txt >nul && echo >nul  || echo 2 not same %%i
​
%test3% <data_%%i.txt >test3_%%i.txt
fc test3_%%i.txt correct_%%i.txt >nul && echo >nul  || echo 3 not same %%i
​
%test4% <data_%%i.txt >test4_%%i.txt
fc test4_%%i.txt correct_%%i.txt >nul && echo >nul  || echo 4 not same %%i
​
%test5% <data_%%i.txt >test5_%%i.txt
fc test5_%%i.txt correct_%%i.txt >nul && echo >nul  || echo 5 not same %%i
​
%test6% <data_%%i.txt >test6_%%i.txt
fc test6_%%i.txt correct_%%i.txt >nul && echo >nul  || echo 6 not same %%i
​
%test7% <data_%%i.txt >test7_%%i.txt
fc test7_%%i.txt correct_%%i.txt >nul && echo >nul  || echo 7 not same %%i
​
%test8% <data_%%i.txt >test8_%%i.txt
fc test8_%%i.txt correct_%%i.txt >nul && echo >nul  || echo 8 not same %%i
​
%test9% <data_%%i.txt >test9_%%i.txt
fc test9_%%i.txt correct_%%i.txt >nul && echo >nul  || echo 9 not same %%i
​
set /a j=%%i%%10
if !j! equ 0 (echo %%i th
)

测试方法2:自动生成测试数据

限于水平,第一单元没有实现过多项式的自动生成测试用例。但第二单元的电梯测试样例比较好生成。

测试方法3:使用JUnit进行测试 & 结合Assert方法

Junit测试虽然相较于测试方法1&2结合繁琐了那么一丢丢,在互测范围内实用性也不太高。但是对于自己的程序来说,好就好在能够精确定位bug。对不同模块构造测试样例,然后用java自带的API中assert方法,能够精确定位,这样确实比一步步调试要方便的多。


四、总结自己的课程收获

一学期下来,这门课程算是我学习的最艰难也最痛苦的一门课程了。虽然水平有限,但收获还是有的。从刚开始连JAVA语言都不熟悉,上来就开始写代码;到现在会考虑层层剥离元素,并且能够抽象出来元素,对几个OO原则也进行了一定的实践。课程过程中也发现,自己的数据结构基础确实薄弱,跟上进度很吃力。

前几周因为一些个人心理上的原因,没有及时跟上进度。后来也因为这件事情有点反复情绪,努力了没有收获想要的结果会让人有些头痛。但关键时刻,荣老师也给了我很大的帮助,还有我身边的几个同学。刚开始设计阶段真的很难,我有很多问题,他们都耐心地给予了一一的解答。遗憾肯定会有,而且很多,但我没有什么后悔的,觉得我在我个人和环境的条件限制做到了我能做的吧。

这学期最大的收获,是让我见识到了面向对象程序设计思维与架构设计的重要性。很多时候写不出来代码、存在需要修改大面积代码的bug,都不是因为具体实现的问题(通常只有几行),肯定是一开始你的设计就出了问题。就像人的组成一样,算法就像你的肉,而架构设计就是骨骼;如果没有一个结实而端正的骨骼撑起来,肉再健美也没有用。在我的经历中,一旦有了整体的框架,实现其实很快。还有一个比较私人的收获就是有点偏向生活吧,时间安排是一个人自律的重要表现吧,每次在DDL前拼死冲刺挺难过的。


五、立足于自己的体会给课程提三个具体改进

建议1:建议课程组先对课程时间安排进行调研,然后安排作业-互测时间

这学期OO和OS都集中在了周末,开始觉得时间有点紧;后来有一次调整到了周日开始,就觉得两门课时间有所错开了,时间也要有所宽裕。但是理论课的时间又不能变,导致一些很矛盾的结果。建议课程正式开始之前对学生的专业课时间安排进行了解,然后有可能申请教务排课之前就做出更为合理的时间安排?

建议2:适当降低单元中作业难度跨度/调整分配时间

每个单元的作业都是第三次作业与前两次作业难度跨度相当之大,但是通常又是一样的截止日期。如果下一次作业特别难,可以考虑把其中难以突破的重点提前预告,让学生有个准备与提前思考。

建议3:希望继续提供示例/优秀代码样例,供同学们交流参考

个人觉得这是个很好的方法。自己闭门造车越造越自闭,需要适当的交流与学习。阅读别人的代码,无论是架构上的启发,还时只是一点点实现上的小tips,我觉得收获都很大。


六、总结致谢

在此谢谢表示这一个学期以来所有老师和助教学长学姐的付出,大家都辛苦了。

尤其感谢:荣老师对我的帮助,还有我身边的小伙伴的帮助,不一一举例了。一分耕耘一分收获吧。

转载于:https://www.cnblogs.com/maltose/p/11077916.html

OO第四单元小结暨2019春季学期OO课程总结相关推荐

  1. 【OO学习】OO第四单元作业总结及OO课程总结

    [OO学习]OO第四单元作业总结及OO课程总结 第四单元作业架构设计 第十三次作业 第十四次作业 总结 这两次作业架构思路上是一样的. 通过将需要使用的UmlElement,封装成Element的子类 ...

  2. 2019春季学期期末总结

    2019春季学期期末总结作业 一.我学到的内容 二.我的收获 作业连接 收获 第二周作业 文件的建立 第三周作业 二维数组 第四周作业 选择排序法 第五周作业 字符串数组 第六周作业 指针 第七周作业 ...

  3. 2019春季学期第四周作业

    2019春季学期第四周作业 这个作业属于那个课程 C语言程序设计Ⅰ 这次作业要求在哪里 2019春季学期第四周作业 我在这个课程的目标是 我希望能够更加掌握循环和排序 参考文献 无 选择法排序 本题要 ...

  4. 2019年北航OO第四单元(UML任务)及学期总结

    第四单元两次作业总结 第十三次作业 需求分析 本次作业需要完成一个UML类图解析器,所需要解析的只有符合UML标准和能够在Java 8中复现的UML类图.查询指令存在两种:仅与所查对象有关的指令,以及 ...

  5. OO第四单元——UML及其解析器——总结 暨 OO课程大总结

    第四单元总结 第四单元主要内容是写代码解析UML,因此需要理解UML UML相关 starUML的储存方式是一个.mdj文件,通过使用文本编辑器观察这个文件,我们可以看出这是一个json格式储存的文件 ...

  6. OO第四单元作业小结

    一.本单元两次作业的架构设计 1.第一次作业 整体思路:以class为核心,建立MyInterface.MyAttribute.MyOperation.MyAssociation四个类分别储存每个类的 ...

  7. 面向对象第四单元小结

    面向对象第四单元:UML类图.顺序图.状态图 一.架构设计 第一次作业      第四单元第一次作业,需要完成的任务为实现一个UML类图解析器UmlInteraction,学习目标为UML入门级的理解 ...

  8. OO第四单元博客作业

    一.UML作业架构设计 1.第一次作业 其中 Main 是入口类,MyUmlinteraction实现了接口,UmlInteractionBase为MyUmlinteraction实现提供了底层功能, ...

  9. 第四单元作业——UML分析总结学期总结

    本单元主要学习关于Unified Modeling Language (UML)的设计与分析的内容,重点对UML中的类图.顺序图和状态图的表达方式和有效性进行了分析. UML与上个单元学习的JML同样 ...

最新文章

  1. 线性表的表示和实现方式之链式表示和实现
  2. calender获取本月最后一天的日期_怕忘记2020法考重点日期?这份法考日历为你护航,信息量巨大...
  3. iOS开发UI基础—手写控件,frame,center和bounds属性
  4. 多个项目怎么配置到服务器上,多个项目怎么配置到服务器
  5. 解决 GraphQL 的限流难题
  6. 使用函数实现数据大小端转换
  7. WP8.1学习系列(第九章)——透视Pivot开发指南
  8. 四种launchMode启动方式
  9. ToolStripStatusRollingLabel——滚动显示状态栏标签
  10. 更改swing应用程序标题栏默认图标
  11. 计算机应用技术头像,意大利科学家应用计算机技术进行头像复原
  12. 服务器设置来电自动重启,电脑来电自动重启怎么样设置
  13. 使用Docker发布DNC项目
  14. 计算机应用基础模拟三答案,《计算机应用基础》模拟试卷三(含答案)
  15. 四轴平面机器人的手眼标定
  16. Bootstrap 排版缩写词
  17. iap进入app后 按复位按钮进入iap无法再进app问题
  18. java刷题--518零钱兑换II
  19. nvr linux 软件,Linux系统下运行RTSP协议安防视频平台EasyNVR出现安装服务错误,如何解决?...
  20. LeetCode1166.设计文件系统

热门文章

  1. linux微软雅黑字体库_linux 使用微软雅黑字体
  2. NLP(七):前馈神经网络基础回顾(NN模型及其正则化,dropout,各种梯度求解算法等模型优化策略)
  3. P4766 [CERC2014]Outer space invaders(区间dp)
  4. gb和gib的区别_GB 和 GiB 的区别
  5. code-push常用命令
  6. DHT11 数字温湿度传感器实验
  7. 【Axure高保真原型】移动端钱包原型模板
  8. 【论文笔记】面向智能假肢手臂的生机接口系统与类神经协同控制
  9. 计算机水平用什么形容词形容,形容应用价值的词语有哪些 , 形容价值的成语有哪些...
  10. 爬虫日记(28):scrapy使用中间件调用浏览器