OO Unit4 UML(United Modeling Language)

OO Unit4 UML(United Modeling Language)

将从第四单元架构设计、四个单元中设计思维变化、测试理解与实践、课程总结收获、改进建议展开

第四单元架构设计

本单元我没有使用诸多类将相关的数据进行封装,而只是在整体上将属于不同UML图中的元素下放到ClassModel、SequenceDiagram、StateChart三个类中,在每个类中管理该类对应的前束检验、查询方法。类的设计应当是以复杂度为标准的,数据结构的复杂度在能掌控的范围之内则不需要过度抽象。

具体而言,对于parent有明确语义的元素,将他们归属到parentId对应的元素集中,实现诸如查询一个Class对应的xxx的功能。

//ClassModel
private final HashMap<String, HashSet<UmlElement>> attributes;
private final HashMap<String, HashSet<UmlGeneralization>> generalizations;
private final HashMap<String, HashSet<UmlElement>> interfaceRealizations;
private final HashMap<String, HashSet<UmlElement>> operations;
private final HashMap<String, HashSet<UmlElement>> parameters;
​
//StateChart
private final HashMap<String, HashSet<UmlElement>> outTransitions;
private final HashMap<Pair<String, String>, HashSet<UmlElement>> transitions;
private final HashMap<String, HashSet<String>> graph;                   
private final HashMap<String, HashSet<UmlElement>> events;              
private final HashMap<String, String> begin;                           
private final HashMap<String, HashSet<UmlElement>> ends;                 
private final HashMap<String, Integer> stateCnt;  

对于诸如这样HashMap<String, HashSet<>>的结构要警惕空指针的问题,比较好的方法应该是设计一个容器实现对这个的增删改查,可惜意识到这一点时已经写得差不多了,没有再修改。

对于检验参数合理性的方式,我采用以下方式,看起来还算优雅(

private static final Map<Direction, HashSet<String>> VALID_PARA =
  Collections.unmodifiableMap(new HashMap<Direction, HashSet<String>>() {
    {
      put(IN, Stream.of("byte", "short", "int",
                        "long", "float", "double",
                        "char", "boolean", "String")
          .collect(Collectors.toCollection(HashSet::new)));
​
      put(RETURN, Stream.of("byte", "short", "int",
                            "long", "float", "double",
                            "char", "boolean", "String", "void")
          .collect(Collectors.toCollection(HashSet::new)));
    }
  });

而对于按名存取、比较是否重名等功能,类似地设置name对应到Set的映射即可

其中查询获取Class、Lifeline时抛出的异常都是相似的,应当抽象成方法完成。

private String getStateId(String smName, String stateName)
  throws StateMachineNotFoundException, StateMachineDuplicatedException,
StateNotFoundException, StateDuplicatedException {
  //do something
}
private String getClassId(String className)
  throws ClassNotFoundException, ClassDuplicatedException {
  //do something
}

第二次作业要求判定关键状态,可以遍历两次,若允许访问当前节点可以到达任一终点,不访问当前节点无法到达任一终点则说明是关键状态。(然而玩嗨皮了忘提交最后一次修改了呜呜呜)

第三次作业增加前束参数检查,值得注意到的是以下几点:

  • Attribute的归属问题

    我将Attribute放到最后再传入(遇到Attribute则传入则无法分辨类图和顺序图中的Attribute,只能依托检查时判定是否parentId出现在当前图中,不够优雅)

  • 循环继承判定

    采用了tarjan找元素个数>=2的强连通分量

  • 重复继承判定

    dfs+记忆化搜索,维护访问过的节点。

其中为了压缩类图的行数,我将tarjan求强连通分量的部分外置,并一贯地用了不少stream

设计思维变化与理解演进

第一单元 表达式解析

实现的功能其实是一些数学运算,根据优化程度不同可能运算能力分布于初中高中之间(

这一单元对设计思维要求较高,需要在理解递归下降法的基础上完成对“类”这一抽象层次结构的功能分划。这个过程中我的类的功能完全服务于计算和优化。

此时我对类的理解更多是封装数据和操作、提供数据间的接口的层面。同时本单元聚焦于层级化设计,我也对高内聚低耦合的思想产生了共鸣。

第二单元 电梯调度

这一单元更多希望我们熟悉多线程与线程安全的保证。设计上采用生产者消费者模型,线程安全上主要采用了管程synchronized和信号量Semaphore来实现。算法上采取了look算法,并进行了量子电梯、重构估价函数等优化。

过程中我学习到了策略与机制分离的思想。同时对于多线程共享资源、临界区的设计有了一定的认识。

第三单元 社交网络

本单元强调规范与束缚,可谓是“戴着镣铐跳舞”,设计上主要层次化的类已经给出,架构都大同小异,只需理解JML描述并实现相应的功能即可。

过程中我对约束、契约式编程等概念有了新的认识。

第四单元 UML解析

本单元实现的是指令查询,从做的事的角度来说和第三单元没有显著差别。

对类的职能划分的理解更多是划分复杂度。

对测试的理解与实践

第一单元测试需要覆盖到边界情况,过程中发现的典型问题源自深拷贝与浅拷贝、优化对于边界情况判定上。这一单元的测试我采用手动构造边界数据完成,能够较好的看到优化带来的典型场景数据长度缩减,缺点在于手动构造边界覆盖性难以保证。

第二单元测试需要针对线程安全完成测试,本单元互测出现的问题也有一定的典型性:第一次没有获取讨论区提供的信息,第二三次均是优化的边界出问题。对于优化应当持谨慎态度。测试采用和同学对拍与手动编造极端数据实现,仍然是手动编造的数据有一定的杀伤力也有一定的局限性。

第三单元测试需要顾及性能,在堆优化与其他算法优化的前提下的正确性,测试方案同上,在手动构造初筛之后通过对拍进行测试。同时面向讨论区问题构造了一组数据(

第四单元测试前两次作业具有普遍性,用到了uu的数据生成测试,可惜测出问题改了忘交了。第三次作业需要手动构造,同样面向讨论区构造了一组数据。

然而在实际生产实践中并没有现成的“讨论区”供我们扩展自己测试数据的边界,这就要求我们写的过程中对诸个可能出现的问题多审视多白盒测试,完成一部分功能测试一部分、及时和相关人员(小伙伴、产品经理)消除自然语言二义性等。

课程收获

  • 基本掌握了java语法、特性、自学方案

  • 学习了面向对象思想与功能拆分解耦合的一些方案

  • 了解到了一些常用的设计模式

  • 初步了解了多线程的问题与解决方案

  • 掌握了一些图论算法

  • 养成了较好的代码风格(Command A + Command option L。。)

课程建议

  • 设置提问奖惩制度以提高提问质量,比如指导书中指明的信息提问记录一次不良记录

  • 预习内容可以再提前两天下放

  • 适当增加对使用设计模式的引导与提倡

posted @ 2022-06-27 14:56  Lumyn  阅读(40)  评论(0编辑  收藏  举报