301
社区成员
发帖
与我相关
我的任务
分享
整体思路:使用unfold方法为核心,将带有括号的Expr类转化为不带有括号的Arithmetic类,所有算术逻辑和优化逻辑全部在Arithmetic类中完成。
优点:分开处理,耦合度低,可优化性强。
缺点:同样的操作可以在多个位置完成,需要有统一的约束,因而容易遗忘。
缺点举例:对于某一个
Variable的正负处理,可以在Factor、Expr、Arithmetic、Simple等多个类的构造方法中完成。因而极其容易遗漏,或错误地多次正负。
解决方法:统一在最后一层Simple处理。尽管如此,在所有有正负号的类中,还是有一个Expfunc因为忘记处理正负号而发生bug。

较长类:
| 类 | 行数 |
|---|---|
| Arithmetic | 211 |
| Simple | 193 |
| Parser | 180 |
较长方法:toString()
整体代码规模评价:规模较小,由于类的拆分分类较为细致,每个类功能都较为专一。少数比较长的代码,仅是因为需要处理计算/输出/优化逻辑。代码耦合性不高,可优化性强。
经过三次作业迭代,我的架构变化如下:
第一次作业:开始着手建立架构,确立基本思路:使用unfold转为算术结构来运算,使用经典的Expr、Term、Factor三大基本类,并让Expr、Variable、Number继承Factor,形成了基本的结构。但是,由于当时未能注意到unfold形成的表达式没有括号这个特别的性质,没有单独地为其分出Arithmetic类,而是跟Expr杂糅到了一起。
第二次作业:新增的Expfunc类用于描述指数。 确立了从因子层面替换的思路。但是,由于第一次架构的缺陷,Expr同时分为有括号和没括号的两种,极大程度地增大了代码的长度和难度,由此引发了第一个逻辑混乱导致的bug:正负号处理。有的类被处理了两次负号,正好负负得正,而有一个类处理了三次负号,导致负号错误。架构极其混乱!
由此,引起了我的重构
重构:将展开后的单项式归类为Simple、将展开后的无括号表达式归类为Arithmetic,然后对各类耦合接口进行隔断。删除了80%的共有方法,同时让正负号处理全部统一到相同的位置。
重构后的优势:代码量迅速缩减,逻辑极其清楚,利于优化和迭代(第三次作业仅用一小时完成)。原先的垃圾桶井然有序。
第三次作业:只需要类似函数调用地,新增一个求导因子,然后递归调用,一级一级求导即可。
在强测和互测暴露的共3个不同质bug中,两个均是由于正负号(另一个是指数没用BigInteger)。
正负号的问题在上面已经多次重复。
这强调我们:在这种多层次递归迭代的程序里,一定要把相同的运算全部在同一级处理,否则极其容易遗忘或者重复处理。
第一单元整体工作量集中在前两周,从小白到深刻理解递归下降思想,OO的作用极其显著。虽然很累,但是成就感也很足。
在不断Debug的过程中,对于各类工具、语法的运用经验也更成熟了。相信以后我能够更进一步!
平衡每周的工作量。前两周的工作量明显偏大,尤其是第二周,新增的要求有可能导致架构重构,所以最好适当减轻第二周的任务,给同学们缓冲和反思的时间。从我的角度来说,我认为第二周的两项操作,只需要保留一项指数函数即可,第二项函数调用的操作,可以留至与求导一起实现。