首页
/ impeccable harden 实战指南:以错误处理、i18n 与边界用例把界面加固到生产就绪

impeccable harden 实战指南:以错误处理、i18n 与边界用例把界面加固到生产就绪

2026-09-08 20:55:20作者:宣利权Counsellor

本文以 impeccable 技能套件中的 harden 参考文档 为骨架展开,讲解该命令的核心命题:只依赖"完美数据"的设计不是生产就绪的设计。你会掌握从需求评估、七大加固维度(文本溢出、国际化、错误处理、边界条件、输入校验、无障碍、性能)到测试与验证的完整闭环,并通过仓库源码与测试夹具了解 impeccable 是如何把这类加固检查固化下来的。

什么是 harden:在 impeccable 中的定位

harden 是 impeccable 技能套件 Refine(精修) 类别下的一个命令,用于把界面打磨到"生产可用"。在 skill/SKILL.src.md 的命令总表中,它的定位如下:

命令 类别 描述 参考文档
harden [target] Refine Production-ready: errors, i18n, edge cases reference/harden.md

对应的命令元数据(skill/scripts/command-metadata.json)给出它的触发条件与参数形式:

  • 描述:"Make interfaces production-ready: error handling, i18n, text overflow, edge case management, and resilience under real-world data."
  • 使用场景:当用户要求 harden、make production-ready、处理边界用例、补充错误状态,或修复溢出(overflow)与 i18n 问题时使用;
  • 参数提示[target],即可以像 harden [目标页面/组件] 这样限定作用域。

同目录下与它协同的参考文档还有 polish(最终质量过检)、audit(技术质量体检)、onboard(首次使用与空状态)等;harden 完成边界用例覆盖后,会把工作交接给 /impeccable polish 做最后一轮质检(详见 polish 参考)。

该技能同时以多套 harness 目录分发(如 .claude/skills/impeccable/reference/harden.md.cursor/skills/impeccable/reference/harden.md.qoder/skills/impeccable/reference/harden.md),以及可供打包分发的 plugin/skills/impeccable/reference/harden.md。不同 harness 使用不同的命令前缀占位符,例如 SKILL 源文件中的 {{command_prefix}}impeccable polish 会被替换为各环境实际的前缀,文档正文则统一写作 /impeccable polish

第一步:系统性评估加固需求(Assess Hardening Needs)

加固不是凭感觉修修补补,而是先刻意制造"坏情况"来暴露弱点。harden 文档把评估分为三类。

1. 用极端输入测试

输入类别 具体用例
超长文本 很长的名字、描述、标题
超短文本 空串、单个字符
特殊字符 emoji、RTL 文本、带重音符号的字母
超大数字 百万、十亿级别
海量条目 1000+ 列表项、50+ 下拉选项
无数据 空状态(empty states)

2. 测试错误场景

  • 网络失败:离线(offline)、慢速(slow)、超时(timeout);
  • API 错误:400、401、403、404、500;
  • 校验错误(validation errors);
  • 权限错误(permission errors);
  • 限流(rate limiting);
  • 并发操作(concurrent operations)。

3. 测试国际化(i18n)

  • 长译文:德语通常比英语长 30%;
  • RTL 语言:阿拉伯语、希伯来语;
  • 字符集:中日韩(CJK)、emoji;
  • 日期/时间格式;
  • 数字格式(1,000 与 1.000 的差异);
  • 货币符号。

CRITICAL 原则:只依赖完美数据才能正常工作的设计不是生产就绪的设计——要对现实做加固(Harden against reality)

加固的七大维度

评估暴露问题后,就进入系统化的加固。harden 文档给出了七个相互独立的加固维度。

维度一:文本溢出与换行(Text Overflow & Wrapping)

长文本处理的三种 CSS 策略

/* 单行省略号 */
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 多行截断(clamp 到 3 行) */
.line-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* 允许正常换行 */
.wrap {
  word-wrap: break-word;
  overflow-wrap: break-word;
  hyphens: auto;
}

Flex/Grid 溢出:Flex 与 Grid 子项默认的最小尺寸取决于内容,一旦内容超长就会把容器撑破。解决方案是把 min-width: 0(Flex 允许子项缩小到内容尺寸以下)与 overflow: hidden 配合,Grid 子项则同时设 min-width: 0min-height: 0

/* 防止 flex 子项溢出 */
.flex-item {
  min-width: 0; /* 允许缩小到内容尺寸之下 */
  overflow: hidden;
}

/* 防止 grid 子项溢出 */
.grid-item {
  min-width: 0;
  min-height: 0;
}

响应式字号

  • clamp() 实现流式排版(fluid typography);
  • 设置最小可读字号:移动端正文 16px 起——这与 impeccable 排版指南给出的底线一致;14px 只允许用于真正次要的文本。注意:iOS Safari 会对小于 16px 的聚焦输入框强制放大(force-zoom),这会破坏表单布局
  • 用 200% 缩放测试文本缩放;
  • 确保容器能随文本内容扩展,而不是反向截断。

维度二:国际化(i18n)

文本膨胀(Text expansion)

  • 为译文预留 30%~40% 的额外空间预算;
  • 用能自适应内容的 flexbox/grid;
  • 用最长的语言(通常是德语)做测试;
  • 不要在文本容器上使用固定宽度。
// ❌ 错误:假设永远是短英文
<button className="w-24">Submit</button>

// ✅ 正确:自适应内容
<button className="px-4 py-2">Submit</button>

RTL(从右到左)支持:核心是改用 CSS 逻辑属性(logical properties),让布局随 dir 自动镜像,而不是写死物理方向:

/* 使用逻辑属性 */
margin-inline-start: 1rem; /* 而不是 margin-left */
padding-inline: 1rem; /* 而不是 padding-left/right */
border-inline-end: 1px solid; /* 而不是 border-right */

/* 或通过 dir 属性处理镜像元素 */
[dir="rtl"] .arrow { transform: scaleX(-1); }

字符集支持

  • 全站统一 UTF-8 编码;
  • 用中日韩(CJK)字符测试;
  • 测试 emoji(单个 emoji 可能占 2~4 字节);
  • 覆盖不同书写系统:拉丁、西里尔、阿拉伯等。

日期/时间与数字格式化:不要手写拼接,交给标准 Intl API,它会按 locale 输出正确格式:

// ✅ 使用 Intl API 做正确格式化
new Intl.DateTimeFormat('en-US').format(date); // 1/15/2024
new Intl.DateTimeFormat('de-DE').format(date); // 15.1.2024

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).format(1234.56); // $1,234.56

复数(Pluralization)规则:英文只有单复数两种形态,但斯拉夫语系、阿拉伯语等有复杂得多的复数分类。字符串模板拼接在全球化场景下必然出错,应交给 i18n 库处理:

// ❌ 错误:假设英文复数规则
`${count} item${count !== 1 ? 's' : ''}`

// ✅ 正确:使用真正的 i18n 库
t('items', { count }) // 内部处理复杂复数规则

维度三:错误处理(Error Handling)

网络错误:清晰说明发生了什么,给出重试入口,能离线就用离线模式,并单独处理超时:

// 带恢复路径的错误状态
{error && (
  <ErrorMessage>
    <p>Failed to load data. {error.message}</p>
    <button onClick={retry}>Try again</button>
  </ErrorMessage>
)}

表单校验错误:字段旁就近展示内联错误;信息要具体明确;给出修正建议;不要无谓阻塞提交;出错时保留用户已输入内容(不要整表单清空)。

API 错误码的对应处理

状态码 应呈现的状态
400 展示校验错误
401 跳转登录
403 展示权限错误
404 展示"未找到"状态
429 展示限流提示
500 展示通用错误并提供支持入口

优雅降级(Graceful degradation):核心功能在无 JavaScript 时也可用;图片带 alt 文本;采用渐进增强;为不支持的新特性提供回退方案。

维度四:边界条件(Edge Cases & Boundary Conditions)

  • 空状态(Empty states):列表无条目、无搜索结果、无通知、无数据可展示时,都要给出明确的下一个动作,而不是一片空白。
  • 加载状态(Loading states):覆盖初次加载、分页加载、刷新;说明正在加载什么("Loading your projects...");长操作用时间估算。
  • 大数据集(Large datasets):用分页或虚拟滚动、提供搜索/筛选、做性能优化——绝不要把 10,000 条数据一次性全部加载
  • 并发操作(Concurrent operations):加载中禁用按钮防止重复提交;处理竞态条件;乐观更新必须带回滚;要有冲突解决策略。
  • 权限状态(Permission states):无查看权限、无编辑权限、只读模式,都要有清晰的界面表达并说明原因。
  • 浏览器兼容(Browser compatibility):为现代特性准备 polyfill;为不支持的 CSS 提供回退;用特性检测而非浏览器检测;在目标浏览器上逐一测试。

维度五:输入校验与净化(Input Validation & Sanitization)

客户端校验:必填、格式校验(邮箱/电话/URL)、长度限制、正则匹配、自定义规则。

服务端校验(永远要做):绝不要只信任客户端校验;所有输入都必须服务端校验与净化;防护注入攻击;服务端实施限流。

用 HTML 约束属性把规则声明出来——约束本身就是对用户最直接的引导:

<!-- 声明清晰的约束 -->
<input
  type="text"
  maxlength="100"
  pattern="[A-Za-z0-9]+"
  required
  aria-describedby="username-hint"
/>
<small id="username-hint">
  Letters and numbers only, up to 100 characters
</small>

注意 aria-describedby 把提示文本与输入框关联起来,兼顾了约束说明与无障碍需求。

维度六:无障碍韧性(Accessibility Resilience)

  • 键盘导航:所有功能可纯键盘操作;Tab 顺序符合逻辑;模态框内要有焦点管理;长内容提供跳转链接(skip links)。
  • 屏幕阅读器支持:正确的 ARIA 标签;用 live regions 播报动态变化;有描述性的 alt 文本;使用语义化 HTML。
  • 高对比模式:在 Windows 高对比模式下测试;不要只靠颜色传达信息;提供替代视觉线索。

维度七:性能韧性(Performance Resilience)

慢速连接:渐进式图片加载、骨架屏(skeleton screens)、乐观 UI 更新、用 Service Worker 做离线支持。

内存泄漏:组件卸载时清理事件监听器、取消订阅、清除定时器/interval、abort 未完成的请求

节流与防抖(Throttling & Debouncing):高频事件必须限频:

// 搜索输入防抖
const debouncedSearch = debounce(handleSearch, 300);

// 滚动处理节流
const throttledScroll = throttle(handleScroll, 100);

测试策略:把加固做进回归防线

手工测试清单

  • 用极端数据测(超长、超短、空);
  • 用不同语言测;
  • 离线测试;
  • 限速到 3G 模拟慢连接;
  • 用屏幕阅读器测;
  • 纯键盘导航测;
  • 在旧浏览器上测。

自动化测试

  • 针对边界用例的单元测试;
  • 针对错误场景的集成测试;
  • 关键路径的 E2E 测试;
  • 视觉回归测试;
  • 无障碍测试(axe、WAVE 等工具)。

值得强调的是,impeccable 自身在设计流程上就要求"有界通过、而非死循环"式的验证(见 skill/SKILL.src.md 核心原则):完整构建 → 一次性批量检查(桌面 + 移动端)→ 一次性批量修复 → 最多再确认一轮即停止。这种收敛式验证同样适用于 harden——避免用无休止的自我 QA 消耗成本。

仓库中也有与这些加固主题对应的自动化反模式夹具可供参考:例如 tests/fixtures/antipatterns/text-overflow.htmltests/fixtures/antipatterns/body-text-viewport-edge.html(正文触碰视口边缘规则)、tests/fixtures/antipatterns/clipped-overflow-container.html(裁剪溢出容器规则),而 tests/live-browser-ignores.test.mjs 等测试则验证了 clipped-overflow-container 这类规则与 ignore 机制的配合。可见"溢出/裁切/可读性"这些 harden 关注点,在 impeccable 的检测引擎里是有 fixture 化回归保障的。

绝对不要做的清单(NEVER)

harden 文档在最后给出了一组硬性禁令,可以作为走查时的红线:

  • 假设输入完美无缺——一切都要校验
  • 忽视国际化——为全球用户而设计
  • 错误提示写得笼统敷衍(例如干巴巴的 "Error occurred");
  • 忘记离线场景;
  • 只信任客户端校验;
  • 文本容器用固定宽度;
  • 假设文本长度都是英文级别;
  • 一个组件报错就把整个界面阻塞掉(错误隔离,而不是全屏白屏)。

IMPORTANT:加固的本质是预期意外(expecting the unexpected)。真实用户一定会做出你从未想象过的事。

验证加固效果(Verify Hardening)

改完之后不要口头宣称"已加固",而是逐项实测:

  • 长文本:试试 100+ 字符的名字;
  • Emoji:在所有文本字段里塞入 emoji;
  • RTL:用阿拉伯语或希伯来语测试;
  • CJK:用中文/日文/韩文测试;
  • 网络问题:断开网络、限速连接;
  • 大数据集:用 1000+ 条数据测试;
  • 并发操作:连续快速点击提交 10 次;
  • 错误:强制触发 API 错误,把每种错误状态都过一遍;
  • 空数据:删光数据,测试所有空状态。

当边界用例覆盖完毕后,harden 文档给出的收尾动作是:交接给 /impeccable polish 做最终质检(polish 的完整流程见 skill/reference/polish.md)——harden 负责"面对真实世界也能撑住",polish 负责"上线前的最后一公里细节"。

延伸阅读:把 harden 放进 impeccable 的完整工作流

harden 不是孤立的一步,它处在 impeccable 的技能编排中。想了解它如何被触发与路由,可以继续阅读:

  • 命令总表与"Refine 精修"类别定位:skill/SKILL.src.mdharden 条目位于命令表中,与 polishbolderquieterdistillonboard 并列);
  • 命令触发条件与参数元数据:skill/scripts/command-metadata.json
  • 精修类命令的共同语义——"精修是保留,重做是替换":Refine 保留现状的形态、行为、文案与范围外的一切,改动前先询问用户,这与 skill/SKILL.src.md 中的设计原则一致;
  • 无参数调用时的上下文路由(如何判断当前该不该推荐 harden):skill/reference/routing.md
  • 质量底线与绝对禁令(编辑 UI 前必读):skill/reference/craft-floor.md

一句话总结本篇:如果你的设计只有在"数据完美、网络畅通、用户讲英语"时才成立,那它还没有生产就绪。照着 harden 参考文档 的评估清单、七大加固维度与验证清单走一遍,配合自动化反模式夹具做回归,再交给 polish 收尾——这才算完成了对真实世界的加固。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
899
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
525