代码的坏味道I

所谓的坏味道是来自于记忆中不好的感觉,是长年累月被臭代码恶心的结果...

场景

今天在修 bug 的时候碰到了如下代码(稍微简化下):

import { maximizeWindow, unmaximizeWindow } from '@utils/helpers';

class ComponentA {
    constructor() {
        this.isMaximized = false;
    }
    // 最大化窗口
    maximize = () => {
        maximizeWindow();
    };
    // 返回正常窗口
    unmaximize = () => {
        unmaximizeWindow();
    }
}

大概意思比较简单:用一个 isMaximized 状态来跟踪窗口的最大化状态,然后用两个工具maximizedWindowunmaximizeWindow方法来操作。

仔细想想感觉有一点坏味道,比如:

  • 假设某个组件使用了 unmaximizeWindow , 那么 isMaximized 状态是不是就乱了?
  • 假设这个窗口最大化的时候刷新了,状态是不是又乱了?
  • 怎么保证别人不用 maximizeWindow、unmaximizeWindow 两个工具类?

一些想法

❌ 注释

用注释去约束警告 ⚠️ 其他用户

/**
 * ⚠️不要直接使用这个方法️,不然会被炒掉!!!
 */
export function maximizeWindow() {}

但是这个注释很无力,有人可以无视他...

✅ 封装资源

对于这种状态和操作直接有必然联系,不能独立操作的资源(上面的 isMaximized 和 maximizeWindow、unmaximizeWindow),一定要封装起来,让调用者通过资源接口去访问。

比如上文的例子可以通过一个 MaximizeManager 对象去最大化窗口

class MaximizeManager {
    constructor() {
        this.#isMaximized = /* foo */
    }
    maximize() {
        maximizeWindow();
    }
    unmaximize() {
        unmaximizeWindow();
    }
}

export default new MaximizeManager();

所有的操作都要从这个资源管理器走,不要单独导出 maximizeWindow、unmaximizeWindow。

类似的例子还有:

  • 开始日期和结束日期
  • 带有频率控制的toast
  • 待补充

其他

还有些和特定平台绑定的代码,还是留作下篇讨论吧。