写代码三年,最怕的不是业务复杂,是同事变量命名全靠当天心情。尤其项目切到 Vue3 + TypeScript 之后,组合式 API 把一堆变量和方法全暴露在 setup 里,一个页面看下来,什么data1、res2、form、getData满天飞,代码评审时恨不得当场重写。我后来花了不少精力梳理了一套命名规范,配合严格模式下的 TypeScript 类型检查,才让项目慢慢从一个“能跑就行”的堆料工程,变成了能长期维护的样子。
这篇东西不是官方文档翻译,是我在真实项目和代码评审里总结出来的经验。适合正在从 Options API 迁到组合式 API 的团队,也适合刚接触 Vue3 + TS、对命名边界还比较模糊的同学。你会看到我踩过的坑、后来定下的规则,以及支撑这些规则背后的逻辑。
1. Vue3 + TS项目里,命名为什么突然变成一件大事
很多从 Vue2 过来的老手会觉得,命名这种事不是靠自觉吗? Vue2 时代确实有这种空间,因为 Options API 把变量、方法、计算属性都分门别类放进了各自的data、methods、computed区块。你看到一个变量叫name,基本能猜到它来自data;看到一个方法是handleClick,也大概率知道它是事件处理函数。
但 Vue3 的组合式 API 把这一切搅在一起了。所有变量、方法、计算属性全部扁平化存在于setup或<script setup>里,本质上就是一个普通的函数作用域。你看到一个裸变量name,可能是一个ref、一个reactive对象,甚至是从props解构出来的值;看到一个getData,可能是请求封装、可能是纯函数,也可能只是触发了一个事件。这种语境丢失,让命名从“加分项”变成了“必答题”。
1.1 组合式 API 把变量从“选项框”搬进了“执行流”
Vue2 的data是一个对象,天然有“状态容器”的心理暗示。Vue3 里你写const count = ref(0)时,count只是一个普通标识符,它既没有类型标注,也没有前缀说明。如果你后续在模板里不加.value,页面显示不出来,IDE 却不会报错——这种隐性问题,如果变量本身叫countRef或明确类型,排查起来就会快很多。
我在实际项目里还遇到过更头疼的场景:一个订单页,有人在setup顶部定义了一个const form = reactive({...}),到模板里却用form.xxx访问;另一处又在方法里写了form.value = ...。命名上完全看不出来,一个普通变量、一个 ref、一个 reactive,全用同一个名字“裸奔”,结果就是类型检查被绕过、运行时行为诡异。
这背后真正的痛点是:组合式 API 让作用域扁平化,但扁平化的副作用就是信息密度下降。命名就成了一种弥补手段,它把变量的“类型”和“行为”重新编码进名字里,让读代码的人不用跳到定义处就能做初步判断。这比任何 Lint 规则都更接近解决问题的本质。
1.2 TypeScript 让命名变成类型心智的一部分
TypeScript 的引入,理论上能帮我们锁定类型,实际项目中却经常出现反效果:因为类型系统能兜底,大家就觉得命名随便点也能编译过、跑得通。这恰恰是本末倒置。类型系统解决的是“这个变量是什么类型”,但解决不了“这个变量在业务里是什么意思”。
举个例子,两个开发者写同一个页面模块,一个把“订单状态”命名为status,另一个命名为state。类型上它俩都是string | number,甚至可能是联合类型,完全合法。但代码评审时,你得反复上下文切换才能确认到底哪个是业务状态、哪个是加载状态。更麻烦的是,如果status被赋值为'pending'、'success',而另一个state也是类似取值,两个变量同时存在,后来的人一旦用错,类型系统根本拦不住。
所以我一直跟团队强调:在 TS 项目里,命名是类型系统的延伸,不是可选项。一个好名字能让你在 IDE 里只靠悬浮提示,就能推断出变量来源和大致语义;一个烂名字,再严格的泛型和联合类型都救不回来。Vue3 + TS 的组合,本质是让我把“类型安全”和“命名可读性”当成同一件事来做。
2. 变量命名建议:从 ref 到 props 的完整规则
变量命名是最容易起纠纷的。有人觉得ref必须带后缀,有人说带后缀是画蛇添足;有人说reactive应该叫data,有人说恨不得全用ref。我综合了团队习惯和代码可读性,最终定了一套相对平衡的规则,先讲清楚每种变量类型的命名语境。
2.1 ref 变量:xxxRef 后缀还是裸变量名?
关于ref变量命名,社区里吵得最凶。我试过两种极端:一种是全部裸命名,比如const name = ref('');另一种是全部加Ref后缀,比如const nameRef = ref('')。裸命名在模板里很舒服,不用写一堆后缀,但回到 script 里,name到底是响应式引用还是一个常量,必须滚到定义处才知道。全加后缀又太啰嗦,尤其在<script setup>里模板直接同名使用时,满屏nameRef非常难看。
我最终的取舍是:在<script setup>内部定义的响应式变量,用裸命名,但必须严格配合类型推导和ref()的显式调用;而涉及跨函数返回、跨模块传递、或者放进reactive里的引用,则显式加Ref后缀表明类型。这个规则听起来简单,实操里能避掉很多坑。
还有一个关键场景:当你需要把 ref 作为参数传给一个工具函数时,必须在命名上区分“是否带 value 语义”。比如:
// 好的做法:明确这个参数接收的是 Ref 对象 function useSearchQuery(keywordRef: Ref<string>) { // ... } // 容易误会的做法:参数名里没有 Ref 字样 function useSearchQuery(keyword: string) { // 里面却把 Ref 对象传进来,类型对不上才调试半天 }2.2 reactive 变量:什么时候用,怎么命名
reactive是 Vue3 里处理嵌套对象响应式的主要工具,但很多人用起来没有章法。我见过最糟糕的命名是const data = reactive({}),整个组件里所有业务字段全塞进这个data,然后到处data.user.name、data.list[0].id,一多起来,谁看得懂data到底承载了什么?
我的建议是,reactive变量必须带“领域名词”后缀,让它看起来像一个实体或模块。比如订单模块就用const orderState = reactive({...}),用户信息就用const userInfo = reactive({...}),页面筛选条件就用const filterForm = reactive({...})。不要用泛化的data、info、obj,这些名字等于什么都没说。
另外一个很容易忽略的规则是:不要让reactive变量承担“跨模块共享”的职责。如果你发现一个reactive对象被多个组件或多个模块引用,这时候它已经不适合做局部变量了,应该提升到 store 或者业务模型里。命名上也要相应调整,比如变成useUserStore()解构出来的结果,而不是继续用userInfo这种局部命名误导使用者。
2.3 props 与 emit:组件对外接口的命名边界
组件之间的 props 和 emits,是命名上最容易失控的地方。Vue2 时代大家一般就写props: ['name', 'value'],类型全靠命名的“前半段”猜测。到了 Vue3 + TS,有了defineProps和defineEmits的显式类型约束,命名反而更应该讲究。
我习惯把 props 命名成“名词属性”,尽量不带动词。比如:
- 好的:
userName、orderList、visible - 不太好的:
getUserName、loadOrderList、showOrNot(语义胡闹)
props 描述的是“父组件给子组件传了什么”,本质上是一个属性描述,动词会让人误以为它是一个方法调用或者事件回调。除非这个 prop 本身就是函数类型的插槽语义,否则不要动词化。
emit 事件名则要用过去时态或完成态,强调“已经发生了什么”。比如update:visible、confirm、change、submit,而不是onUpdateVisible、onConfirm这类“带 on 前缀的事件名”。v-model 的双向绑定场景里,update:xxx是框架约定的格式,但如果你手动写事件,emit('confirm', payload)比emit('onConfirm', payload)清晰得多,因为on前缀通常是用来绑定监听器的,不是事件名的一部分。
2.4 computed 常量与普通常量的命名层次
computed的命名我也见过不少坑。最常见的是把computed当普通变量命名,比如const total = computed(...),然后在模板里直接用total。这种写法在 Vue2 里没毛病,因为computed本来就是和data平级的。但 Vue3 组合式 API 里,computed本质上是一个“带有缓存功能的函数”,你在<script setup>里写const total = computed(...),和普通变量const total = 100在代码上下文里几乎无法直观区分。
我的建议是:computed变量用“名词短语 + 形容词/结果语义”,比如totalPrice、filteredList、canSubmit,让人一看就知道它是一个计算结果。如果要进一步强调它是“机关”,可以加get或use前缀,但别滥用,否则整个页面都是useXxx、getXxx,反而分不清哪些是函数调用。普通常量呢,我习惯用const MAX_COUNT = 10这种全大写下划线命名,和computed天然区分开。
3. 方法命名建议:动词、时态和语义的搭配
方法的命名比变量更复杂,因为方法承载了行为、时序、副作用等多种因素。Vue3 + TS 项目里,方法往往又分为事件处理、数据请求、通用工具、异步流程等几类。如果全用handle+get泛化处理,代码会显得非常平庸,而且查错时毫无抓手。
3.1 事件处理方法:handleXxx 还是 onXxx
社区里一直有handleClick和onClick的命名之争。我个人的经验是:在 Vue 模板里绑定事件时,用onXxx,在组件内部定义处理函数时,用handleXxx,但这会带来一个命名冲突问题。
举个例子:
<template> <button @click="onSave">保存</button> </template> <script setup lang="ts"> function handleSave() { ... } </script>这种写法的好处是:模板里的@click="onSave"非常直观,说明这是一个事件入口;而handleSave在 script 里看起来像一个内部实现细节,不会和onSave混淆。反过来,如果你在模板里同时写@click="handleSave",又在 script 里定义一个const handleSave = () => {},名字重复会显得很绕,而且在模板里调试事件绑定时,你分不清这个handleSave是模板语法还是函数调用。
更稳妥的方案是,事件方法统一以handle开头,并且带上触发场景。比如:
handleSubmithandleCancelhandleInputChangehandleModalClose
然后用on前缀只保留给“组件对外暴露的 emit 回调”和“props 类型的函数属性”。这样在阅读模板时,@click="handleSave"不会让人误以为它是一个对外事件;在阅读 script 时,emit('onSave')这种写法也基本不可能出现。注意,emit的事件名本身不要加on,但对应到组件上接收它的 props 时,可以叫onSave,因为那是父组件在监听的视角。
3.2 数据请求方法:fetch/load/get/query 怎么选
后台管理系统开发里,请求方法满天飞。我见过同一个项目里,有人写fetchData,有人写getList,还有人写loadTable,语义全是“拿数据”,但没有任何统一约定。这种混乱在大项目里的代价非常大,因为代码检索和重构时,你不确定“拿订单列表”到底该搜fetchOrder、getOrderList还是loadOrders。
我给大家的约定是:按动作语义拆分,不要混用。
| 前缀 | 语义场景 | 例子 |
|---|---|---|
fetch | 从远端拉取数据,强调网络请求和异步过程 | fetchUserList |
get | 获取数据,可以是缓存、本地变量或简单计算 | getLocalUserInfo |
load | 初始化或重新加载,通常伴随页面/组件的挂载流程 | loadTableData |
query | 条件查询,强调基于条件的筛选行为 | queryOrderByStatus |
实际项目里,我建议优先选一个主前缀,比如fetch用于所有直接调用接口的方法,get用于非网络请求的取值方法,load只在组件挂载或事件触发的初始化场景中使用。这样至少能让代码搜索简单很多。
还要注意,请求方法不要直接用动词又带async标注的困惑。比如async function getData(),虽然编译没问题,但读代码的人光看名字完全不知道它到底要干嘛,是拿本地缓存还是走网络?你不如直接写成fetchData,结合 TS 的返回类型Promise<...>,语义就很清晰了。
3.3 布尔返回值方法:is/has/can 的语义强化
TypeScript 里返回布尔值的方法非常多,比如权限判断、状态检查、数据是否存在。很多人会写checkStatus()或者getResult(),类型上返回boolean,但命名上一点看不出来。这在业务代码里很危险,因为你调用时经常会条件判断嵌套,一个语义不明的布尔返回值最容易让人误判。
我建议强制在布尔方法前加is、has、can这类谓词:
isAdminUser(user)hasPermission(code)canEditOrder(order)
如果是响应式变量,则叫isXxx、hasXxx、canXxx也成立,比如const isSubmitting = ref(false)。关键是保持一致性:只要返回值是布尔,命名就必须带“是不是”“有没有”“能不能”的暗示。
这个方法在 Vue3 + TS 项目里特别好用,因为v-if="canEditOrder(order)"比v-if="checkOrderAuth(order)"的语义强太多了,模板直接可读,完全不用跳进方法体去猜测。
3.4 异步方法与普通方法的命名区分
Vue3 + TS 里,async/await用得非常频繁,但异步方法在命名上和普通方法往往没什么区别,都是fetchData()或submitForm()。这导致一个问题:调用者只看名字,无法判断是否需要await处理。
我个人的建议是,异步方法统一用动词短语,并且尽量在文档注释或类型上明确返回Promise,命名不强求加Async后缀,因为 Vue3 里请求几乎全是异步的,加了反而冗余。但如果你在一个方法里混合了“同步检查 + 异步请求”的逻辑,比如checkPermissionBeforeFetch(),那这就不是一个纯粹的异步方法,命名上要把它拆成两个:一个同步判断hasPermission,一个异步请求fetchData,不要揉在一起。
另外有个细节,不要在方法名里用await这个关键字。你写await fetchData()是调用,但你定义一个awaitLoadData()就非常怪。如果方法内部有大量串行异步逻辑,可以用loadXxxSequentially、ensureXxxLoaded这类增强语义,让读者明白它不只是单纯发起请求。
4. 类型与接口命名:TypeScript 的“另一半疆土”
Vue3 + TS 项目里,命名不止针对变量和方法,类型、接口、泛型的命名反而更影响项目的整体可维护性。很多时候代码报错,不是因为逻辑不对,而是因为类型名太过模糊,导致as断言满天飞,最后类型约束名存实亡。
4.1 interface 与 type 的选择和命名习惯
我在团队里定过一个简单规则:interface用于对外结构描述,type用于联合类型或工具类型。但命名上,很多人同样会犯“泛化命名”的错,比如interface IData、type Info,这是什么?没人知道。
建议在interface命名中带领域名,比如:
interface OrderEntity { id: number; status: OrderStatus; totalAmount: number; }type则通常表示一组可能值,命名上用大驼峰,不用加前缀,比如type OrderStatus = 'pending' | 'paid' | 'cancelled'。不要动用I前缀,TS 社区现在已经不太推荐了,因为interface本身已经是类型的一种,IUser和User读起来没有语义增量,反而冗长。
还要注意一点:命名要表达“数据形态”而不是“数据来源”。比如type TableData = ...这种命名很危险,因为TableData听起来像是一个 UI 组件的 props,可实际它是一个业务数据模型。业务模型应该用领域实体命名,比如OrderRecord、UserProfile。这样在ref、reactive、computed之间流转时,类型名才能保持一致。
4.2 组件 Props/Emits 类型命名规范
Vue3 + TS 里,defineProps<Props>()是很常见的写法。但很多人都把Props定义得极其粗糙,要么直接defineProps<{ visible: boolean; list: any[] }>(),要么搞一个interface Props然后就再也不管了。我要说的是,这部分命名一旦乱掉,团队协作会非常痛苦。
我的做法是:
- 组件 props 类型统一叫
XxxProps,其中Xxx是组件名去掉后缀,比如SearchFormProps。 - emits 类型统一叫
XxxEmits,同样带组件名前缀。 - 如果 props 和业务实体强相关,可以直接引用领域类型,不要重复定义
list: SomeEntity[]后又单独再写interface SomeList。
来看一个实际例子:
// 好的命名 interface UserTableProps { userList: UserEntity[]; loading: boolean; } // 不好的命名 interface Props { data: any[]; loading: boolean; }后者虽然省事,但你在.reading 几十个子组件时,每个都叫Props,别说人,IDE 的悬浮提示都很容易窜。更重要的是,如果props里嵌套了emits回调,命名上也应该配对好,比如 props 里的函数属性叫onSubmit,emits 里对应事件名就叫submit,不要一个叫sendData,一个叫submit,看起来像两个系统。
4.3 泛型和工具类型的命名细节
TS 项目里泛型用得多了,T、K、V这种单字母命名满天飞。如果你只是写一个工具函数,单字母可以接受;但如果泛型参数代表了具体业务含义,就一定要改成有语义的名字。比如:
// 不太好 function transform<T>(data: T): T { ... } // 更好 function transformEntity<T extends Entity>(entity: T): T { ... }另外,对 Vue3 项目来说,常见的工具类型如ref、computed、Record、Partial也要注意上下文里的命名一致性。比如你写const statusMap = ref<Record<string, OrderStatus>>({}),这个statusMap就比data清晰得多。泛型的约束又反过来帮助你在写map、filter时自动得到正确的类型推断,整个链路都能因为命名而受益。
5. 命名之外的协作规范:目录、文件、导出命名
命名不建议只停留在变量和方法层面。Vue3 + TS 工程里,组件文件、目录结构、导出命名同样影响代码的可读性。一个项目有几十个组件、几十个 hooks,如果文件名和导出名对不上,再好的变量命名都会被冲淡。
5.1 组件文件命名与导入命名
Vue 单文件组件(SFC)的文件命名,业内主流是 PascalCase,比如UserProfile.vue、OrderTable.vue。我建议强制统一,不允许小写中划线式命名为user-profile.vue,因为你在模板里引用组件时,可能写成<UserProfile />,而文件却是user-profile.vue,IDE 虽然可以自动解析,但检索时得花心思去拼。还有一个理由:PascalCase 和组件变量的命名在 JS 里天然对应,可以直接import UserProfile from '@/components/UserProfile.vue',减少了认知负担。
还有一个小细节:局部组件的导入命名,尽量和文件同名。别为了简洁,把UserProfile缩写成UP或者Profile,这样一旦搜索组件,全项目同名,对维护者非常友好。我自己在代码 review 时,就见过有人把<UserProfile />导入成<User />,然后发现页面渲染不对,排查了半天竟然是导入名和模板名不一致,这属于完全可以靠规范避免的坑。
5.2 store、hooks、工具函数的命名约定
Vue3 + TS 项目的状态管理,主流是 Pinia,对应 store 的命名也有讲究。我的建议是:store 文件名用小写驼峰,store 内导出的 useXxxStore 函数用use+ 领域名,比如useUserStore、useOrderStore。不要在 store 内部再导出一堆getUser、setUser这样的裸方法,尽量通过storeToRefs或defineStore的setup写法,保持 state 和 action 的命名语义一致。
hooks(组合式函数)是 Vue3 中复用逻辑的主要方式。我建议 hooks 文件统一放在hooks/或composables/目录下,文件名用useXxx.ts,内部导出的函数名和文件名保持一致。比如useTablePagination.ts导出useTablePagination(),不要导出一个paginationFunction,那会让使用方一头雾水。工具函数呢,建议放在utils/目录,命名上尽量是“动词 + 名词”的通用语义,比如formatDate、deepClone,不要用${项目缩写}_xxx这种只有自己人才懂的简写。
5.3 文件之间的命名对齐很重要
项目里还有一个经常被忽略的点:组件目录、页面路由、store 模块、API 接口函数的命名如果不对齐,检索成本会指数级上升。比如你有一个订单管理模块,目录叫order/,页面文件叫OrderList.vue,API 封装却叫getOrderData,store 叫OrderStore,看起来都“差不多”,但真要搜代码,你得在 5-6 个不同的命名体系里反复切换。
我推荐做一次命名对齐表,在团队规范里列清楚:页面路由层级用什么单词、API 模块函数用什么前缀、store 叫什么、组件前缀是什么。比如订单模块统一用order作为基础词:
- 页面:
OrderList.vue、OrderDetail.vue - API:
fetchOrderList、fetchOrderDetail - store:
useOrderStore - 组件名称:
OrderTable、OrderFormModal
这样一来,从路由到组件到 API,所有代码都是同一个词根,搜索引擎和 IDE 的引用搜索都非常精准。
6. 常见问题与避坑实录
这一节我在实际项目中踩了不少坑,也帮同事处理过不少“命名引发的事故”。列几个高频问题,配上我的排查思路。
6.1 解包忘掉 ref 导致的命名混乱
Vue3 里ref在模板中会自动解包,但在 script 中不会。很多新手或不熟悉的人,在 script 里写const name = ref('hello'),然后直接setTimeout(() => name = 'world', 1000),页面迟迟不更新,也没有报错。这个问题表面上和命名无关,但如果你一开始就遵循“裸变量名也能解包”的预设,很容易写出这种误导代码。
我的建议是:如果你发现某个ref经常被误用成普通变量,就老老实实在命名上加Ref后缀,或者在定义处加一个类型标注Ref<string>。前者能让使用方在 IDE 提示里看到类型;后者则能在编译期提醒你该用.value。说白了,命名规则就是给团队里的“粗心时刻”留一张安全网。
6.2 命名“为了加分”反而减分
有些开发者觉得命名越“高级”越好,于是写了useComposableComplexDataService这种名字,或者把方法名套上多层抽象,比如handleFilterTableDataWithPaginationAndSort。这种命名,我见一个改一个。命名是给人读的,不是给代码专家看的。
我比较推崇的是“十五秒原则”:一个开发者(了解项目建设背景)看到这个名字,15 秒内能不能知道它是干什么的?如果不行,就说明名字里的信息过多或者过抽象了。真正的好命名,不是把整个逻辑都塞进名字里,而是抓住核心语义,剩下的交给类型和注释。
比如,一个函数做了“筛选表格数据并翻页”两件事,更好的做法是拆成filterTableData()和changePage()两个方法,而不是合成一个filterAndChangePage()。如果确实需要一次性调用,可以让外部方法叫handleTableChange(),内部再调用那两个小方法。命名可以因为拆解而变得更干净,而不是靠堆砌变得更“隆重”。
6.3 团队规范的一致性问题
Vue3 + TS 项目通常是团队协作,命名规范最怕的不是没有,而是“有但不遵守”。这个问题很现实,因为哪怕你定义了各种handle/fetch/Ref规则,团队成员写代码时还是随手不一样。
我的经验是:先做一次代码评审专项检查,把命名问题单独列出来,而不是和业务逻辑混在一起讨论。比如每周花 30 分钟专门看命名重构,给每个人的代码做一次“命名体检”。这种事不需要太多理论,关键是形成一种团队默认:命名是代码质量的一部分,不是个人审美。
另外,可以用 ESLint 配合@typescript-eslint/naming-convention规则做一部分自动检查。比如强制组件文件名、函数前缀、bool 变量的is/has前缀等。虽然这不能覆盖所有语义层面的命名问题,但至少能拦住那些“变量名拼音缩写”“无意义数字后缀”这类低水平错误。
6.4 常见命名问题速查表
| 场景 | 常见错误命名 | 建议命名 | 原因 |
|---|---|---|---|
| ref 变量传给工具函数 | keyword | keywordRef或类型标注Ref<string> | 避免函数内部误用普通变量 |
| reactive 对象承载多个实体 | data | orderState | 领域名词提升可读性 |
| emit 事件名 | onConfirm | confirm | on前缀属于监听视角 |
| 请求接口方法 | getData | fetchUserList | 动词加宾语,语义完整 |
| 布尔判断方法 | checkStatus | hasPermission | 返回布尔值时谓词前置 |
| 类型名 | Props | UserTableProps | 避免全项目泛化命名 |
| 组件文件 | user-profile.vue | UserProfile.vue | 与组件导入和模板标签一致 |
这张表是我在做代码评审时常用的一张自查清单,每次新项目启动,我都会把它作为初始规范的一部分发给团队成员。定期对照检查,项目里命名混乱的情况会明显减少。
7. 一点额外的小工具:让命名规范变成可执行的约定
这一节算是经验之外的附加内容。很多人看完一堆命名建议,觉得“有道理,但记不住全部”。我自己的做法是,在项目里维护一个很短的命名约定说明文档,只写关键规则,不用写成几十页的规范手册。然后把这个文档链接放进 README 或者仓库根目录的CONTRIBUTING.md里。
另外一个好用的方式,是在代码里写几个“示范组件”或“示范 hooks”,团队成员照着复制修改,比读文档效率高得多。比如我会在项目里专门留一个components/_Playground/目录,里面放一个命名规范的示例组件,注释写明每一处变量、方法为什么这么命名。新入职的同事看一遍,再上手写业务,比看任何规范文档都直观。
最终你会发现,命名规范这件事,本质上不是在管理“名字”,而是在管理团队对业务的共同理解。Vue3 + TypeScript 项目里的每一个变量、方法、类型、文件,都是这种理解的外化。定好规则,坚持执行,项目会越写越顺手;放任自流,再强类型系统也救不回一坨“能跑但看不懂”的代码。
我个人的体会是:刚开始推行这套规则时,团队会出现不小的摩擦,因为每个人都觉得自己的命名“没问题”。但坚持几个月后,回头改一个老模块时,大家都会真心感谢当初的坚持。代码终究是写给人看的,顺手把自己的命名习惯梳理清楚,长期下来省下的时间和精力,远超一开始那点适应成本。