<重构>笔记

重构:
在不改变的前提下,提高代码的可理解性,降低其修改成本


The rule of three
添加功能时一并重构
修补错误时一并重构
复审代码时一并重构

composing method

a. Extract method. divide a method into two or more method.
提炼方法, 把能分开,重用的部分单独做一个方法。

b. Inline method. conclude two or method into one method.
和Extract method相反, 概括多个方法成一个, 简化代码.

c. Inline temp. remove temp variable as we can.


d. Replace temp with query. change temp variable 's operation into a method that can be recall some other place


e. Introduce explaining variable. change series of operation into some explaining variable, use clear name


f. Split temporary variable. won't reuse temp variable for many set value operation, it make other confused


g. Remove assignments to parameters.
create a temp variable instead of object, java only use pass by value (参数不要用来赋值, 使用final, 避免对参数赋值)


h. Replace method with method object.
create method object( TestObject _testObject), use 'Extract method', use '_testObject.testMethod()'(method object)


i. Substitute algorithm. improve algorithm




Moving features between objects


a. Move method

b. Move field

c. Extract class.

d. Inline class.

e. Hide delegate. (对method进行加一层封装,使Client不能直接访问method. 简单委托关系)

f. Remove middle man. 和Hide delegate相反, 合理的隐藏程序基于实际系统的变化

g.Introduce foreign method. create new method, set server class entity as argument
ex: Date date = new Date(pro.getYear(), pro.getMonth(), pro.getDay()+1)
----> Date date = nextDay(pro);
staitc Date nextDay(Date pro)
{
return new Date()
}
<think>嗯,用户给了一个SQL查询,里面用了MyBatis的动态SQL,特别是<choose>标签,他觉得逻辑有问题。首先,我需要仔细看看这个查询的结构,尤其是where子句里面的条件部分。 用户提到“尤其是choose”,说明可能这里的逻辑有问题。先看原代码中的<choose>部分: <choose> <when test="userId != null"> and zun.user_id = #{userId} </when> <when test="recommend != null"> and zun.recommend = #{recommend} and zun.visibility = 1 </when> <otherwise> and zun.visibility = 1 </otherwise> </choose> 这里的问题是,MyBatis的<choose>标签类似于Java中的switch-case结构,只会执行第一个满足条件的when,或者otherwise。所以当userId不为null时,只会加上zun.user_id = #{userId},而其他条件会被忽略。但用户可能在某些情况下需要同时满足userId和其他条件,或者逻辑上有其他需求。 接下来,原查询中的<where>标签里已经有几个<if>条件,比如objectId的判断和userId为null时的visibility=1。然后再加上<choose>部分,可能导致逻辑覆盖不正确。 比如,当userId不为null时,原代码会添加zun.user_id = #{userId},但原来的<if test="userId == null">中的and zun.visibility = 1可能仍然存在,导致当userId存在时,visibility=1也被添加进去,这可能不是用户想要的。 另外,在<choose>的第二个when里,如果recommend不为null,会添加recommend和visibility=1,但原otherwise里也有visibility=1,这可能在某些情况下重复添加,或者在不需要的时候遗漏。 用户可能希望的是,当userId存在时,仅过滤该用户,并且可能不需要visibility=1。而当recommend存在时,过滤recommend并且visibility=1。否则,只应用visibility=1。但原代码的结构可能导致在userId存在时,visibility=1仍然被添加,因为外层的<if test="userId == null">会添加,如果userId不为null,那个条件不会触发,但可能在<choose>里没有处理visibility。 可能的修正方式是将所有关于visibility的条件整合到<choose>结构中,避免外层和内部的条件互相干扰。例如,当userId存在时,不需要visibility=1,而当recommend存在时,需要visibility=1,否则也需要。同时,外层的<if test="userId == null">可能会错误地添加visibility=1,即使用户Id存在,但原代码中该条件在userId不为null时不会触发,所以可能不会重复,但需要确认。 另外,注意SQL中的AND位置,MyBatis的<where>标签会自动处理前缀的AND,但需要确保条件正确组合。可能需要调整条件的结构,确保逻辑正确。 总结用户的问题,原代码中的choose部分可能没有正确处理不同情况下的visibility条件,导致逻辑错误。需要重新组织条件,将visibility的条件整合到choose的各个分支中,避免重复或遗漏。</think>你的SQL逻辑确实存在问题,尤其在 `<choose>` 控制流的使用上存在条件覆盖错误。以下是具体分析和改进方案: --- ### 一、原代码问题分析 #### 1. **`<choose>` 逻辑缺陷** ```xml <if test="userId == null"> <!-- 外层条件 --> and zun.visibility = 1 </if> <choose> <!-- 内层条件 --> <when test="userId != null"> and zun.user_id = #{userId} </when> <when test="recommend != null"> and zun.recommend = #{recommend} and zun.visibility = 1 </when> <otherwise> and zun.visibility = 1 </otherwise> </choose> ``` - **矛盾覆盖**:当 `userId != null` 时,外层 `<if>` 的 `userId == null` 不成立,但 `<choose>` 中的 `userId != null` 分支会生效,导致 `visibility=1` 被忽略 - **重复逻辑**:`<otherwise>` 和 `<when test="recommend != null">` 都包含 `visibility=1`,但未明确优先级 #### 2. **条件优先级问题** - 当同时传递 `userId` 和 `recommend` 参数时,只会命中第一个匹配的 `<when>` 分支(`userId != null`),而 `recommend` 参数会被忽略 --- ### 二、改进方案 #### 1. **重构后的逻辑 ```xml <where> <!-- 公共条件 --> <if test="objectId != null"> AND zun.object_id = #{objectId} </if> <!-- 动态条件流 --> <choose> <!-- 优先处理 userId --> <when test="userId != null"> AND zun.user_id = #{userId} </when> <!-- 次优先处理 recommend --> <when test="recommend != null"> AND zun.recommend = #{recommend} AND zun.visibility = 1 </when> <!-- 默认情况 --> <otherwise> AND zun.visibility = 1 </otherwise> </choose> </where> ``` #### 2. **改进点说明** | 原问题 | 改进方案 | 效果 | |-------|---------|-----| | 条件覆盖冲突 | 移除外层的 `<if test="userId == null">` | 避免 `visibility=1` 被错误添加 | | 参数优先级不明确 | 明确 `<choose>` 分支顺序 | 当同时传 `userId` 和 `recommend` 时,优先使用 `userId` | | 重复条件逻辑 | 统一通过 `<choose>` 管理 | 所有分支路径唯一且互斥 | --- ### 三、完整修正代码 ```xml SELECT zun.*, CASE WHEN zew.real_name IS NULL THEN su.realname ELSE zew.real_name END AS real_name, zew.depart_id, zew.depart_name, zw.name AS object_name, su.avatar FROM <if test="showOnly == 1"> ( SELECT t1.* FROM zsh_user_note t1 JOIN zsh_sensitive_word t2 ON t1.content LIKE CONCAT('%', t2.word, '%') ) </if> <if test="showOnly == 0"> zsh_user_note </if> zun LEFT JOIN zsh_employee_view zew ON zun.user_id = zew.work_no LEFT JOIN zsh_ware zw ON zun.ware_id = zw.id LEFT JOIN sys_user su ON su.username = zun.user_id <where> <if test="objectId != null"> AND zun.object_id = #{objectId} </if> <choose> <when test="userId != null"> AND zun.user_id = #{userId} </when> <when test="recommend != null"> AND zun.recommend = #{recommend} AND zun.visibility = 1 </when> <otherwise> AND zun.visibility = 1 </otherwise> </choose> </where> ``` --- ### 四、关键验证场景 | 入参组合 | 预期效果 | |---------|---------| | `userId=123` | 仅过滤该用户的笔记,**不要求** `visibility=1` | | `recommend=true` | 过滤推荐且公开的笔记 (`visibility=1`) | | 无任何参数 | 默认只显示公开笔记 (`visibility=1`) | | `userId=123` + `recommend=true` | 优先使用 `userId` 参数,忽略 `recommend` | 通过这种设计,既保留了原有功能,又明确了条件优先级和覆盖范围。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值