2019年北航OO第4单元(UML)总结
1 架构设计
经过了接近一学期的程序设计训练,在这一单元的第一次作业中我就非常注重架构的设计,竭力避免像之前一样陷入“第一次作业凑合,第二次作业重构”的不健康的迭代模式。整体上来说,我对我本次作业的架构还是很满意的。废话不多说了,直接上类图:
从类图也可以看出来,整体的架构非常工整。MyUmlGeneralInteraction
类是整个程序的中心,负责实现接口UmlGeneralInteraction
的全部方法,以及输入的读取和分配。它下面所属的三个类是ClassModel
, StateModel
和CollabModel
,分别是UML类图、UML状态图和UML顺序图的管理类。最下面一层的类是以Res
开头的,分别对应相应的UmlElement,如ResClass
对应的是UmlClass
,ResInter
对应的是UmlInteraction
等等。这些底层类储存的数据不仅包含相应的UmlElement中的属性,还有相应的用于和其他类相关联的数据。以ResItf
(对应的是UmlInterface
)为例,其中的属性包括id
, name
, HashSet<ResItf> parents
, HashSet<ResItf> allParents
,后两个分别是该接口的直接父接口集合以及所有祖先接口集合(用HashSet存是因为Java支持接口的多继承)。这个类的方法也是为上述的数据服务的。除去getters和setters以外,还有一个更新方法updateAllParents()
,其作用是确保通过parents
属性来递归地找出全部的父类,并放到allParents
里。ResItf
的代码框架如下图:
最后一个需要指出的类是DirectedGraph
,它是一个单独的进行图运算的类,封装了建图方法和相应的图算法,作用和上一单元中的图运算类相似。这个类是第二次作业中新加入的,加入的原因是pre-check的相关操作是基于有向图的,而图结构在其它方法中又没有用处,所以需要独立出来,避免和其它类形成无意义的高耦合。DirectedGraph
类的代码框架如下图:
程序运行时,首先通过MyUmlGeneralInteraction
类对输入进行分配:实例化它下面所属的三个类之后,对于类图的输入,分配到ClassModel
;对于状态图的输入,分配到StateModel
;对于顺序图的输入,分配到CollabModel
。至于接口方法的具体实现,只需要调用相应类里面的同名方法即可,具体的方法逻辑放在下面三个类中去实现。
2 总结自己在四个单元中架构设计及OO方法理解的演进
2.1 架构设计的演进
这学期其实是我第一次真正意义上的运用OO方法到我自己的程序中,因此我能清晰地感受到入门的过程。第一阶段是拒绝OO方法,仍然待在自己的comfort zone里。在第1单元的第一次作业中,我还是习惯性地用以前所熟知的面向过程的思路设计程序。虽是在Java语言中,可是只有一个类,所有的方法都堆在里面,自然也没有什么逻辑分层和功能划分。
第二阶段是愿意去尝试,但是不得要领。具体来说就是知道要用OO方法将问题结构化,但是不知道怎么将需求转化为Java语言中的类。有时在具体写方法时才意识到有些数据应该放在一个类中的,于是又得推到重来;有时程序全部完成后才发现其实某些类里的某些数据是完全没有关系的,其实应该分成两个类单独处理……总之,这一阶段算是在摸索和不断试错中艰难前进的。
第三阶段是终于可以自如地运用OO方法设计出合理的架构。具体说来就是先建类和类里面需要的方法壳子,方法的内部实现以后再回来写,类里的属性也可以依照需要随时添加。这种自上而下的设计+编程方法可以兼具架构和代码框架,同时也还算灵活(如果发现架构有问题也不会做无用功),算是这一学期我自己探索的成果。我认为这一单元的两次作业就是很好的例子,详细的架构设计在上一节已经介绍了,在这里不再赘述。
2.2 OO方法的演进
这一学期的四个单元分别有四个主题。第一个主题其实算是一个Java引言,通过多项式求导这个任务让大家熟练Java语言,理解面向对象的思维方式和设计方法,并适应逐步迭代的需求变化。第二个主题是多线程程序,具体的任务则是多部电梯调度,目的是锻炼编写多线程Java程序的能力,更重要的是搞清JVM在进行多线程调度时的机制和原理,从而才能更好地使用锁来确保数据的一致。第三个主题是JML及程序规格,具体的任务是根据JML规格撰写Java代码,目的是让大家不能一设计好程序框架便一头钻进代码细节中,而是应该捋清方法的内部逻辑、权利和义务。第四个主题是UML,具体的任务是解析UML图,目的我认为是让大家从一个更高的视角来看待程序结构,进一步弱化Java代码细节,而将注意力集中在程序架构设计上。这四个主题相对独立,但是同时也是能够串联成一个整体的。经过了四个主题15次编程和博客作业的训练,我认为我已经对于Java语言以及基本的OO方法有了全面的了解。
3 总结自己在四个单元中测试理解与实践的演进
测试这个环节其实是和架构设计同等重要的,而且它们都属于在课堂上老师不会具体讲到的知识,需要通过练习和思考才能够熟练。
最开始时的我进行的测试其实是比较原始的,只是盲目地在输入空间里乱射,试图去覆盖到所有可能的边界。这样做的缺点是有很多无意义的、多余的测试样例,即这个样例的覆盖面被其它一个或多个样例包含在内了;而且,缺乏条理的测试也几乎不可能覆盖到所有分支,使得测试的目的没有百分之百达到。
当前我的测试方法就更加合理了一些,我大体上通过整体+局部的方法进行测试。整体上是根据输入的特征(比如在第四单元中,按查询指令的类别来划分输入)有目的地去覆盖每个大分支和边界情况;局部则是指针对每个类甚至是每个方法分别进行细致的测试。通常这些类和方法通常是逻辑比较复杂、代码量比较大、不容易在整体测试中覆盖全的。在对这些实体进行测试时,我认为不能完全遵从契约设计的规范,即想当然地认为输入具有某种约束和限制。有时候虽然这个方法的代码没有问题,但是其他地方的bug会导致错误的输入被传播到这里。换一种方式来说,要做到同一个错误不仅仅只能在一个地方才能检查出来并报错,要争取让更多的类和方法在遇到这个错误时都能够报错,这也是我对于程序鲁棒性的一种理解,我想。
我认为对我来说今后仍旧需要进一步锻炼和改进的地方是自动化测试。虽然我现在的测试方法相对来说很合理,但是就时间上来说并不高效。其中,撰写测试样例倒并不是最麻烦的,思考其实占据了相当大的一部分时间。我想通过自动化的程序生成测试用例似乎是一个省时省力的办法,不过还不是很清楚如何让这样自动生成的测试做到准确和全面,这也是我在以后需要学习和探索的。
4 整体课程收获
这一学期的OO课程下来,我认为有相当多的成果和收获,而且更重要的是这些收获不仅仅是局限于面向对象相关知识的,而是方方面面的。首先最直观的就是编程能力的提高。截止这一学期开始的时候我做过的最庞大的项目是在编译原理实验课上的两三千行代码量的编译器,而在这一学期有的项目自己就是近千行代码量的工程,而这仅仅是一周的project。纵观整个学期,总代码量已经到达了万行数量级。现在我能明显感觉到代码的可靠性相比于上学期甚至学期初都有了显著的提高,出错的情况更少了,可读性也有所上升,不像之前的代码一样过若干个月已经看不懂自己当时的思路了。
第二个收获是架构设计上的,如上文所提到的,我认为现在自己的设计更加逻辑清晰,同时对需求的更新和迭代也更加友好。这一点,老师在课堂上也曾经多次提到,在以后的工作中是很有帮助的一项技能,因为在实际的工程项目中需求不可能是一成不变而且是一次性全部交代的,必然会随着项目的发展增加、删减或修改,因此我们的程序也应该具有与之相匹配的特性。
第三个收获是面向对象式的思维方法。在这学期以前我接触的程序全部都是C风格的面向过程程序,即便在Python里有类的概念也是作为面向过程的一种辅助,而Java则是一个“一切皆对象”的语言,通过这门语言第一次接触到了完完全全的面向对象设计。起初我不是很能理解,也不是很能接受,但随着时间和作业的向前推进我现在能明白为什么面向对象是必要的,尤其是在复杂工程中。只有通过拆分数据和封装功能,才能在不失效率的同时写出高可靠性、高可读性的代码。曾经有人把面向过程比作编年史,而把面向对象比作纪传史,现在看来这个比喻是极为恰当的。
5 立足于自己的体会给课程提三个具体改进建议
- 个人感觉,理论课的内容有时候会有一点过于形而上学,和作业、实验的结合不是特别紧密
- 实验课没有任何形式的结果反馈,经常会心里没底,不知道自己作答得好不好,也不知道下次实验前应该做哪些准备
- 在学习JML部分内容时感觉很无力,网上几乎没有任何资料,相关IDE工具也很初级很原始(这一条尚不知道时什么原因造成的)
2019年北航OO第4单元(UML)总结的更多相关文章
- 2019年北航OO第1单元(表达式求导)总结
2019年北航OO第1单元(表达式求导)总结 1 基于度量的程序结构分析 量化指标及分析 以下是三次作业的量化指标统计: 关于图中指标在这里简要介绍一下: ev(G):基本复杂度,用来衡量程序非结构化 ...
- 北航OO第四单元——UML图解析
北航OO第四单元--UML图解析 作业要求简析 刚接触本次作业可能需要花上一会才能搞清楚到底是要我们写个啥,在这里简单说一下: UML图的保存格式.mdj文件是以json文件的形式存储的,将每一个Um ...
- 2019年北航OO第四单元(UML任务)及学期总结
第四单元两次作业总结 第十三次作业 需求分析 本次作业需要完成一个UML类图解析器,所需要解析的只有符合UML标准和能够在Java 8中复现的UML类图.查询指令存在两种:仅与所查对象有关的指令,以及 ...
- 2019年北航OO第三单元(JML规格任务)总结
一.JML简介 1.1 JML与契约式设计 说起JML,就不得不提到契约式设计(Design by Contract).这种设计模式的始祖是1986年的Eiffel语言.它是一种限定了软件中每个元素所 ...
- 2019年北航OO第2单元(电梯模拟)总结
1 三次作业的设计策略 经过了上一单元的训练,我也积累了一些设计策略上的经验.在这一单元的一开始,我便尽可能地把问题中的各个功能实体区分开来,分别封装成类,以便于随后作业中新需求的加入.与此同时,我也 ...
- 2019年北航OO第3单元(JML)总结
1 JML语言的理论基础及应用工具链 1.1 JML语言 Java建模语言(JML)是一种行为接口规范语言,可用于指定Java模块的行为.它结合了Eiffel的"契约设计(design by ...
- 2020北航OO第四单元总结
2020北航OO第四单元总结 一.本单元架构设计 本单元作业是实现一个UML图解析器,其中实现接口及主要框架课程组已经提供,只需要我们完成特定功能. 在第一次作业时,感到十分迷茫,不知道如何下手,最后 ...
- 2020北航OO第三单元总结
2020北航OO第三单元总结 本单元要求是根据JML规格完善代码,初看是一个简单的代码照搬实现的东西,但最后才发现由于CPU时间的限制,还考察了大量优化策略及数据结构中关于图的知识,是一次非常注重细节 ...
- OO第四单元(UML)单元总结
OO第四单元(UML)单元总结 这是OO课程的第四个单元,也是最后一个单元.这个单元只有两次作业,相比前三个单元少一次作业.而且从内容上讲这个单元的作业目的以了解UML为主,所以相对前三个单元比较简单 ...
随机推荐
- Koa Cookie 的使用
Cookie 简介 cookie 是存储于访问者的计算机中的变量.可以让我们用同一个浏览器访问同一个域 名的时候共享数据. HTTP 是无状态协议.简单地说,当你浏览了一个页面,然后转到同一个网站的另 ...
- Linux离线安装Docker
1.从官方下载Docker安装包并上传至虚拟机 https://download.docker.com/linux/static/stable/x86_64/ 2.解压安装包 tar -xvf doc ...
- Aspect切面的使用实例
一.导入切面库 以maven工程为例,除了springmvc基础的库,需要导入切面库,本例aspectj为例. <properties> <aspectj.version>&l ...
- Android : Camera HAL3的参数传递(CameraMetadata)
一.camera_metadata简介 Camera API2/HAL3架构下使用了全新的CameraMetadata结构取代了之前的SetParameter/Paramters等操作,实现了Java ...
- python爬虫中XPath和lxml解析库
什么是XML XML 指可扩展标记语言(EXtensible Markup Language) XML 是一种标记语言,很类似 HTML XML 的设计宗旨是传输数据,而非显示数据 XML 的标签需要 ...
- Node.js+Express框架+Mongo学习(一)第一个node.js实例
1.在桌面新建一个空的文件夹,比如叫node,当然也可以在其它地方新建. 2.命令行进入到所新建的文件夹的目录,下载Express框架,再在这个文件夹里新建一个叫final的项目 3.在项目(fina ...
- UI Automator 介绍
简介 Android 4.3发布的时候包含了一种新的测试工具–uiautomator,uiautomator是用来做UI测试的.也就是普通的手工测试,点击每个控件元素 看看输出的结果是否符合预期.比如 ...
- [LeetCode] 341. Flatten Nested List Iterator 压平嵌套链表迭代器
Given a nested list of integers, implement an iterator to flatten it. Each element is either an inte ...
- [LeetCode] 555. Split Concatenated Strings 分割串联字符串
Given a list of strings, you could concatenate these strings together into a loop, where for each st ...
- android基础---->SharedPreferences的使用
SharedPreferences 还支持多种不同的数据类型存储,如果存储的数据类型是整型,那么读取出来的数据也是整型的,存储的数据是一个字符串,读取出来的数据仍然是字符串.这样你应该就能明显地感觉到 ...