面向对象编程——第一单元回顾与感想

一、作业结构分析

  第一次作业:

  

  类图(真·一类到底)

      

  方法复杂度、类复杂度、类间依赖

 

  第二次作业:

  

  类图

      

  方法复杂度、类复杂度、类间依赖

 

  第三次作业:

  

  类图

      

  方法复杂度、类复杂度、类间依赖

  结果一目了然:方法复杂度、类复杂度逐渐减少;类间依赖程度增加、类的层级化更加明显。

  应用工具度量得到的结果和我个人回顾三次作业时的感受是高度一致的:更多的类、单个类的复杂度下降以及类间依赖关系的增长,体现的是更清晰的思路和程序的层次化与模块化。

但我编程时的思维方式更加“面向对象”了吗?我觉得很难说,一方面,我在编程的时候会更加注重分而治之简化问题的理念,注意封装代码,避免结构过于复杂——这一点在第三次作业中得到了很好训练。另一方面,在我主观地、凭经验地把问题分解为不同对象的通信和协同工作之后,具体的流程实现依然是“面向过程”的。

  目前我对面向对象的理解是这样的“通过大量封装代码实现复用性和安全性。”复用性,即通过封装可重用代码或逻辑结构(使之成为父类抽象类接口)实现;安全性,即将类间通讯的方式加以限制,在保证程序正常工作的前提下严格控制类中的数据访问权限。我知道目前对于课程的理解依然有点浮于表面,但希望在之后的学习中能够更深入全面地了解OOP思想。

二、作业bug分析

  首先,前三次作业的程序逻辑是相似的(好吧这里又面向过程了),即层次构造多项式、项和因子,随后层次调用求导方法,以及可能的优化方法。根据所在位置,bug可分为构造、求导和优化这三类。相应的,一个bug的诞生与其所在环节的设计是密不可分的。

1)第一次作业

  主要有两个bug:,分别出现在首项的构造和带负号项的构造上。程序在“首项前有符号时”会重复录入首项(相当于输入了两个第一项),因此在第一项不为常数时出错;此外程序在“最后一项的系数带符号且前置的运算符为减号时”会把最后一项前的减号当加号处理,因此求导时出现负号错误。

Bug的产生主要归咎于第一次糟糕的设计——类似自动机的项匹配方法,导致Poly类的构造方法极为冗长,可读性较差。设计风格也帮了倒忙——整个项目里只有一个长达三百行的类。

  我匹配项的思路是:找到两个运算符,将它们之间的字符传递给check方法构造项。这个思路有两个主要的问题:找到一个+/-时如何判断它是不是运算符而不是系数/指数符号?如果找不到下一个运算符呢?强测和互测的两个bug,以及中测的无数个bug,都是因为没能完美地解决这两个问题。具体而言,是因为在“找不到下一个符号”时,当前符号可能是系数,可能是指数,也有可能是运算符。相应的,调用check构造项时的处理细节也有不同,因此,在如此多种的情形中,写错其中的一两种几乎是无法避免的。加之我又没有细致地列出所有情形,又没有做自动化测试,仅凭自己对不同情况的判断和强度不够的手造数据,是很难发现bug的。

2)第二次作业

  本次作业仅有的一个bug发生在多项式类Poly.java的第128、129行,虽然只是简单的两行输出优化的代码,却让我在强测中取得了61.33分的好成绩。我将每一项开头的“1*”换为“1”,将“-1*”换为“-”,但由于replaceall时的正则里没有加表示匹配开头的^,导致前一个因子以“1”结尾碰上后一个因子的前导“*”时发生了错误匹配。这和设计结构关系不大,主要是因为自己写时的疏忽,以及弱爆了的手造数据。

3)第三次作业

  本次作业两个bug都发生在ITEM类的构造方法里:由于使用正则匹配,有时程序会匹配到有前导负号的项,我采用了把负号换为“-1*”的方法。很有效,然而。。。换的时候matcher中参数的变量名写错了。一开始我是直接在传入的参数字符串item中匹配和替换负号,后来我发现想把“-+”和“--”都替换一下,引入了一个字符串item1(传入参数不能直接改),但是这样一来,最后匹配前导负号就应该在item1中进行了。但我修改的时候遗漏了matcher中的参数item,于是乎整个“替换前导负号”这部分功能都没有正常执行,所有带前导负号的项我都处理不了了。

  这看似是粗心,其实还是因为命名不规范、随意修改导致的,很多时候我在replaceall的时候都会命名一些string123什么的变量,虽然不会写错,但后续修改极易犯错;此外我每一次修改也没有计划改什么,没有考虑改动可能的影响,从而导致新增bug。今后我会仔细查看修改部分的上下文,保证修改的影响符合预期。

  第二个bug则是只考虑了-sin和-cos没有考虑-()的情况,属于拘泥于“表达式因子没有系数”这一想法,忘了第一个系数可以省略(明显是第三次指导书中与第二次重复的的部分懒得看了)。

三、互测体会

  因为不了解对拍,我在互测阶段采用的方法是阅读代码、针对性构造样例。例如第一次互测时阅读了房间所有人的代码,仔细研究正则表达式是否有不完善的、项录入后的处理有没有问题等等。

  这种策略在第一二次作业还是相对有效的,第一次作业中针对构造的样例有时还能“命中”其他人,最后刀的人还是挺多的,虽然最后分数一算并没有多少。

  但是第三次代码量增大、同时取消WF之后这种方法就非常不实用了。这次根本没有时间阅读长代码,即使读了理解了也很难马上指出漏洞(递归的执行过程缺少一定规律,只能检查递归的结束条件和每一步执行有没有问题)。第三次我依然有尝试结合被测程序结构构造样例,但效果平平。

四、可能的改进

  以难度最高的第三次作业为例,可以考虑引入简单工厂模式。我目前在factor这一层,根据因子的不同分为三种情况,构建power/sin/cos类,现在如果引入了因子ln(x),那我不仅需要在最底层加入一个ln类,同时factor中的判断语句也要修改。因此,如果改为每次建立底层因子时都调用一个工厂类,由工厂类负责判断生产什么类,可以避免factor的结构过于复杂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值