我对工程化的理解

工程师是个古老的职称了。耳熟能详的有建筑工程师,电器工程师等,往往他们在人们脑海中的印象是刻板,严谨,可靠。

随着互联网的发展,软件工程师出现了!他们不用一砖一瓦,也不用尺子电钻,计算机是他们的施工现场,代码是他们的工程部件,键盘之上的指尖跃动是他们的工程活动,在你看不见的地方运行着的一项项服务,操作系统上你看得见的 app,网页等是他们的工程产出。

然而有行业的地方就有江湖,正如不是每一个会盖房子的都是建筑工程师,同样的也不是每一个会编程的都可以叫做软件工程师。那普通程序员和软件工程师的区别在哪里?首先我认为工程的本质是让工作内容机械化,只需要靠重复就可以完成工作。说起来可能会觉得比较枯燥,然而实际上正是这种枯燥保障了工作的效率和正确率。基于此软件工程师的主要服务对象其实是其他程序员,他们的职能本质是通过上层的规范和设计让工程降低对开发者水平的敏感度

什么是规范?

谈到规范,就不得不提一句在各行各业都快传烂的话即约定大于实践

因为工程的实践过程必然要涉及到协作,而人作为协作的主体是不可靠的,没有好的约定再好的设计都是纸上谈兵。基于此软件工程里最好的协作状态应当是每一个人都可以不生产代码,只当个快乐的代码搬运工。怎么搬运,去哪搬运,如何摆放,这些需要约定去保障。

那如何评判约定的好坏?我的套路是开启假设性原则,假设你是刚入职过来的萌新,约定可不可以像游戏新手帮助那样引导你去开始工作,去贯彻前人造轮后人开车的理念,而不是重复造轮子。同时你的加入也不会让项目代码看起来不再像是一个人写的。当然,这里并不反对再配合一些必要的项目培训。

那约定包括了哪些内容?这里我从前端工程的角度来说下

一、工具约定

这个属于强制约定,基于人的不可靠性,首先就应当把可机器约束的部分抽出来。

比如各种 lint 工具,变量词库,它们可以更有效地约束代码风格,命名规范。

然后 npm,webpack,typescript 等等这些工具其实也属于约定的范畴,甚至这些工具本身正是工程化思维的体现。它们让工程的构建,调试,测试,发布,任务切分都可以在一个确定的范式下进行。而且这些全家桶本身就是提炼自业内的各类工程实践,你一旦用了就自动享受到了最先进的技术红利。所以哪怕你是一个普通程序员,通过使用一些 xx 全家桶,也可以输出一份还不错的工程产出。

举些实际点的例子,在前端模块化方案出现之前,页面内的脚本只能通过文档,口头约定等这些相对宽松的形式来组织,做不到静态检测,做不到更安全的封装,甚至编辑器也做不到更精确的代码提示。而现在,几乎模块化开发已经成为了一种习惯,开发者们可以更好地各司其职。然后也都习惯了在发布之前再通过一些确定的简单命令去执行代码压缩,合并,tree shaking 等构建任务,这些习惯本身不正是约定的作用么?

再补充一点,业务中造的各种轮子和使用的各种组件库其实也不只是为了少写代码,从某种意义上来说它们也都是工具约定,举个最简单的例子:你希望项目中的每一个提交按钮在点击提交之后都变成 loading 状态。这种靠开发者每次都手动去实现显然是不靠谱的,因为团队中你不可能保证每一个人都有强迫症,每一个人都那么注重用户体验,当然也有忙起来忘记了的时候。那么如果有个实现了上述规范的按钮轮子,提交什么数据你来定,怎么维护 loading 它来定,是不是就稳妥多了?

所以,工具约定能让项目质量得到基本的保障

二、文档约定

有人说,真正好的代码不需要文档,这个我认同。然后我要补充的是真正好的项目一定需要文档!我认为它的主要作用是作为你的工程设计的使用说明书,目的是去引导团队成员去使用你的设计

比如,页面中的各类部件,你设计了一个组件库出来,它们有一套统一的交互逻辑,色调,动画等等,然后在你的设想中它们也分门别类地对应了各类业务需求,哪些地方应该用 Panel,哪些地方应该有个标题,哪类操作需要放到 ActionBar 中。那你就必须要用文档去把这些设想表述出来,告诉他们你要的这个组件直接来复制这里的代码,你要的这个样式直接来这里复制我定义好的类名。去引导其他开发者去遵循,否则真正开发的时候大家还是两眼一抹黑,稍微负责点的同学会尝试从已经做好的页面中去模仿,更多的情况是去猜,比如这里的边距应该是 10px,那里的颜色应该是“#xxx”。这样一方面浪费了更多的时间,一方面很难产出一个质量稳定的产品。其他的,你封装了一些工具类,Mixin 库,定义了一些开发模式等等,这些东西都需要文档中的 api 说明和最佳实践来指导其他人去用。

说出来感觉这样好复杂,写文档占用工程师的时间会超过写代码本身,然而之后团队其他成员节省下来的时间一定会远远超过这里损失的时间。你会发现团队加班的情况越来越少了,项目出事故的概率越来越小了,成员们开始有了更多的时间去学习和实践其他技术来反哺项目本身,这才是一个良性循环。而且一份好的工程实践是可以复用的,这些才是团队积累下来的真正宝贵的财富!甚至还可以做开源,去帮助更多的团队,哪些 xxx 全家桶,xxx 组件库,不就是这么来的么?我们很多时候爱说,“没关系,之后可以再重构”,“没事,这里先这么实现吧“!我告诉你坑只会越来越多,最终形成破窗效应。。

程序员无数次踌躇满志的准备重构脏代码,结果往往都是在这坨屎上拉上了的属于自己的那坨

最后,来点实在的,说说我是怎么写项目文档的。现在很多团队都有内部代码托管平台,所以实际上文档的形式就是 README,而打开项目的首页,首先看到的其实就是根目录下的 README,它是整个项目文档的索引,我认为应该包括如下内容:

  1. 项目名称+简单介绍+演示地址
  2. 项目的安装,启动,调试,发布的完整步骤
  3. 技术栈:方言(ts,sass),框架(vue/react..),三方库(package.json 中 dependencies 下的所有)。并附上以上所有的链接,方便团队成员去补习一些前置知识
  4. 如果有 IDE 的要求,最好附上一份通用的配置,方便其他成员导入就可以使用
  5. 相关规范,比如:文件/文件夹的创建和命名规范即工程结构、Vue 组件内的标签顺序(template>script>style)、常用变量的命名词库等
  6. 其他。这里主要强调一下纪律,告诉成员们项目中的每个文件夹下面都有一份 README 在等着你,你得去看,全部看完了才可以开始开发,它们告诉了你每个文件夹里放的是什么,具体有什么作用,项目中已经有了哪些轮子,造轮子之前请三思!

然后通过这个索引,去引导他们再去打开一个个的文件夹去里面读各个轮子的 README,这种文档就没什么好解释的了,只强调一下一些业务相关或模式相关的轮子要有最佳实践的链接或 Demo,你可以直接链接到具体的页面代码中去;UI 相关的,要有样式预览和适用场景说明。

什么是设计?

这部分内容如果展开说的话我觉得会是一篇很啰嗦的长文了,而且是见仁见智的东西。坦白说,我也没信心去把它说好说完整。。。

就简单说一下,我觉得对于前端工程来说,本质是 HTML,CSS,JS,这三类元素的共同配合来实现数据的可视化。其中 HTML 是 UI 的数据结构,它应当做到可以更好地承载数据,更好地能够作为 UI 的最小单元来移植复用;CSS 是 HTML 的润色剂,它应当能够更好地为 HTML 服务,命名要更自然,作用域要更面向单元,原子类要更纯粹(bootstrap 就是一份很好的 css 设计);JS 是 UI 和数据交互的桥梁,它可以结合 HTML 和 CSS 封装出一个完整的组件,以及各类插件,工具库和业务逻辑的抽象,去面向这一个个单元去设计它们。怎么去看待上述三者之间的关系,很重要。

最后,之前写过一篇文章浅谈【四更理念】之开发一个管理端,这里面包含了我的一些设计思路和实践,算是一点小干货,希望能对你有所帮助吧。


 评论