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

作业一、UML类图查询

1. 统计信息图

2. 复杂度分析

基本复杂度(Essential Complexity (ev(G))、模块设计复杂度(Module Design Complexity (iv(G)))、Cyclomatic Complexity (v(G))圈复杂度

OCavg为平均循环复杂度;WMC为总循环复杂度

3. 结构信息图

4. 分析架构设计

本次没有架构设计,本次只用了两个类,一个main类,用于启动,一个MyUmlInteraction类,实现了UmlInteraction接口,在MyUmlInteraction类的内部实现所有的方法。这种架构设计的实现很简单,但是会使整个类的复杂度升高,不易于debug和扩展(比如写完成品后我类的长度达到了480+行,十分接近500行的上限了)。

作业二、UML类图、状态图、顺序图查询

1. 统计信息图

2. 复杂度分析

基本复杂度(Essential Complexity (ev(G))、模块设计复杂度(Module Design Complexity (iv(G)))、Cyclomatic Complexity (v(G))圈复杂度

OCavg为平均循环复杂度;WMC为总循环复杂度

3. 结构信息图

4. 分析架构设计

本次作业使用了6个类,一个main类,用于启动,一个MyUmlGeneraIInteraction类,实现了UmlGeneraIInteraction接口。MyUmlGeneraIInteraction类内含有四个类,MyStateChart类(实现状态图的查询指令),MyStandardPreCheck类(实现后两个检查指令),MyCollaboration类(实现顺序图的查询指令),MyClassModel类(实现类图的查询指令,以及第一个检查指令)。

四个类其实分别对应UmlGeneraIInteraction接口实现的四个接口,分别实现对应接口内的方法,进行架构的简单解耦。解耦的效果不错,debug和扩充的体验都不错。

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

1.第一单元——面向过程

第一单元的架构设计还没有摆脱面向过程的思想,次次作业重构程序,之前的程序能用到的只有部分思路以及极小部分代码。可扩充性差,维护性差。

不过在这个过程中,逐渐了解了什么是面向对象,什么是继承,什么是接口,什么是抽象类,什么是包等等一系列将要用到的东西。

 

在第三次作业(上图)中,建立了一个自我感觉良好的架构,将因子和嵌套方式单独建包以及抽象类,一切看起来井井有条。但实际上面向对象只是形象工程,骨子里还是面向过程,请看以下代码:

             if (matcherNum.matches()) {
stringBuilder.append("0");
} else if (matcherPowerFunc.matches()) {
FactorX factorX = new FactorX(addList.get(i));
stringBuilder.append(factorX.derivation());
} else if (matcherTriFunc.matches()) {
FactorTri factorTri = new FactorTri(addList.get(i));
stringBuilder.append(factorTri.derivation());
} else {
ItemMultiIply itemMultiIply =
new ItemMultiIply(addList.get(i), depth + 1);
stringBuilder.append(itemMultiIply.derivation());
}

建立了Factor抽象类,但是重来没有使用过抽象类的真正功能,调用时还是if ...(FactorX) else ....(FactorTri),没有领会到面向对象的精髓——多态是如何使用的。

2.第二单元——多线程与SOLID分析

在第二单元里,我知道了多线程程序的实现方法。并且在第一次作业时,将解耦进行到底,Elevator类中的方法极力拆分,使模块化方法与功能一一对应,为第二次作业打下了良好的基础。

下面左图是第一次作业的架构信息图,右图是第二次作业的架构信息图。不难发现,两者之间的区别只有Elevator类中多了一个方法,Scheduler类中多了两个方法。扩充性很好,第二次作业写的非常舒服。

  

但问题出在了第二次作业,没有考虑到多电梯实现时的调度问题,将一部分Schedule类的工作放在了Elevator类中(sort方法),导致第三次作业解耦困难,并且还出现了不少bug。

下图是第三次作业中最不应该出现的程序代码,这个非常复杂且诡异的代码(另外加上两个类的多个方法),只是为了解决什么时候停止运行这个比较简单的问题,然而最后恰恰出错在了此处。我觉得跟该处代码的复杂度高,逻辑混乱有很大的关系。

                 if (order.get(0).get(1) == 0) {
if (order.size() == 1) {
order.remove(0);
boolean end = false;
empty.setEmpty(name);
while (true) {
if (empty.isEmpty() & (elevScheduler.Num() == 0)) {
if (!closeDoor) {
close();
}
end = true;
break;
}
if (elevScheduler.Num() != 0) {
ArrayList<ArrayList<Integer>> integer
= elevScheduler.pop();
if (integer.get(0).get(1) == 0) {
sleep(100);
continue;
}
order.addAll(integer);
empty.setFull(name);
break;
}
sleep(100);
}
if (end) {
break;
}
}

3.第三单元——继承与接口

这一单元里我使用了不少继承和接口实现,优点在于学会了分离一部分有联系的核心代码到单独的类里(比如都是与图相关算法的代码),并支持传入数据的类型多样(实现了多态),即同一个图的方法可以对不同储存结构的图使用。

 void floyd(HashMap<Integer, HashMap<Integer, Integer>> dist) {
for (Integer integerA : dist.keySet()) {
for (Integer integerB : dist.keySet()) {
if (!dist.get(integerA).containsKey(integerB)) {
continue;
}
for (Integer integerC : dist.keySet()) {
if (dist.get(integerA).containsKey(integerC)) {
Integer tmp = dist.get(integerA).get(integerC) +
dist.get(integerA).get(integerB);
if (!dist.get(integerC).containsKey(integerB) ||
tmp < dist.get(integerC).get(integerB)) {
HashMap<Integer, Integer> has1 = dist.get(integerC);
has1.put(integerB, tmp);
dist.put(integerC, has1);
HashMap<Integer, Integer> has2 = dist.get(integerB);
has2.put(integerC, tmp);
dist.put(integerB, has2);
}
}
}
}
}
}
      void addEdge(Integer nodeA, Integer nodeB, int weight,
HashMap<Integer, HashMap<Integer, Integer>> init) {
HashMap<Integer, Integer> tmpA = new HashMap<>();
HashMap<Integer, Integer> tmpB = new HashMap<>();
if (init.containsKey(nodeA)) {
tmpA = init.get(nodeA);
}
if (init.containsKey(nodeB)) {
tmpB = init.get(nodeB);
}
if (nodeA.equals(nodeB)) {
tmpA.put(nodeB, 0);
} else {
tmpA.put(nodeB, weight);
tmpB.put(nodeA, weight);
}
init.put(nodeB, tmpB);
init.put(nodeA, tmpA);
}

缺点在于,没有用继承的方式将三次作业的内容结合起来,而是采用最简单的复制粘贴的方法。实在是太懒了。

4.第四单元——伪面向对象

第四单元,也是OO课的收官单元,虽然难度不大,但是具有很多面向对象的特征。因为是实现一个接口,所以这使得我在完成作业的时候,也采用面向对象的思维思考程序的架构设计,对于类似的查询指令,建立统一模型,采用一样的思路执行。不过遗憾的是,程序完成过程中,出于懒的想法,还是以代码复制的形式实现了统一建模,没有使用统一方法。

     private void updateAttriResult(String classId) {
if (generMap.containsKey(classId) && !attriResult.containsKey(
generMap.get(classId).get(0).getTarget())) {
updateAttriResult(generMap.get(classId).get(0).getTarget());
}
if (!attriMap.containsKey(classId)) {
attriMap.put(classId, new HashMap<>());
}
if (!generMap.containsKey(classId)) {
attriResult.put(classId, attriMap.get(classId).size());
} else {
attriResult.put(classId, attriMap.get(classId).size() +
attriResult.get(generMap.get(classId).get(0).getTarget()));
}
}
     private void updateAssocResult(String classId) {
if (generMap.containsKey(classId) && !assocResult.containsKey(
generMap.get(classId).get(0).getTarget())) {
updateAssocResult(generMap.get(classId).get(0).getTarget());
}
if (!asEndMap.containsKey(classId)) {
asEndMap.put(classId, new HashMap<>());
}
if (!generMap.containsKey(classId)) {
assocResult.put(classId, asEndMap.get(classId).size());
} else {
assocResult.put(classId, asEndMap.get(classId).size() +
assocResult.get(generMap.get(classId).get(0).getTarget()));
}
}

在第二次作业里,我采用建立四个类,分别对应UmlGeneraIInteraction接口实现的四个接口,分别实现对应接口内的方法,进行架构的简单解耦,收效不错。

5. 总结

其实总的来看四个单元,面向对象的思维不一定是一直增加的,应该是螺旋式上升的,中间也会遇到误区,重新回到老路子上。不过整体来讲,现在对面向对象的思维和架构设计理念有了一定的了解,同时体会到了面向对象思维的优势强大。

三、四个单元中测试理解与实践的演进

1.第一单元——刀耕火种

一开始接触到OO,是一脸懵B的,咱什么都不知道,也不敢问

回顾一下我在第一单元总结时写的测试分析,当时是多么渴望一个评测机啊~

初期的评测全程手动,一行行阅读别人的代码,仔细思考逻辑关系,试图发现漏洞,当时简陋的条件下,硬是靠着眼力,看出了不少bug,虽然方法粗糙,但是这种方法是白盒测试,我清楚的知道他为什么出错,甚至知道怎么改正这个错误,对bug出现的方式以及易错点有了更多的了解。(后期测评机上线后就是“床上一躺,电脑一响”)

2.第二单元——初识评测机

回顾一下我在第二单元总结时写的测试分析,明显看出评测机的效率惊人,虽然没能测出自己的bug(因为生成数据不够全面),但对于互测来讲,简直是天降神兵。

错误原因我是单独看错误输出和大致的程序思路,总结出来的。(也算是没有完全的黑盒测试)

3.第三单元——加强评测机

在经历了第二单元的测评机数据生成不够强的问题后,我们每次同时有多个同学并行写数据生成的程序,扩大覆盖面。并且从网上找了一个评测结果的现实页面(网页),还是很实用的,如下图(标黄的为不同处):

并且,我开始重视每一个bug,更重要的是每一个bug的产生原因,防范于未然。从我第三单元总结的测试分析中就可见一斑:

4.第四单元——展望未来

第四单元临近烤漆,没有对评测机做大的改动,基本上沿用了上一单元的思路,只需要重写数据生成程序。

对于未来的评测机(什么时候会用到呢?),我有一些自己的构想,希望能加入错误分类机制,就像buaaoo平台一样,可以提供错误类型及错误定位信息。错误类型的实现较为容易,我们也尝试过,但因为用途不大最终没有采用。错误定位信息的生成比较困难,尤其是我们现在的评测机大部分是对拍器,不是真正意义上的评测机。

最后,想感谢助教和老师们的辛勤付出,才有了比较健全的buaaoo的judge系统,因为自己写过才知道很不容易,所以,十分感激~~

四、课程收获总结

OO课程收获还是很多的,从一个什么都不会的OO小白,到一个看起来会OOP实际OPP的伪小白。

  1. java从入门到熟练(熟练的,不一定是代码,也可能是BUG)
  2. 从面向过程编程到面向对象编程,最起码现在写程序前,会想一下数据之间有没有什么联系,需不需要建类,需不需要继承...
  3. 搭评测机的过程中,复习了Python,认识了shell,重装java\python环境熟练。
  4. 意识到测试的重要性,随机数据和手捏数据都不能少 & 测试永远不会多,测试多一点,炸点少一点
  5. 意识到架构的重要性,一时重构一时爽,一直重构一直爽
  6. 发现了很多易错点,尤其是多线程单元的作业,希望吃一堑长一智
    ......

五、给课程的三个具体改进建议

1. 希望强测也引入互测中的同质bug修复机制,减少因同质bug导致的强测大面积WA

2. 希望架构方面的因素能体现在分数之中,这样同学会花更多的时间在架构设计上,而不是像我一样有时懒得管架构了(逃

3. 希望每个单元都有一定比例的性能分(具体指标没想出来),这样有利于分层

谢谢助教和老师们一个学期的辛苦付出~~

感谢拉我一把的各位大佬们orz

感谢屡败屡战苟活到现在的自己

~~OO完结撒花~~

OO第四单元总结——查询UML类图 暨 OO课程总结的更多相关文章

  1. OO第四单元总结及学期总结

    目录 OO第四单元总结及学期总结 第四单元三次作业架构设计 第十三次作业 第十四次作业 第十五次作业 四个单元中架构设计及OO方法理解的演进 第一单元 第二单元 第三单元 第四单元 四个单元中测试理解 ...

  2. oo第四单元总结及总课程回顾

    一.第四单元架构设计 1.第一次作业 第一次作业要求实现的只有对类图的分析.为了直观地搭建出一个类图,我新建了Manager类来处理UmlElement以及搭建树.但由于未能做好时间管理,因此第一次作 ...

  3. UML结构与解析——BUAA OO第四单元作业总结

    UML与解析架构 UML是什么 统一建模语言(英语:Unified Modeling Language,缩写 UML)是非专利的第三代建模和规约语言.UML是一种开放的方法,用于说明.可视化.构建和编 ...

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

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

  5. OO第四单元(UML)单元总结

    OO第四单元(UML)单元总结 这是OO课程的第四个单元,也是最后一个单元.这个单元只有两次作业,相比前三个单元少一次作业.而且从内容上讲这个单元的作业目的以了解UML为主,所以相对前三个单元比较简单 ...

  6. 北航OO第四单元——UML图解析

    北航OO第四单元--UML图解析 作业要求简析 刚接触本次作业可能需要花上一会才能搞清楚到底是要我们写个啥,在这里简单说一下: UML图的保存格式.mdj文件是以json文件的形式存储的,将每一个Um ...

  7. OO第四单元UML作业总结暨OO课程总结

    目录 目录一.第四单元UML两次作业架构设计第一次作业第二次作业二.架构设计总结与OO方法理解演进三.测试理解与实践演进四.课程收获总结五.课程改进建议六.尾声 一.第四单元UML两次作业架构设计 第 ...

  8. OO第四单元——基于UML的UML解析器总结&OO课程总结

    OO第四单元--基于UML的UML解析器总结&OO课程总结 前言:一学期愉快(痛苦)的OO课程学习结束了,OO几个单元作业都各有特色,实验也各有特色,仔细回味起来,不再是单纯的敲代码(但自己还 ...

  9. 2020 OO 第四单元总结 UML

    title: 2020 OO 第四单元总结 date: 2020-06-14 19:10:06 tags: OO categories: 学习 1. 本单元三次作业的架构设计 本单元的代码编写与第三单 ...

随机推荐

  1. hook 鼠标键盘消息实例分析

    1.木马控制及通信方法包含:双管道,port重用.反弹技术.Hook技术,今天重点引用介绍一下hook的使用方法,hook信息后能够将结果发送到hacker邮箱等.实现攻击的目的. 转自:http:/ ...

  2. luogu2746 校园网

    题目大意: 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”).注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学校的列表中. 你要 ...

  3. luogu1006 传纸条

    题目大意 小渊坐在矩阵的左上角,坐标 (1,1 ),小轩坐在矩阵的右下角,坐标 (m,n) .从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递. 在活动进行中,小 ...

  4. Windows:Word,PPT,EXCEL com+组件配置

    本文所涉及到配置前提: 服务器必须安装Office套件(Word,PPT,Excel) 第一部分 Word Com+组件权限配置 1.cmd模式输入dcomcnfg 2.找到Microsoft Wor ...

  5. 工具分享1:文本编辑器EditPlus、汇编编译器masm、Dos盒子

    工具已打包好,需要即下载 链接 https://pan.baidu.com/s/1dvMyvW 密码 mic4

  6. POJ 2553 Tarjan

    题意:如果v点能到的所有点反过来又能到v点,则v点是sink点,排序后输出所有的sink点. 思路:Tarjan缩点,输出所有出度为0的连通块内的点. PS:一定要记得把数组清零!!!!!!!否则自己 ...

  7. [你必须知道的.NET]目录导航

    http://www.cnblogs.com/anytao/archive/2007/09/14/must_net_catalog.html

  8. CSS画各种二维图形

    1.效果 2.源码 <%@ page contentType="text/html;charset=UTF-8" language="java" %> ...

  9. Python yield解析

    Pyhton generators and the yield keyword At a glance,the yield statement is used to define generators ...

  10. poj1328 Radar Installation 区间贪心

    题目大意: 在X轴选择尽量少的点作为圆心,作半径为d的圆.使得这些圆能覆盖所有的点. 思路: 把每个点都转化到X轴上.也就是可以覆盖这个点的圆心的位置的范围[a,b].然后按照每个点对应的a从小到大排 ...