面向对象第一单元博客
第一次作业主要实现的功能为表达式的括号展开,然而自己最开始的思路却非常愚蠢,大致是是将表达式视为字符串,并直接对字符串进行修改。这种思路使代码异常繁琐且漏洞百出(原因可能是没看明白training),这里对最开始的思路也不赘述了,只是写下来,以示对自己的提醒吧QAQ。
第一次作业(修改)
(所以这里是第一次作业的正式部分!)
处理的思路与主流的递归下降解析大致相同,但是term并不是factor的集合,而是一些其他数据,类图如下
(这其实是第三次作业的类图,但是由于在编码过程中充斥面向过程的思维,使在后面的修改中几乎只是加入业务类,故不过多重复展示)
(其实是因为不想画了QAQ)
第一次实现功能为类图所展示的左半部分。输入后经过预处理之后进入Prase阶段,通过lexer来解析词法,并归类到不同的项中,最后调用Prase.toString()方法来输出。
这个版本修复了原始版本中各种各样的问题(如符号的处理,以及高次幂的展开问题)
第二次作业
第二次作业加入了三角函数和运算函数(求和与自定义函数)
虽然都是函数,但实际是两个维度的事物。对于运算类的函数,在解析阶段将其处理,化为表达式并存入term中的expr项(即图中的selfFunc和sumFunc)。对于三角函数,则是另行存储于term中。
在类图中则是体现为除了PraseForUse其他的所有类。(不过从名字也可以看出,对函数的解析是FoulishReplace,愚蠢的替换行为,而没有采用更加合适的对内容进行解析的方法。)
第三次作业
第三次作业是功能上的加深,而不是功能上的拓展,如果第二次作业以一个好的架构设计,其实第三次作业并不需要修改(但显然我不是)。
这次也仅仅加入了PraseForuse这个类,用于处理复杂的函数调用行为。
代码度量分析
类分析
Package Name | Type Name | NOF | NOPF | NOM | NOPM | LOC | WMC | NC | DIT | LCOM | FANIN | FANOUT |
---|---|---|---|---|---|---|---|---|---|---|---|---|
definefunc | Foulish | 1 | 0 | 3 | 3 | 41 | 7 | 0 | 0 | 0.666666667 | 1 | 0 |
definefunc | Selffunc | 3 | 0 | 5 | 5 | 79 | 18 | 0 | 0 | 0 | 6 | 6 |
definefunc | Sum | 3 | 0 | 3 | 3 | 65 | 11 | 0 | 0 | 0 | 2 | 5 |
expr | Expr | 1 | 0 | 4 | 4 | 24 | 6 | 0 | 1 | 0 | 7 | 1 |
expr | Term | 5 | 0 | 7 | 7 | 111 | 21 | 0 | 0 | 0 | 3 | 4 |
factor | Factor | 0 | 0 | 1 | 1 | 3 | 1 | 4 | 0 | -1 | 2 | 0 |
factor | Num | 1 | 0 | 2 | 2 | 9 | 2 | 0 | 1 | 0 | 1 | 0 |
factor | PowerFunc | 1 | 0 | 2 | 2 | 17 | 4 | 0 | 1 | 0 | 1 | 0 |
factor | Trifunc | 3 | 0 | 2 | 2 | 30 | 5 | 0 | 1 | 0 | 2 | 4 |
(default package) | MainClass | 0 | 0 | 2 | 2 | 45 | 8 | 0 | 0 | -1 | 0 | 4 |
praseforuse | Praseforuse | 1 | 0 | 2 | 2 | 44 | 7 | 0 | 0 | 0 | 1 | 4 |
src | Lexer | 3 | 0 | 7 | 3 | 135 | 31 | 0 | 0 | 0 | 6 | 0 |
src | Parser | 1 | 0 | 4 | 4 | 95 | 21 | 0 | 0 | 0 | 6 | 10 |
**LCOM **(Lack of Cohesion in Methods – Class)
方法的内聚缺乏度。值越大,说明类内聚合度越小。
FANIN (Fan-in – Class)
类的扇入。扇入表示调用该模块的上级模块的个数,扇入越大,表示该模块的复用性好。
**FANOUT **(Fan-out – Class)
类的扇出。扇出表示该模块直接调用的下级模块的个数,扇出过大表明模块复杂度高,但扇出过小也不好。
设计要求一般是高内聚低耦合,即LCOM值要小,FANIN值要大,FANOUT值要合理。
观测这几个指标觉得似乎还,可以?(没有找到具体的定量分析指标诶)
不过也可以看出,Foulish这个类真的挺符合他的名字的。
方法分析
Package Name | Type Name | Method Name | LOC | CC | PC | Line no |
---|---|---|---|---|---|---|
definefunc | Foulish | Foulish | 3 | 1 | 1 | 9 |
definefunc | Foulish | toString | 3 | 1 | 0 | 13 |
definefunc | Foulish | foolishRepalce | 32 | 5 | 0 | 18 |
definefunc | Selffunc | Selffunc | 3 | 1 | 0 | 30 |
definefunc | Selffunc | addFunc | 6 | 2 | 1 | 34 |
definefunc | Selffunc | parseFunc | 28 | 6 | 1 | 41 |
definefunc | Selffunc | getTarget | 8 | 3 | 1 | 81 |
definefunc | Selffunc | preOperate | 29 | 6 | 1 | 90 |
definefunc | Sum | Sum | 10 | 2 | 1 | 16 |
definefunc | Sum | getSumExpr | 21 | 3 | 1 | 28 |
definefunc | Sum | preOperate | 29 | 6 | 1 | 54 |
expr | Expr | Expr | 3 | 1 | 0 | 10 |
expr | Expr | addTerm | 3 | 1 | 1 | 15 |
expr | Expr | getTerms | 3 | 1 | 0 | 19 |
expr | Expr | toString | 12 | 3 | 0 | 23 |
expr | Term | Term | 7 | 1 | 0 | 18 |
expr | Term | Term | 14 | 1 | 2 | 26 |
expr | Term | getPorm | 8 | 2 | 0 | 46 |
expr | Term | setPorm | 5 | 2 | 1 | 54 |
expr | Term | addFactor | 16 | 5 | 1 | 60 |
expr | Term | toString | 17 | 3 | 0 | 75 |
expr | Term | toTest | 37 | 7 | 0 | 94 |
factor | Factor | toString | 0 | 1 | 0 | 4 |
factor | Num | toString | 3 | 1 | 0 | 8 |
factor | Num | Num | 3 | 1 | 1 | 12 |
factor | PowerFunc | toString | 11 | 3 | 0 | 5 |
factor | PowerFunc | getIndex | 3 | 1 | 0 | 14 |
factor | Trifunc | toString | 8 | 2 | 0 | 16 |
factor | Trifunc | Trifunc | 17 | 3 | 2 | 24 |
(default package) | MainClass | main | 14 | 2 | 1 | 21 |
(default package) | MainClass | preOperate | 29 | 6 | 1 | 39 |
praseforuse | Praseforuse | Praseforuse | 3 | 1 | 1 | 13 |
praseforuse | Praseforuse | analyze | 38 | 6 | 1 | 17 |
src | Lexer | Lexer | 4 | 1 | 1 | 8 |
src | Lexer | getNumber | 12 | 3 | 0 | 13 |
src | Lexer | gettriFunc | 26 | 5 | 0 | 27 |
src | Lexer | getSelfFunc | 23 | 5 | 0 | 57 |
src | Lexer | getSum | 21 | 5 | 0 | 82 |
src | Lexer | next | 41 | 11 | 0 | 105 |
src | Lexer | peek | 3 | 1 | 0 | 142 |
src | Parser | Parser | 3 | 1 | 1 | 15 |
src | Parser | parseExpr | 8 | 2 | 1 | 19 |
src | Parser | parseTerm | 39 | 8 | 1 | 28 |
src | Parser | parseFactor | 42 | 10 | 1 | 69 |
CC (Cyclomatic Complexity – Method)
圈复杂度,用于衡量一个模块判定结构的复杂程度,圈复杂度越大说明程序代码质量低,且难以测试和维护。
重点关注方法的圈复杂度指标。可以看出最大的两个方法为Lexer.next()和Parser.parserFactor()。主要为Factor具体的类并不存在,故这两个方法相当于最底层方法,较为复杂且需要大量使用。
Bug分析
(写bug这件事情还是很擅长的嘛)
第一次作业由于根本上的架构错误,导致没能有什么正确的地方QAQ。
重构和第二次作业解决了大部分的问题。但仍然在强测中出现了化简导致的问题,会在多项结果均化简为0时出现多余的加号。
第三次作业的问题则是经典的爆Sum问题,原因还是在于相关意识的缺少,对于程序的鲁棒性没有足够的认识
反思与总结
第一单元的练习可以确实是出现了很多问题,如第一次作业的一边写pre一边看training一边看练习题,又如后面两次的化简问题,整个过程可以说是风雨飘摇。相比较于能力问题,还是主观因素多一些。做事拖拉这件事,次次说,次次有,就连这篇博客也几乎是踩着ddl完成的。所追求的“从容”二字,倒是一点也体现不出。
诶,还是不谈了吧,毕竟
冯如杯还没写完(逃)。