复用思维
一:故事背景
项目里有两处没有复用的思想的体现。在这里进行总结并且进行优化。以这种思维方式和习惯来指导我们进行开发工作。
1.1 没有复用的接口
通过查看代码可以发现。接口findOnlineUesr和findAllOnlineUser两个接口的返回类型是相同的,只是一个有入参,另一个没有入参。我们万千可以通过一个接口解决这些问题。
1.2 没有复用思想的接口
通过查看代码我们发现。这条动态sql里。course_id = #{course_id} 出现了多此。我们完全可以将这个功能的抽出来。而不是重复的事情做3次。
二:优化方案
2.1 问题1优化
针对问题一。我们实现一个接口。下面将会把代码从
Controller==>IService==>ServiceImple==>mapper 。整个流程依次展示出来。
2.1.1 Controller
这里定义了一个 名为 queryCourseContent 的接口,将接口暴露出去,作为程序的入口
@PostMapping("/queryCourseContent") public List<CourseContentEntity> queryCourseContent(@RequestBody CourseContentEntity courseContent){ return iCourseContentService.queryCourseContent(courseContent); }
2.1.2. IService
controller层与service层的接口,以便之后实现多态。
List<CourseContentEntity> queryCourseContent(CourseContentEntity courseContent);
2.1.3. serviceImpl
具体的service实现类,通过此实现类去调用MyBatis的接口,查询数据。
@Override public List<CourseContentEntity> queryCourseContent(CourseContentEntity courseContent) { return courseContentMapper.queryCourseContentRecord(courseContent); }
2.1.4. mybatis
这里一共有两部分,一部分是MyBatis的接口,另一部分是接口对应的xml文件。
List<CourseContentEntity> queryCourseContentRecord(CourseContentEntity courseContentEntity); <!-- 通用查询语句--> <select id="queryCourseContentRecord" resultMap="courseContentMap" > SELECT id,course_assembly_id,assembly_content,create_time,created_id,created_by,update_time,updated_id,updated_by FROM tar_course_content_info WHERE is_delete=0 <if test="id != null"> and id = #{id} </if> <if test="courseAssemblyId != null">and course_assembly_id = #{courseAssemblyId}</if> <if test="assemblyContent != null">and assembly_content = #{assemblyContent}</if> <if test="createdBy != null">and created_by = #{createdBy}</if> <if test="updatedBy != null">and updated_by = #{updatedBy}</if> <if test="remark != null">and remark = #{remark}</if> </select>
通过这种改造方式。将获取整个系统的在线人员和获取具体某个班级的在线人员就合二为一了。我们只需要通过传递的参数来进行控制即可。让我们来测试一下
2.1.5. 测试获取所有的课程
我们可以看到,body未传任何数据。查询到了所有的课程。返回的json一共4600多行。
2.1.6. 测试获取某个人创建的课程
我们在创建人里,传递了某个createdBy字段。现在接口没变,但是我们查出来的就是某个人创建的课程了。
一个接口就完成了优化前的两个功能,大大的节省了时间,提高了效率。
2.2 问题2优化
2.2.1 优化前
这里给出优化前的mybatis的xml文件内对应的sql的xml映射
select id, user_id, user_name, questionnaire_id, activity_name, course_id, class_id, user_answer, start_time, update_time, remark, is_delete from `arpro_user_answer` <where> <choose> <when test="id !='' and id != null"> and id=#{id} </when> <when test="user_answer !='' and user_answer != null"> user_answer=#{user_answer} and course_id = #{course_id} and class_id = #{class_id} </when> <when test="questionnaire_id !='' and questionnaire_id != null"> and questionnaire_id=#{questionnaire_id} and course_id = #{course_id} and class_id = #{class_id} </when> <otherwise> and course_id = #{course_id} and class_id = #{class_id} and is_delete = 0 </otherwise> </choose> </where>
仔细分析这个代码我们可以发现。它是提供了四种不同的where查询,而这四种查询都是使用 = 来做的。我们完全没有必要使用 choose、when、otherwise、标签。使用if做一个通用查询就可以
2.2.2 优化后
我们将相同的部分抽到了一起,修改了代码。
select id, user_id, user_name, questionnaire_id, activity_name, course_id, class_id, user_answer, start_time, update_time, remark, is_delete from `arpro_user_answer` <where> is_delete = 0 <if test="id !='' and id !=null"> and id = #{id} </if> <if test="userAnswer !='' and userAnswer !=null"> and user_answer = #{userAnswer} </if> <if test="courseId !='' and courseId !=null"> and course_id = #{courseId} </if> <if test="classId !='' and classId !=null"> and class_id = #{classId} </if> <if test="userAnswer !='' and userAnswer !=null"> and user_answer = #{userAnswer} </if> </where>
我这里还进行了命名的优化。通过这种通用sql的方式。我们避免了重复的代码,降低了出错的概率。在代码的整洁度上也是明显的提高。
三:总结&升华
3.1 同一个接口的意义
在Java中,通过参数提供不同的方法的意义可以有多个方面。
实现多态性:Java中的接口可以用作多态的实现方式。通过参数提供不同的方法,可以在运行时根据传递的参数类型选择相应的方法实现。这使得代码更加灵活,可以根据不同的需求执行不同的行为。
减少重复代码:通过参数提供不同的方法,可以避免编写多个几乎相同的方法,只是在某些细节上稍有不同。这样可以提高代码的可维护性和可读性,并减少代码冗余。
提高代码扩展性:如果将参数作为方法的一部分,可以轻松地添加新的参数选项,从而扩展方法的功能。这样可以在不改变方法签名的情况下,灵活地适应新的需求。
实现回调机制:通过参数提供不同的方法,可以实现回调机制。即将某个方法作为参数传递给另一个方法,在适当的时候调用传递的方法。这种方式可以用于事件处理、异步编程等场景。
总的来说,通过参数提供不同的方法可以增加代码的灵活性、可扩展性和可维护性,同时实现多态性和回调机制,使代码更加优雅和易于使用。
3.2 总结
写代码的时候,注意复用的重要性。易读性。维护性。仅仅的实现功能是不够的,必须要努力把我们的代码写的简单,优雅。不然维护起来的成本是无法控制的。