BUAA 2024 OO UNIT1

曹伯炜-20373516 2024-03-23 01:03:08

在第一单元的作业中,我们主要是要实现对表达式的化简。具体而言,第一次作业要求我们对较为简单的表达式进行化简。在第二次作业中,我们则需要扩展化简功能,加入对三角函数、嵌套括号以及自定义函数的支持。在第三次作业中,我们进一步提升了实现的难度,加入了求导因子。

一、基于度量来分析程序结构

首先先对三次作业的程序结构进行度量与分析,将会采用以下的度量评价方式:

代码量分析:采用IDEA的Statistics插件对Project进行代码量分析。

UML类图:直观地反映出代码的架构,基于此分析每一个类的设计思路,并给出该架构的优点与缺点。

类复杂度:在分析类之间的复杂度时采用IDEA提供的插件,主要有以下三个评价指标:

OCavg = Average operation complexity(平均操作复杂度)

OCmax = Maximum operation complexity(最大操作复杂度)

WMC = Weighted method complexity(加权方法复杂度)

方法复杂度:同样采用IDEA提供的插件进行分析。

CogC = Cognitive complexity(认知复杂度)

ev(G) = Essential cyclomatic complexity(基本圈复杂度)

iv(G) = Design complexity(设计复杂度)

v(G) = cyclonmatic complexity(圈复杂度)

复杂度分析主要针对类之间、方法之间的内聚与耦合进行分析,可以清晰地看出哪些类/方法的复杂度会显著过高,也可以为定位bug提供一个借鉴的方向。

 

Homework 1

 

在第一次作业中,我采用了递归下降的方法来解析输入的表达式,这样的设计基本上是按照形式化语言的原理进行的。我将表达式Expr分解为项Term,项Term又包含因子Factor,而因子Factor则包含了三种因子:表达式因子Expr、常数因子NumFactor以及幂函数因子VarFactor。因此,我设计了Expr、Term、Factor、VarFactor、NumFactor这些类,以符合说明书中给出的文法,并且配合递归下降的方法来解析表达式。

类复杂度分析 

根据表格分析,可以看出Expr类和Parser类的复杂度较高,尤其是Lexer类。这种高复杂度在一定程度上可以预料到,主要是因为在第一次作业中,我对架构设计考虑不足,导致表达式化简方法都集中在Lexer类中实现。此外,当时我对Java中深拷贝的机制了解不够深入,因此在需要进行深拷贝时,并没有相应的设计方法。这些因素都导致了在这次框架设计中,Expr类的复杂度明显过高。 

Bug

本次作业仅在本地测试及中测阶段出现了一些小bug,强测和互测均没有出现问题。

 

Homework 2

 

第二次作业的代码量显著增加,主要原因是题目需求的增加和框架的重构。与第一次作业相比,这次作业的代码主要集中在 Expr、Parser 和 Term 三个类中。这种代码结构的调整使得代码量更加均衡,也更加合理。

本次作业中引入了 ExpFactor 类来抽象指数函数的概念,这样设计的原因是根据文法,指数函数可以表示为 exp()。对于指数函数内部的表达式,我们可以按照正常的表达式解析处理,因为递归下降会帮助我们化简。

架构的优点包括:1. 适合迭代开发,能够随着需求的变化进行灵活调整。2. 能够有效地处理合并同类项的问题。3. 各个类和方法的复杂度分布合理。

架构的缺点在于:部分类的 toString 方法复杂度较高,可能会影响代码的可读性和维护性。

类复杂度分析 

 

 

由于 Lexer 方法中承载了进行化简的功能,并且方法较多,因此其权重方法复杂度(WMC)仍然相对较高。

另外,Parser 类的复杂度也较高,这是因为它更像是一个“面向过程”的行为,负责对输入的表达式进行解析,并不断解析出各种组成部分。这涉及到较多的条件判断和逻辑处理,因此导致了类的复杂度相对较高。

至于新加入的 ExpFactor 类,其类复杂度总体上与其他因子类持平,说明指数函数类的设计相对合理。这个类主要用于抽象指数函数的概念,根据输入的表达式进行处理,不会增加过多的复杂度。

Bug

合并同类项时的深浅拷贝问题

Homework 3

在HW2奠定了良好的迭代框架之后,HW3的任务量相对较轻,主要是增加新的类和方法来满足新的需求。

针对新的求导因子,我参照了HW2中设计的ExpFactor指数函数类的抽象。

为了实现求导的功能,需要为每个类实现对应的求导方法。例如,在 Term 类中,需要实现乘法法则。这仍然采用递归处理的方式,只需要处理好不同类进行求导时的方法,整体的框架就可以支持求导功能。

架构的优点包括:1. 适合迭代开发,能够灵活应对不断变化的需求。2. 能够有效地处理合并同类项的问题。3. 各个类和方法的复杂度分布合理。

架构的缺点在于未能很好地处理求导方法的执行位置,这可能会导致代码结构不够清晰,可读性有所降低。

类复杂度分析

 

HW3中类复杂度与HW2中复杂度基本持平,依旧是Lexer类复杂度较高,且原因基本同HW2,在此不过多阐述。

除此之外,Parser的类复杂度相对HW2中却有一定程度的升高。这是由于本人在设计的时候在Parser读取到求导因子后随之执行求导计算,导致有点“架空”了求导因子类应当承担的功能。针对这个问题,可能的解决方案是将执行求导的时间点从Parser推迟到表达式化简simplify之中,这样便可以更合理地分配求导功能的分布。

心得体会

 

通过第一单元的学习,我感到自己在编程方面有了明显的进步,对于面向对象和工程化编程有了更深的理解。在第二次作业的重构过程中,我在草稿纸上绘制了整体架构图,并在与同学交流时表达了一些抱怨:“如果这是一个小组作业,那该多好啊,我可以将任务分配给每个人,然后统一一个接口就行。这样我自己写的代码量就会减少,减少出错的可能性,而且分开写还可以让每个人独立调试自己的部分。”后来看到一个博客分享“如果你能够将架构拆分成几个部分,并让每个部分都能被不同的人完成,那么你就是一个优秀的架构师。这就是工程化的理念。”

 

...全文
36 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧