BUAA OO 2022 第一单元总结

BUAA OO 2022 第一单元总结

        本单元作业主要为表达式拆括号化简,并在此基础上可以进行进一步优化缩短表达式长度。

一、程序结构分析

1、第一次作业

(1)经典OO度量

类度量

方法度量

(2)类图

        本次作业首先将输入的字符串进行pre预处理,去除空格符与连续的加减号,将-x拆分为-1*x,便利之后的数据处理。使用Ipt模块将输入的StringBuilder类型的表达式字符串逐字符地识别输出,而Run模块利用Ipt模块的输出构建树状表达式,大的Expr下辖多个用加号连接的Item,Item下辖多个用乘号连接的Factor,由于Expr继承自Factor,因此可以实现无限嵌套。之后使用MainClass中的多个优化方法对表达式树进行优化化简。

        delTop分解表达式的指数,delBask拆分指数为1的表达式的括号,再结合hasBask判断是否仍然存在Item内的表达式,使用while函数去除全部表达式指数与括号;cal实现Item内部的数字相乘与未知数x的相乘;easy实现去除合并表达式内的乘0、0次方、乘1、乘-1;mix负责合并同类项;addNum将仅包含数字的Item相加;delDark将剩余的-1*x合并为-x;最终将处理后的表达式树利用toString逐层输出。

(3)自我点评

        我的Factor模块下属的Expr模块、Num模块、Alp模块与Item模块主要负责以树状图的形式存储表达式、项、数字、未知数的数据并负责打印;Ipt模块与Run模块共同负责将StringBuilder类型的表达式读取为树状图;MainClass模块负责对于字符串表达式的预处理,树状表达式的去括号、优化化简。因此,MainClass内包含了多个优化方法,使得该模块的长度远长于其他模块,造成MainClass内聚度过高,不过好在我将优化分成多步依次进行,因此对于程序各步的读取较为清晰。在各模块的耦合度方面,由于优化功能内聚在MainClass模块,读取功能内聚在Run模块,因此其他模块基本只负责数据的存储,使得程序间仅保持基本的耦合,整体耦合度较低。

2、第二次作业

(1)经典OO度量

类度量

方法度量

(2)类图

        本次作业添加了三角函数、自定义函数、求和函数,在Run中构建表达式树时,就已经使用字符串替换将求和函数与自定义函数替换为表达式,所以得到的表达式树仅仅添加了三角函数。

        添加gather方法单独实现未知数相乘与三角函数相乘;添加simCos方法实现三角函数内部表达式的化简;将原先的mix方法分解为mixCos与mixNum,mixCos将仅存在sin**2与cos**2不同的项进行合并,mixNum将仅存在数字项不同的Item进行合并同类项。

(3)自我点评

        本次作业相较于第一次作业,增加了继承自Factor模块的Cos模块、Sum模块、Fgh模块,负责存储三角函数、求和表达式、自定义函数的数据;并在MainClass模块中以第一次作业为模板,增补了对于三角函数的化简方法。而Sum模块其实并未使用,只是作为整体结构的象征性表示;Fgh仅存储了先行定义的自定义函数。之所以在表达式中未使用Fgh模块与Sum模块,是由于在Run模块读取表达式时,直接将自定义函数与求和函数替换为了表达式。在增补后,MainClass模块达到400+行,Run模块也由第一次的70+行增加到了200+行。各个方法的独立性较强,使得模块的内聚性较强,耦合度较低,优点在于读取各步过程时较为清晰,缺点在于会使得MainClass这种内聚度较高的模块的长度过长,在需要联系整体进行读取定位某个方法时需要花稍许时间进行寻找。

3、第三次作业

(1)经典OO度量

类度量

方法度量

(2)类图

 

        本次作业相较于第二次作业,由于发现了当经过化简后,Item内可能存在多个三角函数造成同类项判定错误的bug,因此直接删去了合并同类项的操作;同时为了满足新添加的三角函数内部表达式要求,在每个三角函数输出时都额外添加一层括号;为了避免浅复制带来的连带变化问题,在Expr中添加toStrbak方法用来在输出Item内的Expr时添加一层括号,以通过将表达式输出并重新读取消除浅复制影响。

(3)自我点评

        本次作业在第三次作业的基础上并未进行过多修改,仅在MainClass模块中删除了合并同类项方法并增补了三角函数的进一步化简方法,因此,整体结构上的分析与第二次作业保持一致。

二、程序bug分析

1、第一次作业两处bug

(1)去除连续加减号时,误将)后面的+去除。原因为考虑不够全面,未使用科学的情况便利方法。

(2)输入BigInteger时,将String转化为Long再转化为BigInteger,造成数据溢出,应直接使用new BigInteger。原因为对于java的方法使用了解不足,需多加练习。

2、第二次作业三处bug

(1)合并cos**2与sin**2时,未对括号内表达式进行比较。原因为为了尽快完成目标,发生了缺漏,思维严谨度不够。

(2)读取sum函数内的上下限时,未处理负数的负号,造成运行错误。原因为对于代码实际使用的考虑不够全面,需多加自主测试。

(3)拆分表达式的指数时,误将三角函数的指数一起拆分,造成浅复制的连带错误。要随时意识到浅复制可能带来的变化影响,使用clone或其他方法提前预防。

3、第三次作业一处bug

(1)化简三角函数内部为0时,将cos(0)也直接返回0。对于数学尝试不够敏感没出现生疏,应加强相关学科的重温。

4、互测bug

(1)在处理三角函数嵌套的化简过程中产生的三角函数内部的-sin(x)误读取为sin(x)。

(2)在合并同类相时,误以为三角函数化简后和未知数一样在Item内仅有一个,仅比较第一个三角函数就判断所有三角函数相等。

(3)化简0次方时,将0**0判断为0,应为1。

(4)sum函数中的表达式为i**2时,将i替换为负数时未添加括号,导致负号不进行指数运算。

(5)sum函数内的上下限使用int读取,当数字过大时产生数据溢出。

(6)sum函数直接使用指数运算数时,sum函数被取代为表达式后未添加括号,导致部分项不参与指数运算。

三、互测策略分析

        由于每一次强测的测试点数据会在debug阶段进行展示,因此我在每一次互测时都是不考虑前次作业可能出现的bug,仅考虑本次作业新增特性可能出现的bug。对于测试数据的构造,主要是以我自己的代码与遇到的困难为基础,针对于代码优化部分的新增方法进行测试,针对数字的溢出,符号的读取,幂函数、自定义函数、求和函数是否使用括号进行分隔。同时由于化简后一项内可能存在多个三角函数,使得三角函数不同于数字与未知数的唯一性,因此也对与三角函数相关的同类项合并、平方合并进行了测试。最后,对于困惑了我很久的浅复制问题也进行了测试。

四、架构设计体验

        我的整体架构主要参考了本单元的训练部分的逻辑结构,以树状图的形式存储并处理表达式,不同的是我使用了ArrayList取代了哈希序列,原因在于相较于哈希序列,我更加熟悉运用ArrayList。

        将表达式整体处理为Expr,内部使用加号连接多个项Item,在项内部使用乘连接多个因子Factor,由于Expr继承自Factor,因此整个表达式树具有向下无限延拓的性质。

        本来我考虑将Fgh模块与Sum模块也纳入表达式树,之后在优化表达式时再替换为Expr,但经过考虑后,我发现可以在将字符串表达式读取为表达式树的时候直接用字符串替换的方式将Fgh与Sum直接替换为Expr字符串,并在两侧添加括号避免外部符号的影响,再读取为Expr树,同时由于Expr具有可扩展性因此在读取为树的同时便可以自动读取嵌套部分。

        在完成基本任务,拆分括号时,我使用while函数进行处理,当检测到Item内存在Expr时,则说明存在内部多余括号,此时使用优化函数将Expr内部Item与外部的Factor分别合并,当不存在内部多余括号,即不存在Item内Expr时,while函数结束,基本任务完成。

五、心得体会

        在本单元作业中,我充分体会到了在一开始经过考虑选择一个合适的、可拓展的架构的便利性,在后续拓展时仅需要增添几个方法与因子模块即可,有时由于之前的提前考虑,自甚至不必进行增补即可完成拓展任务。

        在拓展项目时,也要注意不要盲目模仿之前已有的因子,要特别注意新的因子有没有独有的特性。例如本单元的数字因子在化简至合并同类项时每个Item内仅有一个Num,但三角函数因子在化简至合并同类项时每个Item内可能存在多个Cos。

        在debug时,我也用惨痛的经验教训铭记了细心的重要性,有时候程序中的多处复杂bug也许只是由于一次不合适的强制转换,或是写代码时偶然出现的思考冗余,亦或是问题存在两个对立情况时仅考虑了其中一种情况,这种简单的bug最容易修复,但是往往最难被发现,可能会因此耗费大量的精力与代价。

posted @ 2022-03-23 21:54  璇璃  阅读(57)  评论(0编辑  收藏  举报