Communitygithub.com

变更卫生与代码工艺

在编写或重构代码、组织提交或PR、或决定是否抽象重复时使用。症状包括:将重组与逻辑更改混为一谈、一个PR同时做多件事、文件变得庞大、出现类似代码的第二次副本、或不确定是否要对重复代码进行DRY处理。

变更卫生与代码工艺 是什么?

该技能专注于通过两项核心原则提升代码变更的清晰度与可靠性:**将结构性变更与行为性变更分离**,并以**最简洁且明确的方式表达意图**。它提供详尽的指导,帮助开发者避免在单个提交或PR中混合不相关改动,从而让评审者能够清晰区分安全的重组与真正的逻辑变化。技能强调“显式优于隐式”、使用描述性命名、注释意图而非机制,并建议保持单元小而聚焦。在DRY(不要重复自己)实践上,它主张在明确意图而非偶然形状上做抽象,并区分生产代码(应DRY)与测试代码(应DAMP,即清晰重于去重)。该技能直接对应工程章程中的第V条和第VI条,常见应用场景包括提交拆分、抽象决策和代码评审,并能有效识别如“同时移动代码并改变其行为”等危险信号。支持所有主流代码平台(如Claude Code、Cursor、Codex等)。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/lguidolin/agent-skills/tree/main/skills/change-hygiene-and-code-craft

在你喜欢的 AI 中提问

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

文档

变更卫生与代码工艺 是做什么的?

概述

变更如何组织、代码如何编写。两个主题:将结构性变更与行为性变更分离,以及用最简洁且有效的方式表达意图。

变更卫生

  • 先做结构性变更,再做行为性变更,并分别独立验证。 重组(拆分文件、重命名、添加注释)是一个独立的、可单独检查的步骤,应与行为变更(新增约束、修改逻辑)分开。永远不要将它们混合在一个不可分割的变更中——否则评审者无法区分安全的重组与真正的逻辑更改。
  • 每个变更只关注一件事。 一个变更应具有单一、可陈述的目的。
  • 在你工作的代码中进行改进,当它的问题影响你的任务时(让营地比来时更整洁)——但不要启动无关的重构。始终聚焦于目标。

代码工艺

  • 显式优于隐式。 不使用通配符代替名称,不进行隐式类型转换,不使用空字符串或魔法哨兵值。说出你的意图。
  • 描述性命名。 函数/变量描述其功能;遵循语言和生态系统的惯用风格。
  • 注释意图,而非机制。 在非显而易见的场景下解释为什么;对自解释的代码跳过注释。
  • 小型的、单一职责的单元。 对于任何单元,你应该能够说出它的功能、如何使用、依赖什么——而无需阅读其内部实现。一个大文件通常意味着做得太多。
  • 在生产代码中谨慎地遵循DRY原则。 重复是一种信号,而非自动错误。第二次出现近乎相同的代码时,触发一次有意识的决策:要么抽象,要么记录为什么不抽象。抽象共享的含义,而非偶然的形态——看起来相似但因不同原因而变化的代码应保持分离。
  • 遵循生态系统标准。 使用一位称职从业者所预期的惯用方式和受良好支持的库。不要重新发明平台已解决的轮子。

命名的张力

  • DRY vs. 过早抽象: 生产代码只在意图被证实的重复上进行抽象,而非预期中的形态重复。不确定时,等到第三次出现(YAGNI 决定最终判断)。
  • DRY vs. DAMP: 生产代码应 DRY;测试代码应 DAMP(清晰优先于去重,见 tests-as-a-control)。将 DRY 应用于测试是一种违规。

常见合理化说辞

借口现实
“我会在同一个提交里重命名并添加功能”结构与行为混合在一起的一次 diff 是无法评审的。请将它们分开。
“有两份拷贝,我立刻就要 DRY 化”第二次出现 = 做决策。相同形状 ≠ 相同含义。偶然的重复应保持分离。
“既然我在这里,顺便重构另一个模块”无关的重构会扩大范围并增加风险。记下来;现在不要做。
“聪明的单行更优雅”显式胜过巧妙。为下一位读者优化。

危险信号——停下来

  • 一个 diff 既移动代码又改变其行为
  • 一个 PR 的目的需要用“和”字来描述
  • 在第一次见到相似时就进行抽象,或者基于预期(而非实际)的重复
  • 一个你无法再完全记住的文件

完整原理:见章程第 V 条和第 VI 条,位于 engineering-constitution/references/engineering-constitution.md。

Individual skills in this repo

This repo contains 18 individual skills — each has its own dedicated page.

lguidolin/cloud-delivery-aks

Use when deploying to Kubernetes or Azure Kubernetes Service (AKS), configuring cloud secrets, setting up progressive rollout/canary, per-PR ephemeral environments, or k8s health probes. Keywords — Kubernetes, AKS, Key Vault, Argo Rollouts, Flagger, canary, blue-green, liveness, readiness, PodDisruptionBudget, HPA, rollback, GHCR.

lguidolin/commit-history-rewrite

Use when an existing repository has messy commit history that needs to conform to conventional commits before adopting release-please, or when intermediate WIP/fixup/merge commits need to be cleaned up.

lguidolin/conventional-commits-and-releases

Use when committing, writing a commit message, opening a PR that will be squash-merged, or configuring automated versioning/changelogs. Keywords — conventional commits, release-please, semver, feat/fix/chore, breaking change, changelog.

lguidolin/defense-in-depth-security

Use when handling untrusted input, secrets, authentication/authorization, or dependencies — or threat-modeling a new surface. Keywords — STRIDE, threat model, least privilege, secrets management, supply chain, dependency scanning, input validation, audit log, defense in depth.

lguidolin/designing-before-building

Use when starting a feature, fixing a non-trivial bug, or about to write implementation code — before any code exists. Symptoms you need this: "this is simple, I'll just code it", reaching for the editor before a design is approved, or an idea that hasn't been turned into a spec and plan.

lguidolin/engineering-constitution

Use when starting work in a project that follows the engineering constitution, orienting to its rules, or deciding which engineering practice applies to a task — spec writing, commits, testing, security, deploys, database, or UI work.

lguidolin/graphql-contract-testing

Use when writing a GraphQL query/mutation that the UI and a test will share, or building route/schema contract or smoke tests. Symptoms — copying a query into a test, a test asserting on query text, schema change that didn't break the UI build, or RLS/permission drift. Keywords — graphql-codegen, typed document, contract test, route smoke test.

lguidolin/init-repo-CI

Use when setting up a new repository with conventional commits, release-please, and CI automation, or when retrofitting an existing repository that lacks automated versioning and PR validation workflows.

lguidolin/interface-craft-and-accessibility

Use when building or styling UI — components, layouts, forms, design tokens — or making accessibility decisions. Keywords — a11y, WCAG, keyboard navigation, focus state, contrast, design system, minimalist UI, component reuse, ARIA, semantic HTML.

lguidolin/merge-gates-and-automation

Use when setting up or changing CI, pre-push hooks, or a task runner, or deciding what must pass before merge. Symptoms — tempted to put authoritative checks only in a local hook, skip CI, bypass with --no-verify, or unsure what gates a merge vs. runs locally.

lguidolin/observability-and-slos

Use when adding logging, metrics, tracing, health checks, SLOs, or alerting — or when building a service surface that needs to be operable and debuggable. Keywords — structured logs, OpenTelemetry, correlation id, RED metrics, liveness, readiness, SLI, SLO, error budget, alerting.

lguidolin/performance-and-scale

Use when working on hot paths, list endpoints, pagination, data-access in loops, or public interfaces/schemas. Symptoms — unbounded queries, N+1 access, no latency budget, optimizing without measuring, or changing an interface many consumers depend on. Keywords — pagination, N+1, Hyrum's Law, performance budget, bundle size.

lguidolin/postgres-postgraphile-rls-and-sql

Use when writing PostgreSQL, PostGraphile config, Row-Level Security policies, SQL schema files, or working on the Browser→App→PostGraphile→Postgres data path. Keywords — RLS, SECURITY DEFINER, search_path, pgSettings, grants, roles, GraphQL depth limit, query cost, statement_timeout, SQL file organization.

lguidolin/recording-decisions

Use when a design or architecture decision has been made and needs to be captured — writing a decision record or ADR, updating a decision index, noting a deferred idea, or superseding a past decision. Keywords — ADR, decision record, rationale, rejected alternatives, dependency index.

lguidolin/resilience-and-deploy-safety

Use when planning a deploy, designing a rollback, or responding to an incident or writing a postmortem. Keywords — deploy safety, rollback, immutable artifact, progressive delivery, canary, blast radius, incident response, blameless postmortem, error budget.

lguidolin/ship-it

Use when the user wants to ship work — push, PR, archive decision records, merge, and clean up. Handles the full lifecycle from committing final changes through post-merge cleanup including converting specs/plans to compact decision records.

lguidolin/tests-as-a-control

Use when writing or modifying tests, when a test breaks during a refactor, or when testing permission/role rules. Symptoms — tempted to edit a test to make it pass, testing only the happy path, a deny-test that started passing, flaky tests, or unsure what to assert.

lguidolin/zero-downtime-migrations

Use when changing a database schema where data must survive the change — adding/removing/renaming columns, constraints, indexes, or backfilling. Symptoms — a destructive migration bundled with a code deploy, a NOT NULL column with a backfill, a table-locking UPDATE, or a rename. Keywords — expand/contract, parallel change, backfill, NOT VALID, CREATE INDEX CONCURRENTLY, graphile-migrate.

相关技能