面向对象构造与设计第一次总结
第一次作业:多项式运算
第一次作业是一个简单的多项式计算,然而对于完全没有接触过面向对象甚至java语言的我来说并不轻松。好在经过一个星期的恶补java语言,我最终还是写出来了一个假面向对象的多项式运算java程序。
类图:
由类图可以看出该程序结构简单,Tuples类中只有一个将字符型的多项式转化为二维数组的方法,而所有对数据的处理和管理都在主类中进行。这两个类共同处理公共的多项式数据,导致每个类的职责不明确,不具有自包含性。好在每个类中的方法的分工职责比较明确,没有出现单个方法规模过大的问题。
Bug分析:
这次程序唯一的bug在于正则表达式的一个小错误,数字位数上的限制不正确导致不输入数字也能通过正则匹配。
第二次作业:单部电梯(FAFS策略)
这一次作业对面向对象的要求高了很多。先从类图开始分析。
类图:
大致思路如下:主类的三个方法依次为读入数据、检查数据合法性以及报告错误;主类读入数据之后调用Manage类,后者的process方法通过对下层的四个类的方法调用,对数据队列进行处理并输出。电梯类(Elevator)存有电梯运行状态的属性,和每层的请求情况,以及查看、修改这些状态和请求的方法;楼梯类(Floor)同样存有每一层的请求情况和查看、修改这些请求的方法;请求队列类(RequestQueue)中唯一的属性是请求队列,类中有对队列元素操作和检查同质请求的方法。请求队列中的每一个元素都是请求类(Request)的实例,每个请求拥有类型、楼层、方向、时间四个属性和获得这些属性的方法。
从类图中可以看出我最大的问题在于Manage类只有一个方法,而这个方法的用途包含了遍历请求列表,处理电梯状态等。其次我将计算电梯状态和输出电梯状态放在了一个方法中。这些设计导致代码耦合性太高,逻辑不清晰。同时第一次作业中暴露的问题仍然存在,类和类之间并不独立。
从OO度量方面分析:
可以看到在主类和请求队列类中的块嵌套深度偏大,还需注意减少嵌套深度。
Bug分析:
本次程序没有功能性Bug,唯一的Bug出在忘了加#号的输出错误。。。然而由于类之间分工不明确,为后续第三次作业买下了很大的隐患。
第三次作业:单部电梯(ALS策略)
由于第二次作业中类之间关联过高,导致我在这次作业中吃尽了苦头,不仅将第二次的代码大幅度更改,还使得逻辑更加混乱复杂。总体上来来说这一次程序非常糟糕,甚至在功能性上都存在一定问题。下面着重分析存在的一些问题。
类图:
同样先从类图入手。这次存在的问题较多,很多也是在前两次中就存在的问题:
- 类之间关联性太大。ALS调度类不仅无法继承原有调度类,更无法使用原来的其它类。很无奈我只能重新构造电梯类、楼层类,并在请求队列类中增加了许多冗余的方法来计算运动状态。
- 具有相似逻辑的代码段存在重复。原先判断同质请求的方法由于数据结构上的问题无法使用,无奈我又重新写了一个方法两者并用;执行主请求的方法和执行捎带请求的方法上也有高度相似性,但是由于没有设置参数区分主请求和捎带请求,使两种方法没有能够合并。
- 类的职责分工不明确。绝大部分工作都由请求队列类完成,导致该类非常庞杂,也需要调用到很多其他的类和方法,整个结构看起来十分笨重,不利于维护和扩展。
从OO度量方面分析:
该图说明了请求队列类(RequestQueue)的圈复杂度过高,这也就意味着代码难以测试维护,程序可能出现错误的几率很大。也印证了类图分析中请求队列类过于复杂的问题。要解决此问题,必须将类的分工明确细化,结构合理化,将部分对请求处理的方法转移到其他类中,而该类中只保留对队列基本操作的方法。
Bug分析:
这一次作业出现了功能性Bug,在计算捎带的表达式上出现致命问题,最后挂了五个有关捎带测试分支。
互测心得
- 首先对程序的输入进行分析,观察代码中存在的漏洞和边界。
- 再对核心计算的代码研读,找到算法中的逻辑问题。
- 最后看一下程序的数据结构,看一下是否存在结构不合理使得程序出现崩溃等问题。
- 能够做到这三点都没有错误的大佬,就已经是完整的设计了。
总结
经过这三次面向对象编程实践,我对面向对象有了些具体的理解,但仍然不够深入。总的来说,有以下几点值得注意:
1、在拿到任务之后,不要急于敲代码、开始构建程序,这样做只会使得程序面向过程、调理不清晰。在拿到指导书之后,首先要仔细阅读。在对指导书的要求有了充分理解之后,再对整个程序的结构设计构思,用自顶向下的方法逐层分析需要哪些类,每个类的作用是什么。
2、将程序功能"均衡"分配给多个类。随着程序不断复杂,所需要的类和类的方法也在不断增多,此时应避免出现某个类统管全局或者完成大部分功能,优秀的面向对象程序是类玉类之间相互协同完成任务。
3、千万别拖到最后两天才开始着手写代码,就算你之前构思再久,就算你熬夜再晚,Bug照样满天飞。sorry,Bug就是可以为所欲为。