Skip to content

避免命名重复

可预测性

具有相同名称的函数或变量应该具有相同的行为。微小的行为差异会降低代码的可预测性,并可能使代码阅读者感到困惑。

📝 代码示例

在某个前端服务中,通过封装原本使用的 HTTP 库,创建了一个以新形式发送 HTTP 请求的模块。 巧合的是,原本的 HTTP 库和新创建的 HTTP 模块名称相同,都叫 http

typescript
// 该服务使用 `http` 库。
import { http as httpLibrary } from "@some-library/http";

export const http = {
  async get(url: string) {
    const token = await fetchToken();

    return httpLibrary.get(url, {
      headers: { Authorization: `Bearer ${token}` }
    });
  }
};
typescript
// 从 http.ts 文件中导入 http 的代码
import { http } from "./http";

export async function fetchUser() {
  return http.get("...");
}

👃 闻代码

可预测性

这段代码在功能上没有问题,但可能会让代码阅读者感到困惑。调用 http.get 的开发者可能会预期这个函数像原始的 HTTP 库一样只是发送一个简单的 GET 请求,但实际上会执行额外的操作,如获取令牌。

由于误解,预期行为与实际行为之间会出现差异,从而引发错误,或者使调试过程变得复杂和混乱。

✏️ 尝试改善

为了提高函数行为的可预测性,在服务中自定义函数时,应该使用与库函数明显区分开来的、具有描述性的名称。

typescript
// 该服务正在使用 `http` 库。
import { http as httpLibrary } from "@some-library/http";

// 将库函数的名称与自定义函数区分开来。
export const httpService = {
  async getWithAuth(url: string) {
    const token = await fetchToken();

    // 添加认证逻辑,例如在请求头中添加令牌。
    return httpLibrary.get(url, {
      headers: { Authorization: `Bearer ${token}` }
    });
  }
};
typescript
// 从 http.ts 文件中引入定义的 http 模块
import { httpService } from "./httpService";

export async function fetchUser() {
  // 通过函数名,可知该函数发送的是已通过认证的请求。
  return await httpService.getWithAuth("...");
}

这种方式可以减少在看到函数名时对其功能产生误解的可能性。 当其他开发者使用该函数时,他们能够意识到这是服务中定义的函数,并能够正确的使用它。

另外,通过 getWithAuth 这个名称,可以明确传达该函数是用来发送通过认证的请求。