作业分析
架构分析
本单元的主要任务是实现一个解析器,涉及类图、顺序图、状态图的解析,层次结构清晰明了。架构方面,我们仅需建立对应的类图管理类、顺序图管理类和状态图管理类,并封装一些图元素类,根据初始图元素提供的信息,逐步建立起类间的交互逻辑即可。
实现分析
本单元给出的模型为静态图,因此对于图中主要元素信息的查询都可设置缓存。
本单元的需求中,我认为最具有代表性的是获取一个类实现的全部接口。实现该需求,需要我们捋清类的继承关系,类和接口的实现关系,以及接口的继承关系。
talk is cheap, show you my code.
1 public class MyUmlClass { 2 private Set<MyUmlInterface> directInterfaces = new HashSet<>(); 3 private Set<MyUmlInterface> interfaces = null; 4 private MyUmlClass superClass = null; 5 6 public Set<MyUmlInterface> getInterfaces() { 7 if (interfaces == null) { 8 interfaces = new HashSet<>(directInterfaces); 9 for (MyUmlInterface mui : directInterfaces) { 10 interfaces.addAll(mui.getInterfaces()); 11 } 12 if (superClass != null) { 13 interfaces.addAll(superClass.getInterfaces()); 14 } 15 } 16 return interfaces; 17 } 18 }
当前类的getInterfaces
方法调用结束后,不仅该类的interfaces
缓存会被初始化,继承树中该类祖辈的interfaces
缓存也会被初始化,从而为后续可能的查询操作节省开销。
而正是因为采取了上述递归初始化缓存的方式,第三次作业的异常判断变得十分简单。除了循环继承的判断还是需要写搜索外,重复继承和重复实现,只需要稍微改动类和接口的getInterfaces
方法即可。
1 public class MyUmlClass { 2 private Set<MyUmlInterface> directInterfaces = new HashSet<>(); 3 private Set<MyUmlInterface> interfaces = null; 4 private MyUmlClass superClass = null; 5 private boolean realizationDuplicate = false; 6 7 public void addInterface(MyUmlInterface mui) { 8 // check duplication 9 if (directInterfaces.contains(mui)) { 10 realizationDuplicate = true; 11 } else { 12 directInterfaces.add(mui); 13 } 14 } 15 16 public Set<MyUmlInterface> getInterfaces() { 17 if (interfaces == null) { 18 interfaces = new HashSet<>(directInterfaces); 19 for (MyUmlInterface mui : directInterfaces) { 20 // check duplication 21 for (MyUmlInterface mui2 : mui.getInterfaces()) { 22 if (interfaces.contains(mui2)) { 23 realizationDuplicate = true; 24 } else { 25 interfaces.add(mui2); 26 } 27 } 28 } 29 if (superClass != null) { 30 // check duplication 31 for (MyUmlInterface mui3 : superClass.getInterfaces()) { 32 if (interfaces.contains(mui3)) { 33 realizationDuplicate = true; 34 } else { 35 interfaces.add(mui3); 36 } 37 } 38 } 39 } 40 return interfaces; 41 } 42 }
此时,我们对当前类图中的类和接口均调用一次getInterfaces
方法,即可完成重复继承和重复实现的检查,同时初始化了所有类和接口的interfaces
缓存。
值得注意的是,该方式要求递归存在终止条件,若非此次作业的循环继承异常判断在先,则必死。
霸哥分析
本单元第二次作业由于疏漏了UmlMessage
的target
可能指向一个UmlEndPoint
的情况,爆了强测中的一个点,也打破了笔者强测未败的记录。当事人就是非常后悔。
四单元的架构设计及OO方法理解的演进
第一单元:表达式求导
在本单元,笔者认识到一个表达式由若干个项组成,一个项由若干个因子组成的层次结构,分别建立了对应的类和接口,并认识到合并同类项后只有展开再合并才能做更多化简的化简方向,实现了架构允许下的化简,取得了较好的效果。这一单元,笔者认为是四单元中最好玩的一个单元,不同的架构方向对应着不同的化简尺度,且最终都能走向正确的结果。
第二单元:多线程电梯
在本单元,笔者大体清楚应建立电梯、等待队列、调度器等类,对其中的信息交互逻辑却十分困惑,很吃力地写了一版实现,且留有电梯停于某一楼层等待请求时不会自动关门的场景。不过,本单元的作业让笔者体会到了迭代开发的爽感,懂的都懂。可惜的是,受架构约束,笔者未能做到很好的性能优化。
第三单元:领教JML
在本单元,笔者体会到了契约式编程的魅力,规格给予了实现人员充分的自信,也为团队编程提供了基础,你写规格,我写实现,满足规格的实现,就是正确的、完备的实现。至于本单元的作业,笔者愿称之为数据结构与算法分析——爪哇语言描述,并不涉及很多架构层次的东西,考察的大多是图论算法。
第四单元:领教UML
在本单元,笔者清清楚楚的记下了模型图中的各个元素以及它们之间的指向关系,可以说,笔者掌握了读模型图的能力,也掌握了绘模型图的能力。但这不意味着,未来笔者在面对更为复杂的工程时,能画出一个好的架构图,在架构编程的道路上,笔者还有很远的路要走。
总结
受限于笔者的表达能力,笔者无法清晰地表达这个演进过程。但笔者深知,在拿到一项任务时,首先应该做好架构分析,秉持高内聚,低耦合的原则,给出建立哪些类,分配哪些职责,类之间存在哪些交互等问题的答案,且万不可一条路走到黑,更多地尝试新的实现版本,择优迭代。
关于测试
测试真的是笔者的一大短板,笔者虽知晓数据生成、对拍分析等测试步骤及原理,但受限于语言基础,实现起来异常困难。在此,笔者感谢诸位小伙伴们的不吝指教,没有你们,我真滴不行。
课程收获
回顾整个面向对象程序设计课程,我们学习了层次化程序设计、多线程程序设计、规格化程序设计和模型化程序设计,收获最大的应该就是问题剖析能力了,同时,每一次的作业对我们的编码能力和测试能力也是一种锤炼。
改进意见
-
希望理论课可以控制视频时长,90-100分钟为好
-
希望实验可以降低自由度(最后一次实验的填空形式舒服的一),以及明确考察方向(垃圾回收实验我万万没有想到考察的是手撸的二叉堆),以及公布正确结果(不然就摸了)
笔者老希望工程了。
线上学习体会
一般般吧,主要是没有见到英俊可爱的助教们。
言归正传,线上学习最好的一点就是学习时间的自由,录播视频可以提前看,可以提后看,可以反复看。以及隔着屏幕做研讨,也能少一分紧张吧(我太难了)。