代码的拆分复用和整洁之道

2019/04/26

前言

写这篇文章的原因是感觉自己的某些习惯可以给自己的开发效率带来很大的提升,同时也让自己的开发体验变得越来越舒适,甚至会喜欢上写业务逻辑。

当然我知道自己的代码也有很多缺点,并且我并不喜欢纠正这些缺点。

我可能会写一些magic number,这样会导致别人不太容易知道某些变量在干嘛。

我不喜欢写常量,就是大写加下划线的方式,因为自己识别这种命名的难度远大于驼峰命名。

我也不喜欢写单元测试,虽然非常的推崇tdd,也不喜欢写typescript但是我会经常写注释。

1. 文件命名

关于命名,可以参考我的另外一个文章 前端命名规范

组件的命名用类的方式。

其他的都用css class的命名方式。比如 url-tools.js,index-page.scss,前端不需要用其他的命名方式。注意,一定要用名词,千万一定要养成这个好习惯,坚持只用名词命名。无论是文件夹还是文件都用中划线和名词来命名。

为什么一定要用名词,是因为这个习惯会让你写的代码更面向对象。

比如不要用mdCompile.js然后export default一个mdCompile方法,而是用md-compiler表示这是一个工具,然后用export导出一个compile方法。

为什么只用中划线,因为这个对人眼最友好。比如md-compiler要比mdCompiler更容易识别,比md_compiler更加舒服点。

当然也有非常多的其他的命名方式,比如python中的__init__.py,nextjs的文件也会用_app.js。还有比如后端的命名会用app.controller.js这样的方式,但是前端都不需要这些。

2. 变量和函数的命名

函数方法常用的命名前缀有 init, fetch, handle, is。

请求方法常用的命名前缀有create, update, get等等。

普通变量名不限定,但是尽量不要用缩写,能不用就不用,宁可稍微长一点,每一个缩写都会让读代码的人产生抱怨。尽量不要用x, y, z, l, m, n, i, j, foo, bar,除非真的是坐标值。

react class中的方法除了生命周期之外,尽量统一的去命名,而且严格的按照顺序排列,先生命周期,然后init,然后fetch,然后handle,然后getter。

比如fetchUserInfo,handleChangeGrade,isStudent 等等,分别指的是获取数据用fetch开头,用户交互用handle开头,计算或者判断返回一个boolean用is开头,和初始化相关的用init开头,init方法很少用,一般写在主文件中。

比如初始化系统配置,项目日志系统等等,表示各种辅助功能初始化和准备就绪。

除了命名之外,还需要注意的就是格式,每个方法换行,每个块之间空行,当然这些有eslint帮你做,但是习惯好了,甚至可以不用eslint也能做到。

而方法命名其实也有对应的eslint,比如react就有强制使用event hanlder prefix的命名方法

生命周期的order也有对应的eslint插件可以很容易的做到。

3. 删掉没用的注释,写有用的注释

一个非常不好的习惯就是改别人的代码的时候,觉得没用但还是不敢删,或者确定没用了,也不去删,只是把代码注释掉,然后自己重新开始写,这个方法看起来很有礼貌,但是会让项目的费代码变多。所以果断的删掉多余的代码,如果别人想要改回去可以用git版本工具去查看历史代码。

多写一些注释,我主要会写三种注释

1. 长流程注释

2. 工具函数注释

3. 通用组件注释

写注释本身也是个技术活

4. 拆分代码

代码能不写在主文件中就不写在主文件,强迫自己把代码拆分到tools, utils, Component中

组件化开发会期望把项目拆分成各种组件,然后把组件分类,互相叠加,比如这个是某个被我用组件化的方式重构的项目的page页面,链接在这里

这个文件里没有一行样式,所有的代码都被拆分到各个组件中,然后互相复用。

然后拆分完之后就会有出现一系列的UI组件和一系列的业务组件。多写几个页面UI组件就很快能达到一个小的组件库的效果。

很多人可能会觉得这样开发肯定会时间完全不够用,哪会允许估这么长的时间做这么多的前置事情,但是事实上我用这种方式开发和平常开发用的时间差不多,甚至更短。

因为这种开发方式让我的代码被拆分开,可以更加专注在各种点上。当然这种做法更大的好处是项目更可控,项目更容易迭代,项目越写越快。

组件化开发是为了复用代码,但也达到了拆分代码的效果,事实上即使不复用,也要把代码拆分开,让代码称为颗粒度更小的不耦合的元素。

拆分代码可能是为了复用,也可能只是为了拆分代码,为什么非要拆分呢,为了让自己专注在更小的单元上,写的代码更容易tdd。

5. tdd

tdd全程测试驱动开发,这是最最最重要的一点。我说过自己并不喜欢写测试用例,但事实上我承认测试用例非常非常的重要。

先粘一段官方的定义:

TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。

其实tdd这个方法论很庞大,开发们都确信先写测试后开发是完全政治正确的,但几乎没有人真的这么做到过的。是因为写测试真的不能帮你给需求板子里搭上对勾,反而很可能让你无法按时完成需要,所以不需要那么完美的遵守tdd,也不需要完美的跑过所有的测试用例,让你的代码可以达到开源的水平。

以业务逻辑为测试用例去开发,比如需要在开发一个支付弹窗。

那么先写出一行组件

然后再写一行引入

然后再开始编写这个组件,知道业务逻辑通过,就相当于测试用例完成。

当然这样是不严谨的,也是不符合tdd的,但是这样确实可以很快的帮你写出接近与tdd的代码。

6. 排序

我见过各种各样的人有着非常严格的强迫症

引入的时候先引入第三方包,然后引入自己的包,然后引入自己的工具函数。

写样式的时候,先写dispaly相关,然后position相关,然后写size相关,然后写color和background相关,最后写shadow,border-radius,opacity。

还有react component中先按照顺序排生命周期,然后init,然后fetch,然后handle,最后render。

我完全认同这种类似于强迫症的排序习惯,我也有类似的习惯,但这个习惯并没有那么严格的遵守。因为这种习惯让你的代码看起来更有味道,更加整洁,更加易读,更加容易查找,更加不容易对他生气,更加容易让别人觉得你是个大神,更加容易让你喜欢上写代码等等。

最后

我相信新手是不会有这些所谓的强迫症的,而且几乎所有的经验丰富的大牛写代码都会有各种各样的好习惯,都会有着所谓的自己的拆分代码原则和整洁之道。不同的人可能会不太一样,但一致的是为了让代码更容易管理而拆分,为了让代码更易读而整洁。

因为这些贯穿整个开发生涯的习惯都有着非常显而易见帮助,甚至远远大于任何插件和技巧。

嗨,请先登录

加载中...
(๑>ω<๑) 又是元气满满的一天哟