Community编程与开发github.com

Aliyansayz/agent-skills

通过替换不清晰的命名、不安全的类型、重复逻辑、职责混杂、魔法值和脆弱的错误处理,提升 TypeScript 代码质量,使其具有可读性、可维护性和强类型特性。适用于审查、重构、调试或扩展现有 TypeScript 应用,尤其是销售 CRM 系统。

agent-skills 是什么?

该技能是一个 TypeScript 代码质量代理,专门用于改进现有代码的可读性、可维护性和可靠性。它帮助开发者理解函数行为、业务规则、变量含义以及数据缺失或无效时的处理方式,特别适合处理销售 CRM 系统。技能核心原则包括:使用领域特定命名(如 Lead、Contact、Opportunity)、利用 TypeScript 强类型表示业务概念、分离职责、保持预期行为不变,以及优先使用简单代码而非不必要的抽象。它适用于代码中存在模糊命名、职责混杂、不安全类型、魔法值、重复业务规则和脆弱错误处理的场景。技能提供详细的工作流程,包括理解上下文、记录当前行为、改进命名、定义类型、分离职责、处理错误和测试策略,并通过一个糟糕的 CRM 代码示例展示了常见问题及改进方法。支持的平台为 TypeScript 开发环境,如 Visual Studio Code 配合 AI 代码助手使用。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Aliyansayz/agent-skills/tree/HEAD/typescript-code-quality

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

上下文代码质量 — TypeScript 智能体技能

1. 目的

作为 TypeScript 代码质量智能体,使现有代码更易于理解、维护、测试和扩展。

不要为了显得复杂而重构代码。改进代码,使开发者能够理解:

  • 每个函数的作用。
  • 业务规则存在的原因。
  • 每个变量代表的含义。
  • 函数期望和返回的数据。
  • 数据缺失或无效时会发生什么。
  • 应用程序的哪些部分负责业务逻辑、数据访问和用户交互。
  • 更改如何影响现有应用程序行为。

使用领域特定语言,而不是模糊的变量和函数名称。

在处理销售 CRM 代码时,使用清晰的业务概念,如 Lead、Contact、Opportunity、SalesRepresentative、LeadStatus、PipelineStage 和 FollowUpDate。

目标是可理解、强类型、可靠、可测试和可维护的软件。

2. 何时激活

在以下情况下使用此技能:

  • TypeScript 代码包含诸如 x、data、obj、temp、thing 或 result 等没有足够上下文的变量。
  • 函数名称含糊不清,例如 process()、handle()、manage() 或 doStuff()。
  • 一个函数同时执行验证、业务计算、数据库更新、通知和日志记录。
  • 应用程序依赖 any、不安全的类型断言、未解释的字符串或魔法数字。
  • 业务规则在多个地方重复。
  • 错误被静默吞掉或转换为误导性的成功响应。
  • 函数包含深度嵌套的条件或过多的分支。
  • CRM 术语在组件、API 端点和数据库模型之间不一致。
  • 代码难以测试,除非连接到真实的数据库或外部服务。
  • 开发者希望改进现有代码而不改变其预期行为。

3. 核心原则

3.1 首选领域特定名称

名称应解释其在应用程序中的含义。

首选:

const leadId = "lead_123";
const salesRepresentativeId = "user_456";
const nextFollowUpDate = new Date();
const qualifiedLeadCount = 12;

避免:

const id = "lead_123";
const user = "user_456";
const date = new Date();
const count = 12;

当短名称在较小范围内含义明显时是可以接受的,例如在短循环中使用 i。不要机械地扩展每个名称;当额外的上下文有助于理解时再扩展名称。

3.2 使用 TypeScript 表示业务概念

优先使用显式类型、接口、可区分联合和命名领域模型,而不是非结构化对象。

避免将 any 用作逃生舱。对真正不受信任的数据使用 unknown,并在使用前进行验证。

3.3 分离职责

每个函数或模块应有一个明确的主要职责。

CRM 服务不应在一个函数中构造 HTTP 响应、操作 UI 组件、发送电子邮件和执行数据库查询。

3.4 保持预期行为

在重构之前,确定现有的业务规则和预期结果。

不要静默更改:

  • 潜在客户资格标准。
  • 管道转换规则。
  • 销售代表分配。
  • 跟进调度规则。
  • 重复检测行为。
  • 权限和访问控制。
  • API 响应格式。
  • 数据库语义。

如果现有行为看起来不正确或含糊不清,明确地指出问题,而不是将行为更改伪装成重构。

3.5 优先使用简单代码而非不必要的抽象

除非设计模式、类、泛型、工厂或额外依赖能够解决实际问题,否则不要引入它们。

一个具有描述性名称的简单函数通常比不必要的复杂抽象更好。


4. 编写不佳的销售 CRM 示例

以下代码故意设计存在问题。它说明了潜在客户管理应用程序中常见的代码质量问题。

4.1 之前:编写不佳的代码

// bad-crm.ts

export async function go(d: any, db: any, mail: any) {
    try {
        let x = d.name;
        let e = d.email;
        let p = d.phone || "";
        let s = d.status || "new";
        let v = Number(d.value || 0);
        let u = d.user || null;

        if (!x || !e) {
            return { ok: false, msg: "bad data" };
        }

        let old = await db.leads.findOne({ email: e });

        if (old && old.status != "lost") {
            old.v = old.v + v;
            old.s = v > 5000 ? "hot" : old.s;
            old.p = p || old.p;
            await db.leads.update(old.id, old);

            if (old.s == "hot") {
                await mail.send(
                    old.email,
                    "Hot lead",
                    "Lead is hot!"
                );
            }

            return { ok: true, data: old };
        }

        let a = {
            name: x,
            email: e,
            phone: p,
            status: s,
            value: v,
            user: u,
            created: new Date(),
            updated: new Date(),
        };

        let r = await db.leads.insert(a);

        if (v > 5000) {
            await mail.send(
                e,
                "Hot lead",
                "Lead is hot!"
            );
        }

        return { ok: true, data: r };
    } catch (e) {
        console.log(e);
        return { ok: false, msg: "error" };
    }
}

4.2 智能体应识别的问题

问题示例为何重要改进
函数名称不清晰go()没有传达业务操作如果准确描述行为,使用 createOrUpdateLead()
变量不清晰d、x、e、p、s、v、u、a、r开发者必须推断每个变量的用途使用领域特定名称
不安全的类型输入、数据库和电子邮件服务的 any移除了 TypeScript 捕获许多错误的能力定义接口和显式的输入类型
隐藏的业务规则v > 5000资格阈值未解释定义具名常量或文档化的业务规则
术语不一致status、hot、lost潜在客户状态和资格可能代表不同的概念定义显式的潜在客户状态模型
职责混合一个函数验证、查询、更新、创建、发送电子邮件和处理错误单个行为难以测试分离应用、领域和基础设施职责
潜在数据不一致数据库更新可能在电子邮件失败之前成功即使潜在客户已保存,调用者也可能收到错误明确定义通知失败行为
验证薄弱仅检查 x 和 e无效的电子邮件地址、错误的值和格式错误的字段可能进入系统验证输入和业务不变量
隐式状态规则除非状态为 "lost",否则现有潜在客户会被更新此规则的含义被隐藏命名并记录更新策略
不明确的持久化契约db.leads.findOne() 和 .update() 使用未文档化的形状数据库假设难以验证定义仓库接口
通用错误响应"error"丢失了有用的上下文,使故障排除复杂化显式处理预期失败,并适当记录意外失败
响应不一致{ ok, msg } 和 { ok, data }调用者必须推断每种情况下存在哪些字段使用可区分的结果类型或一致的应用错误模型
可变、松散形状的数据old.v、old.s、old.p字段名称与看似持久化的模型不匹配定义一致的 Lead 类型
不明确的重复策略通过电子邮件合并现有记录合并的确切含义被隐藏文档化哪些字段可以更新以及值如何聚合
难以测试的依赖数据库和电子邮件服务作为 any 传递契约和失败情况未通过编译器检查定义窄接口并注入依赖

重要: 这是一个说明性示例,不是完整的生产级 CRM 实现。重构必须首先确认现有 CRM 的实际行为、数据模型、持久化语义和业务规则。


5. 重构工作流程

按照以下工作流程改进现有的 TypeScript 代码。

第 1 步:理解上下文

在修改相关代码之前先检查它。

确定:

  • 函数的用途。
  • 其调用者和依赖项。
  • 其输入和输出格式。
  • 数据库模式或仓库契约。
  • 领域实体和业务术语。
  • 现有的验证和授权规则。
  • 当前测试和预期行为。
  • 错误处理和副作用。

必要时阅读周围模块。不要仅从函数名称推断其完整契约。

第 2 步:记录当前行为

用通俗语言描述现有逻辑。

对于上面的示例,观察到的行为是:

  1. 从输入读取潜在客户详细信息。
  2. 如果名称或电子邮件缺失,拒绝请求。
  3. 通过电子邮件查找现有潜在客户。
  4. 如果存在匹配的潜在客户且其状态不是 "lost",将提交的值添加到现有值中。
  5. 当结果值超过阈值时,将该现有潜在客户标记为 "hot"。
  6. 当提供了新的非空电话号码时,替换其电话号码。
  7. 更新记录,如果结果状态为 "hot",则发送通知。
  8. 否则,创建带有时间戳的新记录。
  9. 当提交的值超过阈值时,通知潜在客户。
  10. 返回成功或失败对象。

此描述有意区分观察到的实现行为和预期的业务行为。例如,代码在一个通知路径中测试现有记录的结果值,但在另一个路径中测试提交的值。不要将这些规则视为等同。

第 3 步:改进命名

用表达其角色的名称替换通用名称。

糟糕的名称更好的名称
gocreateOrUpdateLead
dleadInput
xleadName
eemailAddress,或在 catch 块中为 error
pphoneNumber
sleadStatus
vleadValue
usalesRepresentativeId
oldexistingLead
anewLead
rcreatedLead
dbleadRepository 或 databaseClient,取决于其实际角色
mailemailNotificationService

改进后的名称必须准确表示该值。不要将一个值重命名为 salesRepresentative

相关技能