一、总结本单元两次架构设计
作业1:
第一次作业需要使用给定的接口,对一个类图进行解析。
由于观察mdj文件的组织形式是类似树的,因此我大部分的组织形式也跟树相似。并且优先构造Class和Interface,之后再把属性、操作、参数等加入其中,防止接口传入的UmlElement不按照顺序出牌
对于所有的功能,基本都设置了缓存的查找方式:假若没有算过,则当即算一遍;如果已经有结果了,那么直接返回结果。
由于这次作业比较简单,也没什么好说的。
作业2:
第二次作业需要使用给定的接口,对类图、时序图、状态图进行解析。
其实虽然这次作业看上去挺复杂的,但是实际上由于给出了较多简化,甚至一些UmlElement都不需要考虑(忽略掉,例如Event之类的)。
--------类图--------
类图部分的架构沿用了上次,新增部分是UmlRuleCheck部分。重点需要说明的算法是后两个Check:一个是循环继承(类之间、接口之间),一个是重复实现(或接口继承):
- 循环继承:以类举例,接口同理。
- 遍历所有类,假若类的循环继承标记为false,则检查是否发生循环继承:
- 使用深度优先方法(对于接口此处重要),访问尚未访问到的类(以找父类的方式访问)。
- 假若遇到与查找初始类id相同的类,则视为发现循环继承,返回true并且把当前类的循环继承标记记为true(因为当前类也在循环圈中)。
- 遍历所有类,假若类的循环继承标记为false,则检查是否发生循环继承:
- 重复实现:以自父亲向下的方式实现,对于一个类,显然,如果他的父类是有重复实现的,那么他也有重复实现,因此考虑使用类似递归的方式来判断。具体算法大致如下(依然以类举例):
- 对于每一个类进行判断:假若当前重复实现尚未被检查,则进行重复实现检查:
- 调用继承的父类的重复实现检查
- 假若父类重复实现标记为true,那么当前类的重复实现标记也为true
- 假若父类重复实现标记为false,那么说明父类没有重复实现,此时会获取父类实现接口的列表,然后更新自己实现接口的列表:
- 对于此类的每一个接口实现(InterfaceRealization),假若target尚未在列表中,那么说明这个接口实现并没有重复,把相应接口加入实现接口的列表
- 假若已在列表中,说明此类有重复实现,直接将标记记为true并不再继续维护列表(本次任务不需要输出所有重复实现的接口,因此在这里可以直接返回)
- 调用继承的父类的重复实现检查
- 对于每一个类进行判断:假若当前重复实现尚未被检查,则进行重复实现检查:
--------时序图-------
比较简单,只需要查找lifeline个数、message个数等不详细解释了
--------状态图-------
查找状态数、查找转换数较为简单
查找后继状态算法:BFS查找即可,其实完全不需要考虑初始态、最终态的数量。
因为实际上就是一个有向图查找后继节点数量而已,最终假若后继有初态+1,有终态+1,其他都+1就行了。
二、总结四个单元架构设计和OO理解的变化
四个单元下来,我们发现作业都是渐进式的,因此一个好的设计就是相当必要的了。
从最开始对于OO的不理解,到现在明白万事万物均对象,简直是个大飞跃,还是有了不小的收获。
OO设计的核心我认为在于,抽象出类,实例化对象。程序则是对象通过消息来进行沟通完成的。
在实现上则有很多技巧、设计模式等,都是等待我们深入挖掘的。
三、总结测试的理解与变化
一开始对于测试的理解就是,我们绞尽脑汁莽一个复杂的测试数据,一下就给对面爆了,好像很爽。
现在发现,其实对于小规模代码(即部分代码)的针对性测试是相当有效的,例如单元测试。
要想保证一个程序的正确性,不仅要进行大规模数据的黑盒测试,更要进行有针对性的白盒测试。只有达到分支覆盖率100%才能保证代码的正确性
四、总结课程收获
课程收获很多,具体总结一下就是以下几条吧:
- 锻炼我的肝代码能力(其实说实话今年的强度还好(重修生如是说道,毕竟有寒假的作业,对于新手是相当有好了))
- 学到了OO的设计理念(别问,问就是封装继承多态)
- 理解了测试的意义和重要性
- 认识了很多优秀的狼人同学
五、提三个改革建议
- 指导书明确
指导书虽说是经过多次修订的,但是实际上每次出来之后还是会出现很多不明确的地方。说实话我也不知道这个该怎么改善(例如多举几个例子?),但是总之请改善。
这个问题在最后这个单元比较明显,例如没说明白所有初始态是否算作一个等。
- 上机部分改善
上机部分的说明有时候也挺模糊的,都要靠实地大家再明确。
- 互测模式改善
虽说今年使用的互测模式相对往年有很大改进,并且算分思路改变。
但是实际上由于大家课业强度和热情的原因,后期好像大家都不太喜欢互测挑bug了,不知道有没有什么好的办法。