本文简单聊聊“整洁代码”的几个点

究竟什么样的代码才是高质量可维护的代码(没有味道的代码)?什么样的组件才能叫作好的组件?函数怎么写才是干净、高效、得体的?瓦卡利马僧。但是,本文中我们尝试着去瓦卡利。

组件化编程

随着业务量代码的积累,自己突然感觉有点力不从心:代码太容易成为“屎山”了。就拿目前项目的一个场景举例:写一个创建任务的表单组件。听起来很简单是吧?是很简单,但写起来,极度费劲。原因在于,该创建表单项过多,且伴随着各种联动需求。一开始愣头愣脑的上去就是干。写到一半,发现已经写不下去了—->该文件已经超过了 1000 行,变量无数,单单 flag 就十几二十来个,如若再这么写下去,我估计即使勉强实现了需求,后面接手的人都会顺着网线来砍我。此时,我的心情是崩溃且尴尬的。
你能够想象,在一个单文件代码超过1000 行游走是什么感觉吗?望着这座自己亲手堆砌的半坐“屎山“,觉得自己有义务寻求一些解决方案,免得被后人耻笑。简单的讲就是一个字:。在《重构》这本书的指导下,疯狂拆分这座屎山,当然,这个过程也是无偿加班的过程。最终单文件代码量干到了 300 来行,虽然被拆出去的儿子组件的可复用性几乎为 0,但当自己看着不超过 400 行代码的主组件时,心情极度舒适,行云流水的代码结构,此刻的内心:至少后人不会来砍我。

问题来了,如何写好一个组件?

  • 组件就是为了使得编程“积木化”,尽可能的精简,拿来即用。
  • 组建的 props,能少则少。
  • 组件暴露的 emit 方法,一个中转函数集中处理即可。
  • 通用组件的前提,功能明确。否则就定制化,哪怕代码几乎一样,也得隔离开。否则就会如同修水管,后果你懂的
  • 必须果断屏蔽各种事件穿透、值穿透的行为。就是动不动$parent.x = ‘x’,$parent.update()。。。
  • 单组件代码量限制在 300 行以内,能拆则拆,超过此数者,均视为不可维护之组件

命名规则

编程,尤其是在写前端代码的时候,最烦人的就是为组件的各种命名。我觉得,为了不被后人砍,还是需要一套标准,规范一下。

  1. 变量名用名词;函数名用动词 + 名词;返回布尔值用 is 开头。
  2. 组件名称多个单词
  3. 紧密耦合的组件名应带上父组件名称
props: {
    greetingText: String
}
...
...
<WelcomeMessage greeting-text="hi"/>
  1. 多个 attribute 的元素应该分多行撰写,每个 attribute 一行。
  2. 组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。

任何组件或者函数,注释一定要清楚。组建的 props 和响应事件,函数的输入输出,都必须详尽的书写。(可以借助一些插件)

以前觉得代码风骚是褒义词,夸人的,各种骚气的写法写完就觉得很得意,但是,在具体的业务中,这类的风骚代码,如同垃圾。事实上不单单是别人看了你的风骚代码会骂人,有时候就连你自己隔了段时间再去看,都懒得看了,尤其是在还没有注释的情况下。
插一句:关于注释,最近看到一个大哥提到的老毛子的风格:直接无注释,有注释,意味着函数不够简洁。有点道理,但不能全盘接受,注释可以精简,但一些比较大的函数或者模块,没有任何注释就是灾难。

优雅的 commit

提交 commit 可以有多随意?

佛祖看了都直摇头。当然,上面因为是我个人项目就无所谓了。在公司的团队中开发,当然不能向上面那般 commit,我们需要一些规范。配合 husky,逼格瞬间提升了一个档次。

type: commit 的类型
feat: 新特性
fix: 修改问题
refactor: 代码重构
docs: 文档修改
style: 代码格式修改, 注意不是 css 修改
test: 测试用例修改
chore: 其他修改, 比如构建流程, 依赖管理.
scope: commit 影响的范围, 比如: route, component, utils, build…
subject: commit 的概述, 建议符合 50/72 formatting
body: commit 具体修改内容, 可以分为多行, 建议符合 50/72 formatting
footer: 一些备注, 通常是 BREAKING CHANGE 或修复的 bug 的链接.

函数编写规则

我现在最烦见到的代码,就是那种动不动就包裹着大几十行代码的函数,真的很恶心。一个函数恨不得把所有事儿都做了,把所有的代码都塞进去,这么个写法,您干嘛还费劲写个函数包起来呢?

  1. 整洁的代码,只做好一件事。
  2. 函数的第一原则,就是短小,第二原则,就是要更短小。
  3. 函数的入参, 0 个最佳,1 个次之,两个再次,坚决杜绝两个以上的入参。
  4. 容易适配,即数据发生变化也无需重写。这一点借助 ts 的 interface 类型,能够完美规避。任何函数的入参,需要对数据的结构作严格的定义。

关于 vue 的值传递

请看下面这张堪称“经典”的组件样例:

第一反应,真是苦了先前写这组件的大哥了,确实是不容易。第二反应是啥我就不说了都懂。组件写成这般,我建议直接枪毙。塞了这么多的参数?方法就写了五个?怎么下得了手的?
写 vue 差不多也两年了,关于组建的规范,我有两点认为是比较重要的:

  1. 父传子的值,统一用一个对象传递。
  2. 子对父的改动,统一用一个中转函数集中处理。严禁直接使用$parent 这样的方法,一时写一时爽,一直写这玩意那真的就是一直爽了。
    最后再强调一点,组件能写成上面样例那样的,真心建议墙壁。