目录
- BUAA_OO_UML第四单元总结
- 本单元两次作业架构设计
- 第一次作业
- 第二次作业
- 四个单元中架构设计以及对OO理解的演进
- 第一单元:表达式求导
- 第二单元:多线程电梯
- 第三单元:JML规格化设计
- 第四单元:UML模块
- 四个单元对测试理解以及实践的演进
- 第一单元:自动生成数据+对拍
- 第二单元:利用Python的time库进行多线程精准投放记时
- 第三单元:利用JUnitNG、SMTSolver进行自动化检测
- 第四单元:JUnit测试
- 课程收获
- 对课程的改进建议
- 本单元两次作业架构设计
BUAA_OO_UML第四单元总结
本单元两次作业架构设计
第一次作业
作业概述
第一次作业主要需要我们完成的是对于UML类图的解析工作。第一次作业拥有较高的深度,虽然涉及的内容只是UML类图,但是对UML类图的所有主要元素、主要联系都有所考察。同时由于UML和java在建模的过程中有许多不一致之处,所以这次作业中的规范理解也至关重要,但是在本次作业中,为了保证正确性和鲁棒性,同时也为了更好地锻炼自己的代码能力,我还是选择了尽量满足所有UML支持的建模,从第二次作业来看,虽然依旧写了非常多的“无用”代码,但是代码的可扩充性、可复用性都经受住了检验。
架构设计
对每一个类图中的元素建模,UmlInteraction下管理若干个类接口
并使用多个Hashmap来建立不同的映射关系。
private HashMap umlClassHashMap = new HashMap<>();
private HashMap
umlInterfacesHashMap = new HashMap<>();
private HashMap classAndInterfaceMap = new HashMap<>();
private HashMap classesNameMap = new HashMap<>();
private HashMap classesGetByNameMap = new HashMap<>();
在我的处理中UmlInterface,即接口类直接继承UmlClass类,这样就可以统一进行处理,也可以支持类继承接口,接口实现接口之类的UML能画出的所有情况。
而在UmlClass类中,需要存储的信息就比较多了
/*
*本类的基本信息
*/
private String name;
private String id;
private String visibility;
/*
*存储本类与其他 类 / 接口 关系
*/
private HashMap associateClassMap = new HashMap<>();
private List associateClassList = new ArrayList<>();
private HashMap interfacesMap = new HashMap<>();
private HashMap childClassesMap = new HashMap<>();
private HashMap fatherClassesMap = new HashMap<>();
/*
*本类的方法、属性统计
*/
private HashMap attributeHashMap = new HashMap<>();
private HashMap wholeAttributeNameMap = new HashMap<>();
private HashMap
wholeAttributeGetByNameMap = new HashMap<>();
private HashMap
notHiddenAttributeMap = new HashMap<>();
private HashMap operationsHashMap = new HashMap<>();
private HashMap wholeAttributes = new HashMap<>();
/*
*存储特定的需要查找的数据
*/
private UmlClasses topBaseClass = this;
private int nonReturnCount = 0;
private int returnCount = 0;
private int nonParaCount = 0;
private int paraCount = 0;
这里的存储父类使用了Hashmap,意味着我的代码架构也能支持多继承,这个架构在第一次作业非法,但是在第二次作业中就能够直接使用,无需修改。
使用了这些结构之后,类与类的继承关系就能构成一颗树、关联关系就能构成一张图,我这里采用的是边建立边运算的方法,在查询时可以直接得到结果,但是不可否认,这个设计增加了维护的难度,所幸并未出现bug。
总体类图如下:
代码复杂度统计
Method | ev(G) | iv(G) | v(G) |
---|---|---|---|
AssociationEnd.AssociationEnd(String,String,String) | 1 | 1 | 1 |
AssociationEnd.getAssociationId() | 1 | 1 | 1 |
AssociationEnd.getClassId() | 1 | 1 | 1 |
AssociationEnd.getId() | 1 | 1 | 1 |
Attribute.Attribute(String,String,String,String) | 1 | 1 | 1 |
Attribute.getId() | 1 | 1 | 1 |
Attribute.getName() | 1 | 1 | 1 |
Attribute.getType() | 1 | 1 | 1 |
Attribute.getVisibility() | 1 | 1 | 1 |
Main.main(String[]) | 1 | 1 | 1 |
MyUmlInteraction.MyUmlInteraction(UmlElement[]) | 3 | 8 | 15 |
MyUmlInteraction.dealAssociation(UmlElement) | 4 | 4 | 4 |
MyUmlInteraction.dealAttribute(UmlElement) | 1 | 3 | 3 |
MyUmlInteraction.dealClass(UmlElement) | 1 | 2 | 2 |
MyUmlInteraction.dealGenerazation(UmlElement) | 1 | 1 | 1 |
MyUmlInteraction.dealInterface(UmlElement,UmlElement[]) | 1 | 6 | 6 |
MyUmlInteraction.dealOperation(UmlElement) | 1 | 4 | 4 |
MyUmlInteraction.dealParameter(UmlElement) | 1 | 2 | 2 |
MyUmlInteraction.getClassAssociatedClassList(String) | 3 | 3 | 5 |
MyUmlInteraction.getClassAssociationCount(String) | 3 | 1 | 3 |
MyUmlInteraction.getClassAttributeCount(String,AttributeQueryType) | 4 | 2 | 4 |
MyUmlInteraction.getClassAttributeVisibility(String,String) | 9 | 2 | 9 |
MyUmlInteraction.getClassCount() | 1 | 1 | 1 |
MyUmlInteraction.getClassOperationCount(String,OperationQueryType) | 8 | 6 | 8 |
MyUmlInteraction.getClassOperationVisibility(String,String) | 4 | 8 | 14 |
MyUmlInteraction.getImplementInterfaceList(String) | 3 | 2 | 4 |
MyUmlInteraction.getInformationNotHidden(String) | 3 | 2 | 4 |
MyUmlInteraction.getTopParentClass(String) | 3 | 1 | 3 |
Parameter.Parameter(String,String,String,String,String) | 1 | 1 | 1 |
Parameter.getDirect() | 1 | 1 | 1 |
Parameter.getId() | 1 | 1 | 1 |
Parameter.getName() | 1 | 1 | 1 |
Parameter.getOperationId() | 1 | 1 | 1 |
Parameter.getType() | 1 | 1 | 1 |
UmlClasses.UmlClasses(String,String,String) | 1 | 1 | 1 |
UmlClasses.addAssociation(UmlClasses) | 1 | 2 | 2 |
UmlClasses.addAttribute(Attribute,int) | 4 | 9 | 9 |
UmlClasses.addChildClass(UmlClasses) | 1 | 1 | 1 |
UmlClasses.addFatherClass(UmlClasses,int,UmlClasses) | 1 | 12 | 14 |
UmlClasses.addInterfaces(UmlInterfaces) | 2 | 4 | 5 |
UmlClasses.addOperation(UmlOperations) | 1 | 1 | 3 |
UmlClasses.getAssociateClassList() | 1 | 1 | 1 |
UmlClasses.getAssociateClassMap() | 1 | 1 | 1 |
UmlClasses.getAttributeHashMap() | 1 | 1 | 1 |
UmlClasses.getChildClassesMap() | 1 | 1 | 1 |
UmlClasses.getFatherClassesMap() | 1 | 1 | 1 |
UmlClasses.getId() | 1 | 1 | 1 |
UmlClasses.getInterfacesMap() | 1 | 1 | 1 |
UmlClasses.getName() | 1 | 1 | 1 |
UmlClasses.getNonParaCount() | 1 | 1 | 1 |
UmlClasses.getNonReturnCount() | 1 | 1 | 1 |
UmlClasses.getNotHiddenAttributeMap() | 1 | 1 | 1 |
UmlClasses.getOperationsHashMap() | 1 | 1 | 1 |
UmlClasses.getParaCount() | 1 | 1 | 1 |
UmlClasses.getReturnCount() | 1 | 1 | 1 |
UmlClasses.getTopBaseClass() | 1 | 1 | 1 |
UmlClasses.getVisibility() | 1 | 1 | 1 |
UmlClasses.getWholeAttributeGetByNameMap() | 1 | 1 | 1 |
UmlClasses.getWholeAttributes() | 1 | 1 | 1 |
UmlClasses.hasAttributeName(String) | 1 | 1 | 1 |
UmlClasses.isAttributeNameDuplicated(String) | 1 | 1 | 1 |
UmlInterfaces.UmlInterfaces(String,String,String) | 1 | 1 | 1 |
UmlInterfaces.addRealizationClass(UmlClasses) | 1 | 2 | 2 |
UmlInterfaces.getRealizationClassMap() | 1 | 1 | 1 |
UmlInterfaces.getType() | 1 | 1 | 1 |
UmlOperations.UmlOperations(String,String,String,UmlClasses) | 1 | 1 | 1 |
UmlOperations.addInParameters(Parameter) | 1 | 1 | 1 |
UmlOperations.getId() | 1 | 1 | 1 |
UmlOperations.getInputParameters() | 1 | 1 | 1 |
UmlOperations.getMyClass() | 1 | 1 | 1 |
UmlOperations.getName() | 1 | 1 | 1 |
UmlOperations.getReturnParameter() | 1 | 1 | 1 |
UmlOperations.getVisibility() | 1 | 1 | 1 |
UmlOperations.setReturnParameter(Parameter) | 1 | 1 | 1 |
可以看到除了顶层类UmlClasses和UmlInteraction,其余类的方法复杂度都非常小。而顶层类都是功能实现,与整体的数据结构无关,具有较好的可扩展性。
第二次作业
作业概述
第二次作业在完全保留了第一次作业功能的基础上,添加了关于顺序图、状态图的支持,同时添加了类图规范检测。这次涉及的范围较广,而难度我个人认为集中在类图规范检测以及状态图上,但是在经历了大幅度的简化之后,难度其实就在类图规范检测上了。
架构设计
在第一次作业的基础上,将第一次的MyUmlInteraction修改成专门的类图模型MyUmlClassModelInteraction,同时对状态图、顺序图都分别实现专门的接口,而不要在GeneralInteraction之中合并实现,这样能够初步保持代码的整洁性。
同样地,在处理状态图和顺序图时,我也对每个元素进行了重新建模。
这里出现的唯一问题就是类图的模型有效性检查,因为模型有效性检查在类图构造完毕之后。如果按照我第一次的代码实现,如果出现了循环继承那么必然会出现栈溢出的现象。但是我们可以通过抛出异常来顺利解决这个问题。但是抛出异常之后问题接踵而至了,在模型有效性检查中,重名异常的优先级高于循环继承异常,但是当循环继承抛出异常之后,类图就没有构建成功,重名检查也就无法进行。所以这里我直接使用了原有的Elements数组进行判断,一切也就迎刃而解。
状态图部分设计
状态图对状态机state machine、状态state和状态转换transition进行建模
顺序图部分设计
顺序图部分对每一个顺序图Sequence、每一个顺序图消息建模,并将Lifeline和endpoint统一建模
类图模型有效性检查部分
重名元素,只需在Elements数组中将每一个类的所有元素、关联统计起来,建立一个
Name <-> 次数
映射关系的Hashmap,统计完毕后遍历即可
循环继承,抛出异常只能作为检测是否出现循环继承的方法,但是如果存在很多个循环,显然不能够找出所有的循环链,所以这里在检测到所有异常之后,再根据Generation继承关系建立一个有向图,再寻找每一个回路
重复继承/实现接口,这条规则包含的情况比较多,但是从我第一次作业的架构来看,完全可以支持多继承等等,
所以我也没有考虑太多规则的限制情况,甚至不需要使用什么DFS就可以直接解决。
总体类图
总体类图比较复杂
代码复杂度统计
Method | ev(G) | iv(G) | v(G) |
---|---|---|---|
AssociationEnd.AssociationEnd(String,String,String,String) | 1 | 1 | 1 |
AssociationEnd.getAssociationId() | 1 | 1 | 1 |
AssociationEnd.getClassId() | 1 | 1 | 1 |
AssociationEnd.getId() | 1 | 1 | 1 |
AssociationEnd.getName() | 1 | 1 | 1 |
Attribute.Attribute(String,String,String,String) | 1 | 1 | 1 |
Attribute.getId() | 1 | 1 | 1 |
Attribute.getName() | 1 | 1 | 1 |
Attribute.getType() | 1 | 1 | 1 |
Attribute.getVisibility() | 1 | 1 | 1 |
CircleGeneralNode.CircleGeneralNode(String) | 1 | 1 | 1 |
CircleGeneralNode.addFatherId(String) | 1 | 1 | 1 |
CircleGeneralNode.getFatherIdSet() | 1 | 1 | 1 |
CircleGeneralNode.getThisId() | 1 | 1 | 1 |
FindCircle.FindCircle(HashMap |
1 | 7 | 7 |
FindCircle.addTransMap(String) | 1 | 2 | 2 |
FindCircle.findCycle(int) | 2 | 5 | 5 |
GenerationError.GenerationError(HashMap |
1 | 1 | 1 |
GenerationError.GenerationError(Set) | 1 | 1 | 1 |
GenerationError.getClassAndInterfaceMap() | 1 | 1 | 1 |
GenerationError.getClassesSet() | 1 | 1 | 1 |
Main.main(String[]) | 1 | 1 | 1 |
MyUmlClassModelInteraction.MyUmlClassModelInteraction(UmlElement[]) | 4 | 8 | 16 |
MyUmlClassModelInteraction.dealAssociation(UmlElement) | 4 | 4 | 4 |
MyUmlClassModelInteraction.dealAttribute(UmlElement) | 1 | 3 | 3 |
MyUmlClassModelInteraction.dealClass(UmlElement) | 1 | 2 | 2 |
MyUmlClassModelInteraction.dealGenerazation(UmlElement) | 1 | 2 | 2 |
MyUmlClassModelInteraction.dealInterface(UmlElement,UmlElement[]) | 1 | 6 | 6 |
MyUmlClassModelInteraction.dealOperation(UmlElement) | 1 | 4 | 4 |
MyUmlClassModelInteraction.dealParameter(UmlElement) | 1 | 2 | 2 |
MyUmlClassModelInteraction.getClassAndInterfaceMap() | 1 | 1 | 1 |
MyUmlClassModelInteraction.getClassAssociatedClassList(String) | 3 | 3 | 5 |
MyUmlClassModelInteraction.getClassAssociationCount(String) | 3 | 1 | 3 |
MyUmlClassModelInteraction.getClassAttributeCount(String,AttributeQueryType) | 4 | 2 | 4 |
MyUmlClassModelInteraction.getClassAttributeVisibility(String,String) | 9 | 2 | 9 |
MyUmlClassModelInteraction.getClassCount() | 1 | 1 | 1 |
MyUmlClassModelInteraction.getClassOperationCount(String,OperationQueryType) | 8 | 6 | 8 |
MyUmlClassModelInteraction.getClassOperationVisibility(String,String) | 4 | 8 | 14 |
MyUmlClassModelInteraction.getImplementInterfaceList(String) | 3 | 2 | 4 |
MyUmlClassModelInteraction.getInformationNotHidden(String) | 3 | 2 | 4 |
MyUmlClassModelInteraction.getTopParentClass(String) | 3 | 1 | 3 |
MyUmlClassModelInteraction.getUmlInterfacesHashMap() | 1 | 1 | 1 |
MyUmlCollaborationInteraction.MyUmlCollaborationInteraction(UmlElement[]) | 1 | 4 | 4 |
MyUmlCollaborationInteraction.getIncomingMessageCount(String,String) | 5 | 1 | 5 |
MyUmlCollaborationInteraction.getMessageCount(String) | 3 | 1 | 3 |
MyUmlCollaborationInteraction.getParticipantCount(String) | 3 | 1 | 3 |
MyUmlGeneralInteraction.MyUmlGeneralInteraction(UmlElement[]) | 1 | 2 | 2 |
MyUmlGeneralInteraction.addAllChild(UmlClasses,Set) | 1 | 2 | 2 |
MyUmlGeneralInteraction.addItem(HashMap |
1 | 2 | 2 |
MyUmlGeneralInteraction.addRepeatNameMap(String,HashMap |
2 | 2 | 3 |
MyUmlGeneralInteraction.buildCirlceNode(UmlElement) | 1 | 2 | 2 |
MyUmlGeneralInteraction.checkForUml002() | 2 | 2 | 3 |
MyUmlGeneralInteraction.checkForUml008() | 2 | 1 | 2 |
MyUmlGeneralInteraction.checkForUml009() | 6 | 10 | 13 |
MyUmlGeneralInteraction.countRepeatFatherClasses(UmlClasses,HashMap |
1 | 2 | 2 |
MyUmlGeneralInteraction.dealElementForUml002(Set,UmlElement) | 7 | 18 | 18 |
MyUmlGeneralInteraction.dealStraightRealization(Set) | 5 | 7 | 7 |
MyUmlGeneralInteraction.getClassAssociatedClassList(String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getClassAssociationCount(String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getClassAttributeCount(String,AttributeQueryType) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getClassAttributeVisibility(String,String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getClassCount() | 1 | 1 | 1 |
MyUmlGeneralInteraction.getClassOperationCount(String,OperationQueryType) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getClassOperationVisibility(String,String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getImplementInterfaceList(String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getIncomingMessageCount(String,String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getInformationNotHidden(String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getMessageCount(String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getParticipantCount(String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getStateCount(String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getSubsequentStateCount(String,String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getTopParentClass(String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.getTransitionCount(String) | 1 | 1 | 1 |
MyUmlGeneralInteraction.isFatherHasRealization(UmlClasses,UmlInterfaces) | 4 | 2 | 4 |
MyUmlGeneralInteraction.judgeHasRepeatRealization(UmlClasses) | 4 | 3 | 4 |
MyUmlGeneralInteraction.judgeHasSameRealization(UmlClasses) | 3 | 2 | 4 |
MyUmlGeneralInteraction.sameRealizationCount(UmlInterfaces,HashMap |
2 | 4 | 5 |
MyUmlStateChartInteraction.MyUmlStateChartInteraction(UmlElement[]) | 5 | 7 | 7 |
MyUmlStateChartInteraction.getStateCount(String) | 3 | 3 | 5 |
MyUmlStateChartInteraction.getSubsequentStateCount(String,String) | 5 | 2 | 6 |
MyUmlStateChartInteraction.getTransitionCount(String) | 3 | 1 | 3 |
Parameter.Parameter(String,String,String,String,String) | 1 | 1 | 1 |
Parameter.getDirect() | 1 | 1 | 1 |
Parameter.getId() | 1 | 1 | 1 |
Parameter.getName() | 1 | 1 | 1 |
Parameter.getOperationId() | 1 | 1 | 1 |
Parameter.getType() | 1 | 1 | 1 |
SequenceDiagram.SequenceDiagram(String,String,UmlElement[]) | 1 | 8 | 8 |
SequenceDiagram.getId() | 1 | 1 | 1 |
SequenceDiagram.getLifeLineGetByNameMap() | 1 | 1 | 1 |
SequenceDiagram.getLifeLineMap() | 1 | 1 | 1 |
SequenceDiagram.getLifeLineNameCountMap() | 1 | 1 | 1 |
SequenceDiagram.getMessageHashMap() | 1 | 1 | 1 |
SequenceDiagram.getName() | 1 | 1 | 1 |
SequenceDiagram.getSequenceEndHashMap() | 1 | 1 | 1 |
SequenceEnd.SequenceEnd(String,String,String) | 1 | 1 | 1 |
SequenceEnd.addNext(SequenceEnd) | 1 | 1 | 1 |
SequenceEnd.addPre(SequenceEnd) | 1 | 1 | 1 |
SequenceEnd.getId() | 1 | 1 | 1 |
SequenceEnd.getName() | 1 | 1 | 1 |
SequenceEnd.getNext() | 1 | 1 | 1 |
SequenceEnd.getPre() | 1 | 1 | 1 |
SequenceEnd.getType() | 1 | 1 | 1 |
SequenceMessage.SequenceMessage(UmlElement) | 1 | 1 | 1 |
SequenceMessage.getFrom() | 1 | 1 | 1 |
SequenceMessage.getId() | 1 | 1 | 1 |
SequenceMessage.getName() | 1 | 1 | 1 |
SequenceMessage.getTo() | 1 | 1 | 1 |
States.States(String,String,String) | 1 | 1 | 1 |
States.addBeforeState(States) | 1 | 1 | 1 |
States.addNextState(States) | 1 | 1 | 1 |
States.calculateWholeTransistState(int,HashMap |
1 | 6 | 6 |
States.getBeforeStatesMap() | 1 | 1 | 1 |
States.getId() | 1 | 1 | 1 |
States.getName() | 1 | 1 | 1 |
States.getNextStatesMap() | 1 | 1 | 1 |
States.getType() | 1 | 1 | 1 |
UmlClasses.UmlClasses(String,String,String,UmlElement) | 1 | 1 | 1 |
UmlClasses.addAssociation(UmlClasses) | 1 | 2 | 2 |
UmlClasses.addAttribute(Attribute,int) | 4 | 9 | 9 |
UmlClasses.addChildClass(UmlClasses) | 1 | 1 | 1 |
UmlClasses.addFatherClass(UmlClasses,int,UmlClasses) | 2 | 14 | 16 |
UmlClasses.addInterfaces(UmlInterfaces) | 2 | 4 | 5 |
UmlClasses.addOperation(UmlOperations) | 1 | 1 | 3 |
UmlClasses.addStraightRealizeInterface(UmlInterfaces) | 1 | 1 | 1 |
UmlClasses.getAssociateClassList() | 1 | 1 | 1 |
UmlClasses.getAssociateClassMap() | 1 | 1 | 1 |
UmlClasses.getAttributeHashMap() | 1 | 1 | 1 |
UmlClasses.getChildClassesMap() | 1 | 1 | 1 |
UmlClasses.getElement() | 1 | 1 | 1 |
UmlClasses.getFatherClassesMap() | 1 | 1 | 1 |
UmlClasses.getId() | 1 | 1 | 1 |
UmlClasses.getInterfacesMap() | 1 | 1 | 1 |
UmlClasses.getName() | 1 | 1 | 1 |
UmlClasses.getNonParaCount() | 1 | 1 | 1 |
UmlClasses.getNonReturnCount() | 1 | 1 | 1 |
UmlClasses.getNotHiddenAttributeMap() | 1 | 1 | 1 |
UmlClasses.getOperationsHashMap() | 1 | 1 | 1 |
UmlClasses.getParaCount() | 1 | 1 | 1 |
UmlClasses.getReturnCount() | 1 | 1 | 1 |
UmlClasses.getStraightRealizeInterface() | 1 | 1 | 1 |
UmlClasses.getTopBaseClass() | 1 | 1 | 1 |
UmlClasses.getVisibility() | 1 | 1 | 1 |
UmlClasses.getWholeAttributeGetByNameMap() | 1 | 1 | 1 |
UmlClasses.getWholeAttributes() | 1 | 1 | 1 |
UmlClasses.hasAttributeName(String) | 1 | 1 | 1 |
UmlClasses.hasCircleRealization(UmlClasses) | 4 | 4 | 4 |
UmlClasses.isAttributeNameDuplicated(String) | 1 | 1 | 1 |
UmlInterfaces.UmlInterfaces(String,String,String,UmlElement) | 1 | 1 | 1 |
UmlInterfaces.addRealizationClass(UmlClasses) | 1 | 2 | 2 |
UmlInterfaces.getRealizationClassMap() | 1 | 1 | 1 |
UmlInterfaces.getType() | 1 | 1 | 1 |
UmlOperations.UmlOperations(String,String,String,UmlClasses) | 1 | 1 | 1 |
UmlOperations.addInParameters(Parameter) | 1 | 1 | 1 |
UmlOperations.getId() | 1 | 1 | 1 |
UmlOperations.getInputParameters() | 1 | 1 | 1 |
UmlOperations.getMyClass() | 1 | 1 | 1 |
UmlOperations.getName() | 1 | 1 | 1 |
UmlOperations.getReturnParameter() | 1 | 1 | 1 |
UmlOperations.getVisibility() | 1 | 1 | 1 |
UmlOperations.setReturnParameter(Parameter) | 1 | 1 | 1 |
UmlStateMachines.UmlStateMachines(String,String,String,UmlElement[]) | 1 | 6 | 8 |
UmlStateMachines.dealState(UmlElement,boolean,boolean) | 1 | 14 | 20 |
UmlStateMachines.getDifferentIdFinalStateCount() | 1 | 1 | 1 |
UmlStateMachines.getDifferentIdInitStateCount() | 1 | 1 | 1 |
UmlStateMachines.getId() | 1 | 1 | 1 |
UmlStateMachines.getName() | 1 | 1 | 1 |
UmlStateMachines.getRegionId() | 1 | 1 | 1 |
UmlStateMachines.getStatesGetByNameMap() | 1 | 1 | 1 |
UmlStateMachines.getStatesHashMap() | 1 | 1 | 1 |
UmlStateMachines.getStatesNameCountMap() | 1 | 1 | 1 |
UmlStateMachines.getTransitionHashMap() | 1 | 1 | 1 |
UmlStateTransition.UmlStateTransition(UmlElement) | 1 | 1 | 2 |
UmlStateTransition.getAimStateId() | 1 | 1 | 1 |
UmlStateTransition.getId() | 1 | 1 | 1 |
UmlStateTransition.getName() | 1 | 1 | 1 |
UmlStateTransition.getPreviousStateId() | 1 | 1 | 1 |
可以看到除了顶层类(UmlStateMachines、UmlClasses、MyUmlGeneralInteraction)需要较多关联之外,其余类的复杂度都控制在一个比较合理的范围内,所以在设计架构上具备了较好的鲁棒性
四个单元中架构设计以及对OO理解的演进
第一单元:表达式求导
第一单元自己显然还没有做好充足的准备(其实是还没做好开学的准备),刚开始连git都用不顺55555,前两次作业难度非常小,所以都顺利过关没有出现WA的情况,但是现在回去看看前两次作业的代码简直无法直视,一个类莽到底的那种,所以我在第三次作业就很顺利地翻车了。
但是从对OO的理解上看,第三次作业已经初具雏形了,从因子、项、表达式,这些层次化的东西,求导接口等等抽象化的东西,都在慢慢地体现面向对象的思维,而且现在看起来,第三次作业的类递归向下和我在最后一个单元的思想相近。
第二单元:多线程电梯
第二单元的多线程我们大多数人是第一次接触,多线程设计也是OO课的一大难点,不过所幸这时我已经开始适应了OO的节奏,而且多线程对于面向对象层次化设计也提出了更高的要求,如果不能够合理安排好线程类的实现,那么多线程一旦运行起来将会变得一团糟。如果说第一次作业只是开胃菜,那么后面两次作业都需要在线程安全、数据投放组织等方面下很多功夫。
第二单元从正确性上看我做的还是不错的,三次作业没有出现WA,但是不可否认,多线程我们训练的还不够多,这个单元做的也只能算是比较基本的。
第三单元:JML规格化设计
第三单元总体来说是比较轻松的(从代码实现的角度),但是也蕴含了不少OO思想,封装数据容器并统一管理,这就是path和pathcontainer;封装数据结构,在本单元最后一次作业中封装图结构并实现求最短路的接口,这样能使得代码非常清爽。当然最重要的还是帮助我们学会了一门非常严格的Java规格化语言。
第三单元后两次作业都顺利没有出现任何错误,但是第一次作业由于自己的一点点小疏忽理解错了一个概念,导致强测直接炸了,只得了60分,这次作业之后我就养成了“迫害妄想症”,同时也加强了对自己代码的测试工作,所以在后面的作业之中我也没有再出现任何问题。
第四单元:UML模块
第四单元我们要完成的是对UML各种图的解析工作,而每种元素,比如类、属性、方法、关联、关联对端等等都在提醒我们面向对象的思想,对每种元素单独建模,再合理地组织每种元素的关联,这就是第四单元的工作。
在第四单元,我其实是没有过多的关注讨论区的,一直都尽力使得我的代码能够支持所有UML能画出的图,所以我支持了多继承、支持了类继承接口等等很多并不会出现的情况,虽然事实证明我写的代码很大一部分都是没什么作用的,但是我觉得这真正锻炼到了我的代码能力,最后一次作业总共加起来有两千余行代码(如果不考虑这些情况,我觉得一千行左右绰绰有余),我觉得这也算实现了以前进入学院时说的“OO之后,你们要具备一周完成千行以上有效代码的能力”
四个单元对测试理解以及实践的演进
第一单元:自动生成数据+对拍
第一单元的测试过程,指导书进行了详细的解释,而我们显然也可以依据指导书的测试过程搭建自己的对拍器。对拍简单粗暴,直接构造样例运行程序并对比,能直接发现是否存在问题,但是显然不能够定位问题。第一单元中我实现了Python构造样例+Matlab计算+Bat批处理衔接、对比。Python将表达式生成并输出到文件,bat将文件输入到matlab脚本和jar中,并将结果对比。这个测试过程也是对新的知识的学习,不过之后由于OS使用更多的是bash指令,所以我在后面使用更多的还是bash指令进行粘合。
第二单元:利用Python的time库进行多线程精准投放记时
第二单元也用到了较多的对拍测试,但是和第一单元有着天壤之别的是多线程的输入必须精准投放,很多同学出现的“本地正确评测机错误”就是由于手动输入太慢导致线程安全执行,所以在这里我们需要精准的记时,这里就使用到了Python的subprocess操作命令行库以及time计时库,其实time库的计时精度也不算高,但在本单元作业中完全够用,如果想要较高精度的计时,我们还需要依赖一些Python的第三方库。可以说前两个单元的测试极大促进了我们对其他语言的学习以及实践,扩展了我们的视野和知识面。
第三单元:利用JUnitNG、SMTSolver进行自动化检测
第三单元学习的是严格的规格化设计语言JML,所以它自然也会有配套的测试工具,不然何以体现JML的优越?在第三单元的测试中我们就能使用JML来进行样例自动生成以及像评测机那样带来直观的测试,但是比较遗憾的是OpenJML对我们课程内使用的JML支持不是特别好,诸如\foreach、\exists等语句都无法进行解析,这是一个遗憾。
第四单元:JUnit测试
第四单元由于依然采用实现课程组提供的接口的方式,所以依然非常适合使用JUnit来进行单元测试,当代码测试覆盖率非常高的时候,我们基本也能够保证自己代码的正确率。同样当自己的程序能够支持更多UML图时,我们构造样例也能更加轻松自由。
课程收获
- 通过一学期的代码练习,我的程序设计能力得到了极大的提升,虽然现在从自己的直观感受看,总觉得没学到啥特别厉害的玩意儿,就和计组一样,结束之后觉得自己就做了个支持中断的CPU,但是回头想一想,在开始学逻辑门的时候,我想都不敢想CPU是长什么样的。OO也是如此,我们使用的java和大一使用的C/C++有共通之处,算是有一定基础,但是我在学习OO以前都是一个文件莽到底,也不敢想象自己有能力写出这样的project。
- 不仅仅是设计层面,OO对以前学过的算法也是一次凝练熟悉的过程,在学习数据结构的时候,我对很多算法的理解还不是很到位,但是在OO的学习过程中,我弄懂了很多之前不是很熟悉的最短路算法,甚至也能自己构思一些比较奇怪的算法出来,所以OO给我一大感受,就是熟能生巧。
- 到目前为止,OO可能是最接近我们将来工作、最接近现代软件工程的一门课程,因为java在现代工程中的普及,所以我相信未来我会很感谢OO这门课给我这个机会去熟悉java,熟悉架构设计。研讨课中邀请到的几位IT公司BOSS的讲座也给我带来很大的触动,对未来的学习之路也有了更深刻的思考。
对课程的改进建议
- 首先在开学前我觉得应该让我们更加熟悉课程工具的使用以及课程规则,可以对git的用法出一些题目,来促进我们早点进入课程的节奏中,
我第一次实验就因为没用ssh,总是交不上去。555555同时希望能图文并茂的介绍一些课程规则,在github中最初发布的规则介绍文档我个人认为还不是特别完善,所以刚开学时候有点无所适从(当然后面就适应了),甚至可以把寒假预习的几次作业放在课程网站里面让我们事先体验一下完整的流程,这样应该能起到更好的效果。 - 其次是关于课程内容的一些建议,我们是不是可以尝试做一些更具有表现力的东西?比如做个游戏?因为我们一直在经历这种“对着黑框框输入文字输出文字”,所以我觉得是不是能换换鲜?当然我觉得这比较困难23333,因为这样势必涉及到教学计划的改变和难度的增加。不过如果OO有了这些内容,那么我们的学习乐趣和学习满足感绝对能提升的。
- 最后是关于课程网站的建设,其实学期中也有很多同学提了建议,可以完善讨论区支持修改帖子?可以支持我们自行测试样例?and so on.....
最后,感谢OO这学期的陪伴,这是一段艰辛、难忘、而又硕果累累的旅程。感谢老师助教们的付出,希望OO能越来越好!