面向对象第一单元博客

第一次作业(原始)

  第一次作业主要实现的功能为表达式的括号展开,然而自己最开始的思路却非常愚蠢,大致是是将表达式视为字符串,并直接对字符串进行修改。这种思路使代码异常繁琐且漏洞百出(原因可能是没看明白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完成的。所追求的“从容”二字,倒是一点也体现不出。
  诶,还是不谈了吧,毕竟

  冯如杯还没写完(逃)。

posted @ 2022-03-25 19:25  荀彧1732  阅读(25)  评论(2编辑  收藏  举报