一、本单元架构设计
如类图所示,各个类之间的关系一目了然,类与类之间几乎是完全模仿mdj文件的树形结构,层次化设计。官方包中已有的Umlxxx
类,仅作为Myxxx
类的成员变量出现。
各个Myxxx
类中,除存有Umlxxx
类、下级Myxxx
类对象和相关的数据结构外,仅包含该类对应元素自身的查询方法,不存也不访问其他的、同级Myxxx
对象。比如MyClass
对象不能访问其他MyClass
、MyInterface
等类的对象。
顶层MyUmlGeneralInteraction
类负责构造类之间的树形关系,实现官方接口中的抽象方法,只负责各个查询方法中较为宏观的部分,负责协调多个同级Myxxx
类间的查询。比如getClassAttributeType
方法,顶层类只负责循环遍历找到所有父亲MyClass
对象(获得父类id也是靠MyClass
中的getParentId
方法,因只有顶层类存有所有MyClass
的总表),并检查类型的正确性。对每个Class
中的查询逻辑则在MyClass
类中。
如此设计的优点在于,各个元素模型之间关系十分清晰,使得查询逻辑有效分散与解耦,易于实现正确性检验。
缺点在于
- 构建类之间的树形关系十分麻烦,若mdj文件出现树形结构上的改变,则代码修改起来也较为困难。
- *类的逻辑较为复杂,该类中保存了所有
Myxxx
类对象的引用,且存在MyXXX
类对象引用存储了两遍的情况,比如MyOperation
类的对象引用在MyClass
和MyUmlGeneralInteraction
*类中都有。 - 在原本的mdj文件的
Class
元素中,Association
、Attribute
、Operation
等应该是平级的,且这些元素有共同的抽象父类UmlElement
,便于使用数据结构进行存储。但在我将Association
等封装为MyAssociation
,而同时Arribute
并未封装,这会出现明明是同级元素却拥有不同父类,十分不便于使用统一的数据结构进行存储。
在数据结构的使用上,我还有个缺点。比如在MyClass
类中,对于存储MyAssociation
、MyOperation
等元素的各个ArrayList
,不应当是互相独立的、靠容器名来区分其内容的不同。而是应当建立一个这些MyXXX
类的公共接口,设置一个HashMap
,其key
为ElementType
,其value
为对应MyXXX
对象 向上转型接口的ArrayList
。这样即可通过ElementType
直接得到对应的ArrayList
。不是向上找代码,一行行看存某个类型元素的容器是哪个,再根据容器名访问,这显然是个很失败的设计。
由于顶层MyUmlGeneralInteraction
类的构造过程较为复杂,代码量很大,最终导致该类超长,理论上应当将构造过程移出去作为一个新类,也算是将构造逻辑和查询逻辑深度解耦了。
二、总结
- 写代码、容器使用更加熟练了
- 学会写代码前先想怎么搭架构、会考虑扩展性了
- 学会了先把方法声明写好,最后再填写方法内的内容
- 第1、2单元的时候还要强迫自己往层次化设计构思,到第4单元,层次化架构已经是直觉了
- 构思架构的时候学会去查查有没有现成的设计模式
- 学会了控制线程安全的基本方法
- 学会使用一些代码分析、建模工具
- 托第一单元的福,正则表达式和递归用的是越发熟练了
- 学会看类图、顺序图、状态图了
三、建议
- 建议在每个大项目的合适时机给出一些架构上的提示,并在项目开始就指出一些十分糟糕的架构,而不是到最后项目写完了才跟同学讲什么架构有什么优点。学生中的大佬毕竟是少数,许多学生会因为完全不懂而写出屎一样的架构(关于架构的提示太少了),结果就是按照这屎一样的架构撑过了三次作业,完全没有锻炼效果,到最后优秀的架构也没实现,只是听老师讲了一下。
- 务必优化一下UML单元的指导书,明确语义,建议参考评论区同学们问的问题来完善指导书。因为指导书的描述不清而导致猜谜语一样的写代码,实在太痛苦,且是在浪费时间。