BUAA OO 第四次作业总结

第四单元架构设计

第十三次作业

按照 UML 图建立类和关系即可。

需要注意的是输入的顺序是随机的,但是 UML 的 parent_id 隐含了一个继承的关系,所以我才用的是每次只读取一种 UmlElement 的方法,多次读取:

for (UmlElement element: elements) {
    if (element instanceof /* ElementType1 */) {
        // ...
    }
}

for (UmlElement element: elements) {
    if (element instanceof /* ElementType2 */) {
        // ...
    }
}

// ...

读取的顺序如下:

- UmlClass
- UmlInterface
- UmlAssociationEnd
- UmlAttribute
- UmlGeneralization
- UmlInterfaceRealization
- UmlOperation
- UmlAssociation
- UmlParameter

同时,这个单元我用了大量的 Stream 简化代码。Stream 真好用()

第十四次作业

增加了状态图和顺序图,和上一次作业差别不大。解析的顺序为:

- UmlClass
- UmlInterface
- UmlAssociationEnd
- UmlAttribute
- UmlGeneralization
- UmlInterfaceRealization
- UmlOperation
- UmlAssociation
- UmlParameter
- UmlStateMachine
- UmlRegion
- UmlState
- UmlFinalState
- UmlPseudostate
- UmlTransition
- UmlEvent
- UmlInteraction
- UmlLifeline
- UmlMessage

第十五次作业

这次作业主要加入了错误 UML 的判断。因此架构上基本不变,但是为了解耦,我单独分出了一个 Parser 类用来解析 UML 元素。

实现上的难点主要在于判断循环引用等,这个可以用 DFS 实现。简单计算不难发现暴力 DFS 并不会超时。

另外就是要注意对于各种“判断是否重名”/“判断是否存在”的 Rule,要搞清楚他们分别在说什么。这里没有规格,而且语义表述有点模糊,还是比较麻烦的。

架构设计总结

我觉得每个单元的架构设计思路都是不一样的:

  • 第一单元强调用“对象”来模拟一个已经存在的东西(一个“数学对象”),而不是另一种抽象的模型
    • 在这个单元设计架构时,我以数学定义为基础,根据 BNF 语法来设计架构层次,只需要定义“表达式”/“项”等类即可
    • 这样设计的好处是贴近现实,一定程度上降低了复杂度
  • 第二单元的主题是“多线程”
    • 很明显,这个单元和第一单元不一样,加入了“生产者消费者”模型的概念,强调以一个抽象模型为基础进行设计(我认为这个单元最接近 Design Patterns
    • 因此我在设计架构时,以“生产者消费者”模型为基础,加入调度器等设施,设计“Producer”/“Consumer”/“Controller”等类
  • 第三单元强调“规格化”
    • 相比起前两个单元,这个单元的设计“几乎”已经通过规格给出了,因此我设计的基础也是给出的规格
    • 同时,也要考虑到性能等因素,加入一些Cache,此时会引入一些额外的对象
  • 第四单元以 UML 为基础,在现有的模型上进行改进
    • 其实这个单元有点像第一单元和第三单元的结合,因为 UML 的结构已经定义好了,我们要做的是在此基础上添加自己想要的内容
    • 但是这个单元在设计架构时比第三单元更加灵活,因为没有了规格的定义,十分符合“适配者模式”

对 OO 的理解演进:

  • 一开始我认为 OO 的发明只是为了代码复用,例如“继承”技术等
  • 现在我认为 OO 最大的作用在于解耦隐藏复杂度。架构设计的关键在于“封装”,而“代码复用”则是一个副产物。
    • 代码复杂度和代码量之间并不是一个“线性关系”,而是一个“高次多项式”甚至是“指数”的关系。通过设计上的“解耦”,我们能够将一个工程分解成几个小架构,然后逐个击破(有点像因子分解)
    • 只要保证每个组件的正确性,以及组件间“关系”的正确性,我们就能保证整个系统的正确性
    • 无论是“面向对象”,还是“面向规格”,或者是“设计模式”,他们被发明的目标都是为了应对工程的复杂度

工科的历史就是人类与工程复杂度塔塔开的历史
而博客作业则是同学们与 OO 作业塔塔开的见证

测试总结

  • 在第一单元中我使用了 Python + Sympy 作为数据生成和测试手段
    • 一开始效率比较低下,后来通过减小“数字”的规模来加速
  • 在第二单元中我以手动测试为主(主要是各种边界情况)
  • 第三单元以肉眼 Debug 为主,因为规格是固定的,所以阅读代码找漏洞比较方便

总结来说,最好的测试方法是“随机” + “构造”。

课程收获

  • 在第一单元学会了根据对象的属性分割出“类”和“接口”(同时学到了递归下降,感觉有点像写解释器了)
  • 在第二单元进行了多线程的简单实践,学到了锁的产生原因和避免
  • 在第三单元学到了规格化编程的思想
  • 在第四单元学习了 UML 类图相关的知识

除此之外:

  • 学会了熟练使用各种“容器”:虽然以前参加竞赛写过 C++,但是一直不习惯使用容器,而是习惯用自己手写的。经过这门课的学习,我也变成了“调库侠”(褒义)了
  • 学会了“封装”,以及各种 OO 的规范和 checkstyle
  • 学会了熟练使用函数式 API(Stream 永远的神)
  • 知道了一些工程上的概念,例如代码的“圈复杂度”等
  • 熬夜技能更加熟练了!

改进建议

  • 增加可选的预习环节
    • 个人感觉似乎每个单元中最难熬的都是第一次作业(第一单元除外)。无论是第二单元“对多线程的使用”,还是第三单元明白“什么是规格”,以及第四单元理解“UML 的结果”,在经过第一次作业后都感觉轻松不少。相反的是,与之相邻的博客周却非常轻松。
    • 因此我认为可以在博客周提前发布一些可选的预习任务或者资料,让同学们提前了解下一单元的内容
    • 可以的话希望能在寒假预习中提一下“递归下降算法”,让同学们提前了解
  • JML 单元的改进
    • 据收集资料,我发现网上很少有有关 JML 的资料,这个工具使用的似乎也比较少(不过看了一些资料,好像也没有更好的选择就是了)。
    • 感觉可以加入关于防御式编程的普及,例如推广 assert 的使用
    • 此外,我建议可以加入各种测试方法实践(单元测试/回归测试/etc)
    • 如果要加入新内容的话,可以考虑削减部分原来的任务量
  • 设计模式
    • 这门课有很多实践内容,但是似乎对于“设计模式”本身的介绍比较少,都是靠同学研讨课普及,或许可以考虑加一些阅读材料?(为什么不推荐在考试里面加呢,当然是为了减轻同学的压力(
  • 给出一些 Best Practice
    • 希望课程组能选出同学中比较好的一些代码或者架构,让同学们能互相学习。
    • 不然实验做下来,虽然自己做的有问题但是却不自知还是比较难受的。
  • 希望能减轻“互测”的强度
    • “互测”感觉很耗费精力,希望能适当减轻一下强度
  • (小声)建议加入函数式编程的科普
posted @ 2021-06-23 01:10  roife  阅读(600)  评论(0编辑  收藏  举报