OO学习总结(一)
一、 程序结构分析
1. 第一次作业:多项式计计算
本次作业我只写了两1个类,即polyCompute。类中共4个方法,平均每个方法26行,但最大达到了77行。也就是说方法规模还应进一步控制。类的总代码规模150行。
lack of cohesion of methods值为 0.75,也就是说类的内聚度不够高。改: 将类的result属性改为某个方法的局部变量,然后将变量传给printf()方法,进行打印。
另外,在getData()方法中融合了对格式的判断。改:将格式判断单独写一个方法或者类。
2. 第二次作业:单部傻瓜式电梯
Elevator类 | |
属性个数
|
6 |
方法个数 | 6 |
方法平均规模 | 7.6行 |
类的总代码规模 | 69行 |
Lack of cohesion of methods | 0.86 |
由于Elevator类的属性大多是提供给调度器查询的,所以内聚度不高。但该类的方法规模控制得比较小。
Floor 类 |
|
属性个数 |
2 |
方法个数 |
1 |
平均方法规模 |
26 |
类的总代码规模 |
35 |
Lack of cohesion of methods |
0 |
Floor类只有一个方法,出现了各个类职能分配不均的情况。在本次作业中,Floor类主要功能就是形成一个楼层请求,因此这个缺陷似乎无法避免。
Request 类 |
|
属性个数 |
4 |
方法个数 |
6 |
平均方法规模 |
2 |
类的总代码规模 |
31 |
Lack of cohesion of methods |
0 |
Request类主要定义了请求的一些属性,其方法都是属性的getter方法。
Schedule 类 |
|
属性个数 |
2 |
方法个数 |
5 |
平均方法规模 |
4.4 |
类的总代码规模 |
38 |
Lack of cohesion of methods |
0.5 |
Scheduler 类 |
|
属性个数 |
3 |
方法个数 |
3 |
平均方法规模 |
11.6 |
类的总代码规模 |
48 |
Lack of cohesion of methods |
0.5 |
整个项目的规模是272行,平均一个方法8.4行,最大方法规模45行,与上一次相比减少了30行。平均Lack of cohesion of methods为0.43,与上一次作业相比有了一些提升。块嵌套深度平均1.7,几乎是第一次的3一半。不足的地方在于类的职能分配不均,类的内聚度虽有提高,但也不够理想。
类图:
除Request类外,其余类都在运行过程中会用到Request类,所以都和该类有依赖关系。
Scheduler拥有Elevator和Schedule,所以和这两个类有关联关系。
3. 第三次作业:可捎带电梯
Elevator类 |
|
属性个数 |
5 |
方法个数 |
12 |
平均方法规模 |
4.75 |
类的总代码规模 |
91 |
Lack of cohesion of methods |
0.74 |
Queue类 |
|
属性个数 |
2 |
方法个数 |
8 |
平均方法规模 |
3 |
类的总代码规模 |
46 |
Lack of cohesion of methods |
0.5 |
Queue类 |
|
属性个数 |
8 |
方法个数 |
12 |
平均方法规模 |
1.75 |
类的总代码规模 |
57 |
Lack of cohesion of methods |
0.45 |
Running 接口 |
|
属性个数 |
0 |
方法个数 |
3 |
平均方法规模 |
0 |
总代码规模 |
6 |
Lack of cohesion of methods |
0 |
在Running接口里定义了电梯的运动方法,包括上下楼和开关门。
ALScheduler类 |
|
属性个数 |
1 |
方法个数 |
13 |
平均方法规模 |
8.7 |
总代码规模 |
192 |
Lack of cohesion of methods |
0 |
ALScheduler继承自Scheduler类,重写了调度方法。内聚度提高了,方法规模下降了。
Storey类 |
|
属性个数 |
2 |
方法个数 |
1 |
平均方法规模 |
26 |
总代码规模 |
34 |
Lack of cohesion of methods |
0 |
楼层类主要还是用于形成楼层请求。
类图:
这一次作业的类图比上一次复杂很多。造成这种状况的原因在于类之间相互引用太过繁杂。Scheduler类和ALScheduler类几乎贡献了一半的“关系”,而Storey类依然只和Request类间存在依赖关系。第三次作业的平均内聚度相比第二次有所提高,总代码规模470,主要的开销用于描述调度器的捎带功能。平均块嵌套深度1.4。本次作业调度器增加了新功能,导致调度器的代码量和方法数都较多。或许可以考虑将调度器中打印电梯停靠信息的功能移至楼层类中,这也符合现实情况。
二、 分析自己的bug
1. 第一次作业:多项式计算
本次作业公测未发现bug,互测发现一个bug。主要问题出现在对输入字符串的的解析上。没有利用正则表达式的特性,导致程序解析过程中有很多if,while等分支,使得解析逻辑异常复杂,结构相当臃肿。
学习java正则表达式:http://www.runoob.com/java/java-regular-expressions.html
2. 第二次作业:单部傻瓜式电梯
公测未发现bug,互测未发现bug。第一次作业之后去学习了java的正则表达式用法,明显减轻了本次作业解析字符串的工作量,同时正确性也得到了保障。
本次作业问题表现在将过多的职能给了调度器类,而楼层类、电梯类都未能很好地分担工作。
3. 第三次作业:单部可捎带电梯
公测未发现bug,互测发现1个bug。但互测的bug是由于对方输入有误导致的,并不是程序上在这一点上出了问题。
这次作业为电梯增加了四个方法,分别是上楼、下楼、开关门和形成主请求。也就是说将调度器中这一部分职能转移到了电梯中。调度器只负责请求的调度和同质请求的过滤。但由于本次要求能够捎带同向请求,所以调度器的代码量还是有相应的增加。
另外,在写代码的过程中发现,新的ALScheduler类继承原来的Scheduler类,但几乎要重写所有的代码。也就是说原设计的可扩展性和可维护性并不高。我觉得这一点问题出现的原因主要是原Scheduler类中的方法调用了其他类的方法,一些代码只是从逻辑上得到了相应的结果,而没有注意功能的独立性。
三、 分析别人的代码。
拿到别人写的代码,倘若有注释还好,若整个项目无一行注释,变量命名又无规律可循,满篇int a, String b之类的属性,的确头疼。但不管怎么,要尽可能去理解别人代码的逻辑,我一般会把对方的代码略读一遍,形成一个大概的框架。
然后是阅读对方的README,分析是否与实验要求有出入,若是否写地方已经体现出来逻辑漏洞,则可根据自己的观察构造相应样例进行检测。
若README写得条理清晰,无漏可查,我会再次阅读对方的代码。先随便构造一个稍微复杂的样例,输入后对其代码进行单步调试,借此理解其代码的内在关联。一边观察每一步的输出,一边可记下可能有问题的地方,稍后会根据自己的记录构造样例进行检测。
在我自己写代码的过程中也不可避免地会遇到没考虑完全的情况,也就是发现了自己的bug,我会作详细的记录bug情况以及当时发现bug的用例。在测试别人代码的时候当然也会用这些样例进行检测。
若直到这一步依然无法发现bug,我才会根据分类树进行全面的测试,并利用python构造随机样例进行筛查。
四、 心得体会
- 尽可能保持模块的独立
- 尽可能少用public属性,以减少数据共享的情况
- 方法的规模不应太大(30-50行以内),否则必出bug。
- 类的职能分担应尽量均衡。
- 多与同学交流,大家对问题的思考肯定有不同的地方,交流一方面可以学习别人的思想,一方面可以检查自己的bug。