Skip to main content

成员顺序契约(棘轮)

状态:2026-09-17 立的家族级约定。跨仓铁律以引擎仓 AGENTS.md 为准;本页是应用层代码层面的补充约定。

家族的应用层(各仓的页面 / 示例页 / demo)按下面这条顺序排类成员:

static 常量/字段 → static 方法 → 实例字段 → 构造函数 → 访问器 / 实例方法

用正则表达就是 S*T*F*C*(A|M)*(每个字母出现 0 次或多次,且按这个相对先后,不允许跳序回潮):

  • S static 常量 / 字段
  • T static 方法
  • F 实例字段
  • C 构造函数
  • A 访问器(getter / setter)
  • M 实例方法

为什么立这条

写新类时,「这段逻辑该挂在哪里」不该每次重新纠结。约定把答案固定下来:

  • 静态的都在最前:常量、工厂、纯函数工具一眼能找到,不穿插在实例方法之间;
  • 字段集中在构造之前:看一个类先看完它"有什么",再看"怎么造",最后看"能做什么";
  • 构造是分水岭C 之前是状态声明,之后是行为,审计与 code review 都好扫。

这是一条棘轮:新代码照契约写,偏离会被对应仓的约定测试守住(例如 ice-web-componentstests/layoutConvention.test.tstests/resizeFollowsOwnSize.test.ts 这类"成员顺序"守护测试)。

什么强制、什么不强制

  • 强制:应用层的页面 / 示例页 / demo 类。这些类形态千差万别,最需要从顺序上获得一致性。
  • 不强制:各组件库仓库的 src/(引擎仓、ice-web-components 等)。2026-09-17 体检里这类仓库有少量组件类偏离——典型是 private static __countText() / __iconOf() / __defaultPalette() 这类静态小助手紧挨着它唯一的调用者。这恰好是 Google Java Style §3.4.2 说的"每种顺序都讲得通、维护者能解释"那类顺序(该指南同时明确说成员顺序"没有唯一正确的配方",Google 的 TypeScript 指南对顺序完全沉默)。所以组件库存量不搬迁。

为什么存量不迁移

代价不对称,而且 TypeScript 里字段的声明顺序是有语义的

  1. 初始化按声明顺序执行——字段初始化器依赖前面字段的值时,挪顺序会改变求值;
  2. 影响 V8 的 class shape——为排版挪字段可能改变隐藏类,反而伤性能。

为"看起来整齐"去挪字段,既不划算也有真实风险。所以约定是:新代码照写,存量保持原状,由棘轮测试保证不再新增偏离即可。

速查

要加的东西放哪
常量 / 枚举 / 配置表S 静态区最前
纯函数工具 / 工厂T 静态方法区
实例状态字段F 构造之前的实例字段区
建对象、接依赖C 构造函数
getX / setXA 访问器区(在实例方法之前)
业务方法M 实例方法区(最后)

跨仓铁律(渲染 / 序列化 / 事件 / i18n 边界 / 动画等)见引擎仓 AGENTS.md;本页只管"类内部成员怎么排"这一件小事。