Final Summary

Final Summary

写在前面:由于撰写本文时正处考期,时间较为紧张,很多内容没有展开来谈,深表遗憾。

第四单元三次作业架构设计

总体架构:用MyElement管理每个(任何类型的)UML元素,其中存储儿子、父亲、关联对端、继承与实现的目标、状态转移的目标状态、生命线接受的信息等。在MyUmlInteraction交互类中,用HashMap<ElementType, HashMap<String, MyElement>>管理各种类型的MyElement

public class MyElement {
    private final UmlElement element;
    private MyElementsManager sons = new MyElementsManager();
    private HashMap<String, UmlAssociationEnd> associations = new HashMap<>();
    private HashMap<String, MyElement> generalizations = new HashMap<>();
    private HashMap<String, MyElement> implementations = new HashMap<>();   
    private HashMap<String, UmlTransition> transitionsTo = new HashMap<>();
    private HashMap<String, UmlMessage> messagesRecv = new HashMap<>();
    private MyElement parent;
    ...
}

第二次作业及第三次作业中,由于元素类型增多,对不同元素的访问需求越来越复杂,因此引入元素管理器类MyElementsManager,提供增加元素、按照指定类型获取该类型所有元素、按照指定id获取该元素的功能接口,为每个UML元素管理所有儿子和总交互类管理所有元素提供服务。这样的好处是,无需按照不同的元素类型分开管理,只需要处理时取出相应类型的元素即可。

public class MyElementsManager {
    private HashMap<ElementType, HashMap<String, MyElement>> elements =
            new HashMap<ElementType, HashMap<String, MyElement>>() {{
                for (ElementType type: ElementType.values()) {
                    put(type, new HashMap<>());
                }
            }};

    public MyElement findElementById(String id) { ... }

    public HashMap<String, MyElement> 
        findAllElementsByType(ElementType... types) {
        ...
    }

    public void add(MyElement newElement) { ... }

    public HashMap<String, MyElement> getAllElements() { ... }
}

第三次作业增加了检查功能,但大多数都由交互类和元素类负责实现,导致单个类代码较长;这也是使用元素管理统一管理带来的副作用。但总体来看,代码复杂度和算法复杂度都较低,除了第一次由于架构过于简单导致一个点TLE之外,都没有bug。

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

总体来看,四个单元架构设计的进步,主要体现在动手设计之前会更加考虑到后续的迭代,从而使用更加可维护且可增加功能的架构。例如,第一单元第二次作业就对第一次作业的架构进行了完全的推倒重构,是所有作业中工作量最大的一次;后续几次作业中,整体架构都比较稳定,没有出现大规模重构,可以说是有所进步。个人认为,架构设计最稳定的是第二单元的多线程电梯,三次作业的架构基本没有变化。三四单元的架构也相对稳定,每次都只有小修小补。

至于OO方法的理解,我认为第一单元教会我们的就足够了,即继承、多态等经典的OO概念;运用这些概念是十分自然的,这也是书写OO的代码给我们带来的快感所在。在每个单元的总结中,我们都会对工程的一些OO参数进行查看和反思;通过查看这些参数,有助于我们理解OO的设计应该是什么样的,例如“高内聚 低耦合”等等,可以说是让我们从自己的代码中理解OO的思想。

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

四个单元了,还是不会写自动测试脚本,也没有用成相关的自动生成测试用例的工具。

测试的方法总体来看还是比较粗暴的,前两个单元主要是根据理解,手动构造一些简单但有价值的样例;第三单元可以生成一些随机数据和同学的进行对拍;第四单元则主要是用实际的用例来进行测试。

这种测试简单,但只适合单线程程序;对于第二单元的多线程电梯,这样测试的难度较大。这也侧面反映出,对于程序的测试,主要还是要靠实际使用过程中的反馈;无论自己如何测试,也很难仅通过自行构造用例就发现所有的问题。

后面我们引入了JML、JUnit这样的工具来进行验证。从这些工具涉及的初衷来看,对开发程序的人员进行测试都有很大的帮助;但实际上我们也看到了,JML实际操作起来难度较大,使用体验也极差;JUnit虽然需要手动实现一些东西,但更加实用。坦白地说,我从来没有在作业中使用过相关的测试工具,只是在多线程debug中用到了相关的查看运行状态的工具,但我们必须正确认识这些工具的初衷带来的价值。尤其是JUnit使用的单元测试和覆盖性检查的思想,值得我们在今后的工程开发过程中使用。

课程收获

  • 语言

    学习并在一定程度上掌握了Java语言。这是学习本课程的最大收获。

  • 多线程编程

    此前从来没有接触过多线程编程,而OO课程为我们打开了新世界的大门。这也是最有价值的收获。

  • OO的思想

    上文也提到过,OO的思想其实是显而易见的。本课程是让我们用最好的实践的方式,去运用了OO的知识,让我们在实践中收获了经验,可谓是实践出真知。

  • 工程化思想

    坦白来说,对工程化思想的训练,OO课程不如计算机组成课和操作系统课更有力;但必须承认,这是OO课训练的必然结果。

改进建议

  1. 互测机制不公平,不同room使用的hack用例不同。建议改room内hack为提供评测用例对所有人进行评测,将被hack的bug计入公测,并为提供有效测试用例的加分。
  2. 多线程评测结果不稳定,严重缺乏严谨性。对于一份代码,在同一个测试用例上,至少应时间间隔较远地进行多次测试,并取最终结果。
  3. 单次作业周期太短;建议在提交截止前至少两周(甚至是讲授相关课程内容前)就发布作业。
  4. 公布每次实验结果,并实验结束后进行讲解。

线上学习体会

听课能听得更清楚,但对于课上讨论和研讨课来说,效率就过低了。

线上学习终究只是一种应急的方式,对于OO这种知识很活、需要大家共同分享的科目来说,还是需要线下的学习。这学期OO还是有相当的遗憾。

猜你喜欢

转载自www.cnblogs.com/stitch11752/p/13166179.html