U4 Summary
BUAA_OO U4 Summary
1.单元架构设计
| - MyImplementation
| - MyClass
|- UmlAttribute
|- MyInterface
|- Myoperation
|- UmlParameter
在本单元的作业中, 我并没有使用UmlClass、UmlOperation、 UmlInterface等官方包自带类,而使用自己实现的Myclasss类。一是因为对于上述类所需要关注的原始属性只有Id,ParentId,Name,官方包中上述类的结构较为复杂(其实是我看不懂),更重要的是,可以根据指令要求灵活地在各层结构中设置属性、方法,抛出异常。但是,对于不需要额外方法、内部属性的UmlParameter、 UmlAttribute类,并不需要实现自己的类,使用官方包自带即可。
在层次化建模下,我们对于指令的处理结构也遵循层次化的原则,例如查询类方法的耦合度时,在Myclass类设置可以访问是否为重复操作或存在错误类型的方法,该方法的实现为调用Myope类中判断是否为重复操作和存在错误类型的方法,在impletation设置对于上述异常的抛出异常处理;对于符合要求的正确情况,在Myclass、Myoperation设置得到耦合度的方法,其中在Myclass类中实现为计算Myoperation的耦合度返回值总和。
| - MyImplementation
|- MyDiagram
| - MyClass
|- UmlAttribute
|- MyInterface
|- Myoperation
|- UmlParameter
|- MySequenceParse
|- MyInteraction
|- MyLifeLine
|- UmlEndpoint
|- MyStateMachineParser
|- MyStateMachine
| - MyState
| - MyTransiition
| - UmlEvent
值得说明的是,上述结构并不是正确的层次简的逻辑结构,而是在我的层次实现中的实现关系,比如MyTransition在设计中为MyState类中的属性,state对象可以调用transition类的方法。
在第二次作业中,为了实现层次的清晰,我将对类图、时序图、状态图的解析分别建模。此外,值得说明的是,我在此次作业作业采用了分层次异常抛出。
例如在时序图中返回对象创建者的查询指令实现中,我在MySequenceParse的层次中抛出 InteractionDuplicatedException()
、InteractionNotFoundException()
;随后调用MyInteraction类方法,在此层次中,抛出 LifelineDuplicatedException()
、LifelineNotFoundException()
异常,最后在MyLifeLine类中抛出 LifelineNeverCreatedException()
、 LifelineCreatedRepeatedlyException()
;
public UmlLifeline getParticipantCreator(String s, String s1) throws
InteractionNotFoundException, InteractionDuplicatedException,
LifelineNotFoundException, LifelineDuplicatedException,
LifelineNeverCreatedException, LifelineCreatedRepeatedlyException {
if (interactionWithNames.containsKey(s)) {
return interactionWithNames.get(s).getCreator(s1,umlLifeLines);
} else if (dupInteraction.containsKey(s)) {
throw new InteractionDuplicatedException(s);
} else {
throw new InteractionNotFoundException(s);
}
}
MyInteraction :
if (lifeLineWithNames.containsKey(lifeLineName)) {
return lifeLineWithNames.get(lifeLineName).lifeLineGetCreator(this.getName(),lines);
} else if (dupLifeLine.containsKey(lifeLineName)) {
throw new LifelineDuplicatedException(this.getName(),lifeLineName);
} else {
throw new LifelineNotFoundException(this.getName(),lifeLineName);
}
MyLifeLine:
if (creators.isEmpty()) {
throw new LifelineNeverCreatedException(interNa,this.getName());
} else if (creators.size() > 1) {
throw new LifelineCreatedRepeatedlyException(interNa,this.getName());
} else {
return lines.get(creators.get(0));
}
其实,上述架构的原因很明显,由于我们采用层次化设计的方法,所以每个层次的类就管理一定层次下的数据,以当前层次不能判断是否需要抛出异常,所以我们就将抛出异常的决定权交由下一层次。
架构设计总结
-
面对着第一单元第一作业,回忆起架构设计的过程可谓非常艰难;尽管有着pre2的预习经验,但入手表达式的建模仍不是一件一件的事。首先需要构建起解析字符串的模式,在这个过程中我也学会了递归下降,学会了由构建Parser类、Lexer类等某一特定类型的类来实现我们的解析过程,这也呼应了我们在计组中学习到的“高内聚,低耦合”的思想吧;随后,更为重要的是,我们需要建模来表征运算因子、运算符,在第一次的作业中,
我竟然有过由字符串表示因子的想法,我们初步开始应用面向对象的思想,什么是对象,在这作业中,运算因子就是对象,我们需要建立运算因子专属的类来表征他们,并通过一定的容器管理这些因子对象。当建立运算因子的类后,就需要将运算符抽象为每个类的方法。 -
第二单元的训练过程中,在初步面对多线程的束手无策到看到实验代码后的豁然开朗,可谓是“守得云开见月明”。第二单元的架构,更像是一个流水线,各个工种在同一时间各司其职。在设计架构时,引入输入处理类、调度器类、电梯类、候乘表类;输入处理线程、调度器线程、电梯线程同时工作。其中,候乘表作为共享对象,需要封装成线程安全的类,以实现各个线程的互斥访问、存取。
-
第三单元的主题是规格,规格中的抽象数据、抽象方法其实已经包含了对于层次架构的设计,在这一单元,我的架构设计以实现整体规格为主,并辅助设计几个特殊的类来实现并查集判断是否为公共父节点、构建用于规划最短路径、最小生成树的小堆顶。
-
第四单元的整体架构其实由类图、时序图、状态图的结构决定,在这个单元的作业中,我更能体会到一种层次化设计的鲜明特点,所有的指令实现由实现UML图的各个层次的类分层次部分实现。
对oo思想的演进:
一开始对于oo的理解是,对一些具有鲜明结构的数据,或者是对一组具有联系的数据,用一个特定的结构来存储并设置一系列方法来管理。确实也算是入门级的理解了(笑哭。
到一单元,在我自己开始独立设计复杂的方法实现时,深刻地体会了oo思想带来的便捷。在表达式类中构建乘法方法时,突然想到,表达式由因子组成,如果以常规方式实现,这个乘法方法太过于复杂;但其实,在表达式类的乘法只需要关注实现逻辑,及有限个,表达式A中的因子A1和表达式中因子B1的乘积之和。所以,当我捋清这一关系后,只需要实现因子类的乘法即可,而因子类的乘法实现也已经实现。所以,在我的理解中,oo建模思想是有助于代码复用,和简化设计。
后续,又看见实验代码中Parser类和Lexer类的解析表达式器设计,感觉oo思想又莫名眼熟,这不我们CO时期模块化的低耦合和高内聚嘛
在完成第四单元时,我也再一次体会了,当我在重构某一个指令实现时,途中只出现了一个类的飘红,我想其中原因,无非是做完了层次化设计后,我们各个层次、各个类的实现都只是对自身的管理,不会牵一发动全身,相较于面向过程的编码,一处修改,往往可能带来处处填坑。
总结而言,其实OO思想更为重要的时候,分层次建模,归纳层次架构时,我们完成了对有联系的抽象数据的梳理、抽象方法的构造,这样才有助于各个不同的类各司其事,不因为某个类变化影响其他类。
课程收获总结
1.在第一单元中,在额外学习递归下降解析的基础上,以Expression表达式、Factor因子分层次对运算因子和运算数完成了建模,第一次以面向对象的方式思考分析形式化语言的实现,也学会BNF形式化表达。
-
在第二单元中,第一次了解了多线程,学会多线程互斥访问共享资源的写法。
-
在第三单元,开始接触契约式编程,其实感觉更像是面向规格编程。
-
第四单元,进一步深化了层次化设计架构思想。
测试
在第一单元前期,主要使用sympy库生成正确答案进行对比,但到第二次、第三次作业就需要和同学进行对拍。
在第二单元,没有自主完成测试。第三、四单元主要采用随机生成数据+ Subprocess库构建子进程+与同学对拍完成。
对课程的建议
1.建议在pre环节训练表达式建模的思想,降低第一单元的引入难度。可以先由后缀表达式解析训练来完成实现运算符、运算因子的建模。
2.引入现场答疑环节,对每单元的建模架构可进行指导。
3.完善研讨课制制度,建议固定分组,每次研讨课轮流划分记录、发言分工;在讨论内容相对较少的第三、第四单元可以引入小组自由决定讨论内容的策略。