349
社区成员
结合三次作业的迭代介绍自己的架构如何逐步成型
在 training1 中我们实现了仅含有数字、括号、加法和乘法的表达式转化为后缀表达式,并结合课程组的经验分享,从而初步了解了递归下降的具体实现。对于第一次作业的要求,采用了 training1 的架构和层次,在处理上有如下方式:
+
删除, -
前补零,从而便于后续字符串解析。表达式因子类
和unit因子类
,其中unit因子类
可以表示常量因子和变量因子及其幂次,并统一使用Factor接口。mono类
来表示unit因子相乘所得到的单项式,用poly类
表示单项式相加减形成的多项式。第二次作业中增加了三角函数因子和自定义函数因子。
sinFactor类
和cosFactor类
,用以表示内部有表达式因子、外部有幂次的三角函数因子。 hashCode
和equals
方法,也可以将内部表达式按一定规则排序后转化成字符串进行比较。Definer类
,用以存储所有自定义函数的函数名与函数表达式、函数名与函数形参。 xyz
,容易造成函数形参与实参出现混淆,如 h(x,y) = x + 2*y
,对于 h(y,2x)
就会因为重复替换出现 6*y
的错误结果。所以在一开始保存函数表达式的时候,就可以用不会出现在表达式中的符号直接替换其中的形参,如用 XYZ
替换 xyz
(注意不要用 abc
替换,因为 cos 中有 c )。FuncFactor
进行字符串的解析和结果保存。第三次作业增加了函数嵌套调用和求导功能。
由于使用的是递归调用的分析方法,函数嵌套调用已经基本实现。
对于求导功能的实现,仍然在原有架构上,通过求导方法的实现来完成:
对于Factor类
增加求导的抽象方法diff()
对于所有的因子(unit因子、三角函数因子、项、表达式),类比转化成多项式方法toPoly()
的实现,根据求导公式重写diff()
。这里我没有严格按照求导公式的递归来实现,而是根据不同因子的特点手动进行求导,例如:
常量变量因子:a*x^b -> a*b * x^(b-1)
三角因子:sin(in)^b -> b * sin(in)^(b-1) * cos(in) * dx(in)
term:遍历一下,其中一个因子求导后和其他因子相乘,将结果相加
表达式因子:(expr)^n -> n * (expr)^(n-1) * dx(expr)
表达式:term求导后相加即可
为求导因子建一个类DiffFactor
表达式解析的时候如果检测到求导因子如dx(expr)
,要得到其对应的多项式,即对内部表达式用diff()
。后续操作就可以按照原有架构实现运算、输出字符串等等。
根据代码度量分析工具Designite
,度量类的属性个数、方法个数、每个方法规模、每个方法的控制分支数目、类总代码规模,得到类和方法的一些度量指标,具体如下:
LOC (Lines Of Code - at method and class granularity) 代码行数
CC (Cyclomatic Complexity - Method)
圈复杂度,用于衡量一个模块判定结构的复杂程度,圈复杂度越大说明程序代码质量低,且难以测试和维护。
PC (Parameter Count - Method) 方法中传入的参数个数
Project Name | Package Name | Type Name | MethodName | LOC | CC | PC |
---|---|---|---|---|---|---|
oohomework_3 | expr | CosFactor | CosFactor | 4 | 1 | 2 |
oohomework_3 | expr | CosFactor | diff | 19 | 2 | 1 |
oohomework_3 | expr | CosFactor | toPoly | 6 | 1 | 0 |
oohomework_3 | expr | DiffFactor | DiffFactor | 4 | 1 | 2 |
oohomework_3 | expr | DiffFactor | toPoly | 3 | 1 | 0 |
oohomework_3 | expr | Expr | Expr | 3 | 1 | 0 |
oohomework_3 | expr | Expr | addTerm | 3 | 1 | 1 |
oohomework_3 | expr | Expr | diff | 7 | 2 | 1 |
oohomework_3 | expr | Expr | toPoly | 7 | 2 | 0 |
oohomework_3 | expr | ExprFactor | ExprFactor | 4 | 1 | 1 |
oohomework_3 | expr | ExprFactor | setIndex | 3 | 1 | 1 |
oohomework_3 | expr | ExprFactor | diff | 16 | 3 | 1 |
oohomework_3 | expr | ExprFactor | toPoly | 3 | 1 | 0 |
oohomework_3 | expr | Factor | toPoly | 3 | 1 | 0 |
oohomework_3 | expr | Factor | diff | 3 | 1 | 1 |
oohomework_3 | expr | FuncFactor | FuncFactor | 4 | 1 | 2 |
oohomework_3 | expr | FuncFactor | funtoExpr | 5 | 1 | 0 |
oohomework_3 | expr | FuncFactor | diff | 3 | 1 | 1 |
oohomework_3 | expr | FuncFactor | toPoly | 3 | 1 | 0 |
oohomework_3 | expr | SinFactor | SinFactor | 4 | 1 | 2 |
oohomework_3 | expr | SinFactor | diff | 19 | 2 | 1 |
oohomework_3 | expr | SinFactor | toPoly | 6 | 1 | 0 |
oohomework_3 | expr | Term | Term | 4 | 1 | 1 |
oohomework_3 | expr | Term | addFactor | 3 | 1 | 1 |
oohomework_3 | expr | Term | diff | 17 | 5 | 1 |
oohomework_3 | expr | Term | toPoly | 11 | 3 | 0 |
oohomework_3 | expr | UnitFactor | UnitFactor | 5 | 1 | 3 |
oohomework_3 | expr | UnitFactor | diff | 17 | 3 | 1 |
oohomework_3 | expr | UnitFactor | toPoly | 4 | 1 | 0 |
oohomework_3 | poly | Mono | Mono | 8 | 1 | 4 |
oohomework_3 | poly | Mono | Mono | 12 | 2 | 2 |
oohomework_3 | poly | Mono | getCoe | 3 | 1 | 0 |
oohomework_3 | poly | Mono | getXexp | 3 | 1 | 0 |
oohomework_3 | poly | Mono | getYexp | 3 | 1 | 0 |
oohomework_3 | poly | Mono | getZexp | 3 | 1 | 0 |
oohomework_3 | poly | Mono | equals | 8 | 1 | 1 |
oohomework_3 | poly | Mono | sinEqual | 15 | 4 | 1 |
oohomework_3 | poly | Mono | cosEqual | 15 | 4 | 1 |
oohomework_3 | poly | Mono | addSame | 3 | 1 | 1 |
oohomework_3 | poly | Mono | mulTri | 24 | 7 | 1 |
oohomework_3 | poly | Mono | toString | 51 | 14 | 0 |
oohomework_3 | poly | Mono | addXyz | 9 | 3 | 3 |
oohomework_3 | poly | Mono | setCoe | 3 | 1 | 1 |
oohomework_3 | poly | Poly | Poly | 3 | 1 | 0 |
oohomework_3 | poly | Poly | Poly | 4 | 1 | 1 |
oohomework_3 | poly | Poly | addMono | 19 | 5 | 1 |
oohomework_3 | poly | Poly | addPoly | 12 | 3 | 1 |
oohomework_3 | poly | Poly | mulPoly | 21 | 4 | 1 |
oohomework_3 | poly | Poly | powPoly | 16 | 3 | 1 |
oohomework_3 | poly | Poly | negate | 5 | 2 | 0 |
oohomework_3 | poly | Poly | toString | 15 | 5 | 0 |
oohomework_3 | temp | Definer | addFunc | 27 | 6 | 1 |
oohomework_3 | temp | Definer | callFunc | 11 | 2 | 2 |
oohomework_3 | temp | Lexer | Lexer | 4 | 1 | 1 |
oohomework_3 | temp | Lexer | simplify | 20 | 3 | 1 |
oohomework_3 | temp | Lexer | getNumber | 12 | 3 | 0 |
oohomework_3 | temp | Lexer | next | 27 | 8 | 0 |
oohomework_3 | temp | Lexer | peek | 3 | 1 | 0 |
oohomework_3 | temp | Parser | Parser | 3 | 1 | 1 |
oohomework_3 | temp | Parser | parseExpr | 15 | 3 | 0 |
oohomework_3 | temp | Parser | parseTerm | 9 | 2 | 1 |
oohomework_3 | temp | Parser | parseFactor | 17 | 5 | 0 |
oohomework_3 | temp | Parser | parseDiff | 7 | 1 | 0 |
oohomework_3 | temp | Parser | parseFuncFactor | 12 | 2 | 1 |
oohomework_3 | temp | Parser | parseSinCosFactor | 18 | 3 | 1 |
oohomework_3 | temp | Parser | exprFactor | 11 | 2 | 0 |
oohomework_3 | temp | Parser | unitFactor | 24 | 3 | 0 |
oohomework_3 | (default package) | MainClass | main | 17 | 2 | 1 |
Project Name | Package Name | Type Name | NOF | NOPF | NOM | NOPM | LOC | WMC | NC | DIT | LCOM | FANIN | FANOUT |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
oohomework_3 | expr | CosFactor | 2 | 0 | 3 | 3 | 33 | 4 | 0 | 1 | 0 | 0 | 3 |
oohomework_3 | expr | DiffFactor | 2 | 0 | 2 | 2 | 11 | 2 | 0 | 1 | 0 | 0 | 1 |
oohomework_3 | expr | Expr | 1 | 0 | 4 | 4 | 23 | 6 | 0 | 1 | 0 | 4 | 2 |
oohomework_3 | expr | ExprFactor | 2 | 0 | 4 | 4 | 30 | 6 | 0 | 1 | 0 | 1 | 3 |
oohomework_3 | expr | Factor | 0 | 0 | 2 | 0 | 8 | 2 | 7 | 0 | -1 | 6 | 0 |
oohomework_3 | expr | FuncFactor | 2 | 0 | 4 | 3 | 19 | 4 | 0 | 1 | 0 | 0 | 4 |
oohomework_3 | expr | SinFactor | 2 | 0 | 3 | 3 | 33 | 4 | 0 | 1 | 0 | 0 | 3 |
oohomework_3 | expr | Term | 2 | 0 | 4 | 4 | 39 | 10 | 0 | 0 | 0 | 2 | 3 |
oohomework_3 | expr | UnitFactor | 3 | 0 | 3 | 3 | 31 | 5 | 0 | 1 | 0 | 0 | 1 |
oohomework_3 | poly | Mono | 6 | 0 | 14 | 14 | 168 | 42 | 0 | 0 | 0 | 7 | 2 |
oohomework_3 | poly | Poly | 1 | 0 | 8 | 8 | 98 | 24 | 0 | 0 | 0 | 8 | 2 |
oohomework_3 | temp | Definer | 2 | 0 | 2 | 2 | 42 | 8 | 0 | 0 | 0 | 2 | 3 |
oohomework_3 | temp | Lexer | 3 | 0 | 5 | 4 | 71 | 16 | 0 | 0 | 0 | 4 | 0 |
oohomework_3 | temp | Parser | 1 | 0 | 9 | 7 | 119 | 22 | 0 | 0 | 0 | 3 | 5 |
oohomework_3 | (default package) | MainClass | 0 | 0 | 1 | 1 | 19 | 2 | 0 | 0 | -1 | 0 | 5 |
秉承着高内聚低耦合的思想,LCOM的值越小越好,FANIN和FANOUT与复用性和复杂度有关,视情况判断好坏。
其中Factor类的FANIN值较高,说明其复用性较好;LCOM值普遍较低,说明代码基本符合高内聚低耦合的设计要求;FANOUT值中MainClass和Parser的值较高,因为其中进行各个模块的调用导致复杂度较高。
由各个方法的代码行数和圈复杂度可以看到,字符串相关处理和输出函数的复杂度最高,其次是各种因子计算函数和求导函数。这是由于在字符串输出过程中使用了大量的判断以实现最终表达式的化简。
在第一、二次作业中,由于利用了大量字符串的判别和处理用以化简,实际上导致了lexer类和因子的toString方法显得有些臃肿,逻辑不是很清晰,故而产生了许多奇奇怪怪的bug,如负数识别等。同时许多同学涉及到了对0次幂的化简问题,常见bug如0**0
第二次作业中涉及到类引用问题,常见bug如(sin(x)**2+cos(x)*sin(x))**2
。对类引用问题,可以使运算方法全部new一个对象,不再改变原有因子的状态。
在第三次作业中,我们可以手动构造三角因子、函数因子、求导因子相嵌套的数据,尝试临界值如0、-1等,尤其是函数因子实参、求导处容易出现bug。
出现了bug的方法一般会在化简步骤上,这部分并没有固定的逻辑方法,很多时候大家都是慢慢补充条件判断的,代码行和圈复杂度上自然更高。
第一星期体验了一把四天速通java,开始艰难地理解递归下降,一行一行代码都要问问百度(泪)。
代码大体结构是站在了前人的肩膀上,读了很多学长学姐的博客,终于大致理解了先解析后计算的逻辑思路。一方面由于前期想不通逻辑迟迟没有开始写hw1导致最后时间不够;另一方面通过再次和同学交流得到了我认为还算不错的架构,方便了后面两次作业的完成,同时也大大降低了出bug的可能性。
后面两次工作虽然繁琐,但是思路都比较清晰,所以完成起来也有一定的规划,不再疯狂压ddl了。
关于互测,个人反思构造数据时候太依赖自己的错误来造数据,并没有更多的面向组内成员的代码对症下药。研讨课上也学到了很多构造的逻辑和方法,希望下次在这方面可以更进一步。