HNU个人项目分析——

发布时间 2023-09-21 15:52:07作者: 青青草原第一扛把子

概要

  • 一.简介
  • 二.项目要求
  • 三.功能测试
  • 四.代码分析
  • 五.总结
    值得学习的地方
    需要改进的地方
  • 六.期待与展望

 

一.  简介

1.项目名称:中小学数学卷子自动生成程序

2.编程语言:JAVA

3.基本情况:本博客是对许晋源同学的个人项目代码的评价与分析,此项目是为中小学生自动生成数学试卷,基于控制台完成的中小学出题项目,项目里面用到了许多技术与规范,代码思路清晰,结构严谨,功能实现完整,值得学习

 

二.项目需求

1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户名、密码”,重新输入用户名、密码;

2、登录后,系统提示“准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”,XX为小学、初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题。每道题目的操作数在1-5个之间,操作数取值范围为1-100;

3、题目数量的有效输入范围是“10-30”(含10,30,或-1退出登录),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子(具体要求见附表)。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复(以指定文件夹下存在的文件为准,见5);

4、在登录状态下,如果用户需要切换类型选项,命令行输入“切换为XX”,XX为小学、初中和高中三个选项中的一个,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;输入正确后,显示“”系统提示“准备生成XX数学题目,请输入生成题目数量”,用户输入所需出的卷子的题目数量,系统新设置的类型进行出题;

5、生成的题目将以“年-月-日-时-分-秒.txt”的形式保存,每个账号一个文件夹。每道题目有题号,每题之间空一行;

表1——账号-密码表

账户类型

账户

密码

小学

张三1

123

小学

张三2

123

小学

张三3

123

初中

李四1

123

初中

李四2

123

初中

李四3

123

高中

王五1

123

高中

王五2

123

高中

王五3

123

表2——小学、初中、高中题目难度要求表

阶段

小学

小学

高中

难度要求

+,-,*./

平方,开根号

sin,cos,tan

备注

只能有+,-,*./和()

题目中至少有一个平方或开根号的运算符

题目中至少有一个sin,cos或tan的运算符

 

 

三. 功能测试

1. 登录功能:

输入正确信息时:

 

分析: 界面设计简洁,提示信息充分

输入错误信息时:

 

分析:错误时会有提示信息,比较简洁;(tips:如果提示信息丰富一点更好

 

 

2.出题功能:

 

分析:提示信息充分,并且把题目展示在控制台,可以让出题者直观地感受到题目的生成;题目生成完毕后,作者又用了两行来说明情况,清晰明了;

(查看本地txt文件):

 

 

3.退出登录功能:

 

分析:功能基本完成,输入1即可退出登录

 

4. 切换难度功能:

错误处理:

 

输入正确的信息时:

 

分析:该功能完成度很好,经过我的多种测试(这里就不展示了),发现能够完全地处理异常情况,效果很好

 

 

四. 项目代码分析:

作者主要定义了七个类,分别是实体类下的User、抽象类School,以及相应继承的PrimarySchool、MiddleSchool、HighSchool,还有工具类LogSystem、启动类ClientSystem;

(tips:由于类的数目较多,我这里就只分析关键的部分,避免冗长

 

1.关键的school类,以及其实现类

父类:

这里定义了两个抽象方法,分别是“根据随机数生成符号sign”,以及“出题makequestion”

子类的继承:

子类实现了父类的两个抽象方法,并且自己定义了一个辅助函数preQuestion预处理

 

 

方法1 selectSign:

分析:

① 这里作者通过switch、case语句来把数字映射到字符上,分别用0-9对应不同的操作符,从下图可以看出,代码结构十分清晰;

②但是存在问题,由于java的字符串是不可变对象,进行大量字符串的拼接,会消耗很多时间,有待改进。

 

 

方法2 preQuestion:

分析:

①   进行数据预处理,主要目的是先生成第一个操作数,然后通过makequestion生成所有数字;

②   这里使用random随机生成temp,然后采用int类型去映射不同情况,并配合“符号生成”函数,进行情况的处理;

 

 

方法3 Makequestion:

分析:这里沿用了上面的预处理函数的基本逻辑;

但还是存在相应的问题:字符串拼接导致的空间和时间的双重损耗,导致堆空间的不断占用

 

 

2. LogSystem

方法1: 文件流的读写:

 

分析:这里作者使用文件流,从txt读取所有用户的信息,以及写入题目到txt文件;这里采用了缓存流的思想;并且使用了try-catch语句来处理流的异常,错误时能够精准知道报错原因;这些都值得学习

 

 

方法2:isNumeric

分析:这里作者巧妙地使用Character类的isDigit方法,来判断某字符是不是数字;

作为辅助函数,能很好地发挥作用

 

方法3:makeQuestion

分析:这里作者对外封装了一个出题方法,之前我们看过了School类里面已经定义好的出题方法,这里通过switch-case的进一步三种分支的判断跳转,使得对外只需要这一个方法,代码开发就不需要创建school类以及其三个子类,具有很好的规范性

 

 

 

五. 优缺点分析

 

值得学习的地方:

1.包结构层面:

该项目的包结构比较清晰,分为entity,utils工具包,启动类单独存放;这样让人一眼明白项目在哪里启动,以及相关函数的位置;相比于所有类放在一个包下面的这种臃肿的行为,是值得学习的;

 

 

2.用户信息的存储方式:

由于本项目不需要存数据到数据库,因此不需要复杂的操作;但是该项目里作者用到了文本存储,把数据放到文件txt里;众所周知,数据库本质上也是一种文件,所以这种方式很好地模拟了数据库的形式;相比于自己项目定义常量,这种方式也让数据可直观地让使用者知道位置。

 

 

3.抽象类的解耦

该项目里使用了抽象类,通过定义abstract方法,子代继承并实现,极大地提高了代码复用,也解决了代码的部分耦合,符合我们的“设计模式”里的面向接口设计原则,值得学习。

 

4.文件流的技术使用

不管是在读取用户信息,还是读取存储题目中,该作者都使用到了java文件io流这种技术,有效地将数据保存到本地。并且采用了BufferedWriter类缓冲流,功能效率上比起一般的流更加地好,,其类内部维护了一个缓冲区,可以一次性写入多个字符到缓冲区,减少了实际写入磁盘或网络的次数,从而提高了写入性能。看得出来该作者对于java的各种流都比较熟悉其适用场景

 

5.代码规范层面

该作者很好地遵循了google的编程规范,包括变量的小驼峰命名、代码的空格缩进、import的规范、Override的注解等等,具有很好的观感;

 

6.项目使用层面

该项目的界面十分规范简洁,对于bug的提示也是十分完善,比较友好,提示到位,体验好;

 

 

需要改进的地方

该项目存在许多值得学习的地方,也体现出作者良好的编程水平、对java底层的熟悉了解;然而天下并无十全十美的代码,有些地方存在些许问题,如果改进那么会更好!

 

1.注释不够完善

该项目里许多方法上缺少部分注释,很多也只是一行//完成,不太规范完善;可以考虑使用javadoc的方式来进行多行注释,说明参数、返回值、函数作用等

 

2.字符串拼接的使用

该项目里使用了很多字符串拼接,当然这可能无足轻重;但对于java底层,字符串String本质是一个不可变对象;每次拼接都会new一个新的String,这样会导致堆区内存被占用过多,并且效率上也会低下;更建议作者能使用stringBuffer这类的append方法(本质上string的拼接就是new了个stringBuffer对象)

3.题目生成仍可优化:

 

对于生成的题目,可能存在一些不太合适的地方,比如上图里的括号加到一个数上;对于括号生成的方式需要进行一些额外的判断,这方面还可以优化;

 

 

六. 期待与展望

  本次项目,可以看成是我在学习完面向对象编程思想课程后的一次练习,过程中我提升了不少。在我和xjy同学一起交流学习的过程中,我们都发现了一些问题与不足。但是,通过思考和解决这些问题,这个经验对我们来说真的很有价值。我们要把自己的心得和教训结合起来,互相学习,互相提高。这样,我们就能够在编程的道路上不断进步,设计出更高效、更稳定、更易于维护的代码。我们要时刻保持积极的态度,勇于挑战自我,不断探索新的解决方案和技术,写出更好的代码。