如何做好CodeReview

CR 看什么:看核心功能的实现、看关键问题的实现。

TODO

  • 熟悉 ES 新特性

  • TS 特性

  • 前端常用的设计模式

从需求和数据结构入手

参考散点图的案例

数据驱动渲染

围绕交互+数据结构进行

【交互】是【操纵】【结构化】的【数据】

数据结构决定了你程序的输入和输出,因此数据结构确定了,剩下的就是填空题,就很容易了

数据结构设计得好不好取决于你对于框架(ECharts)和需求的理解程度

字段和属性都是要根据这 2 者来的

框架理解程度:

比如状态管理的案例

比如禁用交互:series.silent = true;

需求理解程度:

比如 history 的数据结构的设计

AI CodeReview

思路:

  • 上传待 Review 的代码文件给大模型

  • 让 LLM 对代码的功能、执行流程、架构设计进行分析

  • 按照分析框架,从不同维度进行分析,检查基本问题

  • 让 LLM 逐个文件指出问题,针对问题进行追问,并给出优化后的程序设计源码

框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## Role
你是一名资深的数据可视化领域的前端开发专家,拥有丰富的可视化设计和开发经验,非常擅长CodeReview,并发现代码中的问题。

## Background
我的同事编写了一份可视化相关的TypeScript代码,现在需要对这部分代码进行CodeReview,发现里面的优缺点,对于好的部分给出赞扬,对于有问题的部分给出具体的问题和修改建议,帮助其提升代码质量。

## Goals
1.指出代码中的优点,给与肯定,提升工作热情。
2.指出代码中的不足,给出修改建议,提升代码质量。

## Skills:
1.优秀的可视化领域的业务知识,了解常用的名词概念、行业规范。
2.卓越的可视化领域的前端开发技能,能识别数据结构、程序设计、编码的正确性,给出最优秀的程序设计建议。

## Constraints:
1.你的回答必须基于<待审查的代码>,无需额外从外部抓取内容。
2.回答内容必须按照给出的<审查内容>的格式整理。
4.给出内容要求精准且完整,需要注明在原始代码中的位置。

## Workflows
1.解压上传的代码文件包
2.先对解压后的全部文件进行阅读,然后再进行review,保证对代码有整体的认知
3.给出review结果。

## 待审查的代码
上传的文件

## 审查内容

功能说明

1
这些代码实现了什么功能,解决了什么问题?

执行流程

1
这些代码的执行流程是怎么样的?请对流程进行详细说明,并给出对应的关键代码。

架构设计

1
从架构设计的角度分析,这些代码有哪些优点和不足?针对不足请给出具体的改进策略。

可读性

关于命名,可以看下这个:classnames

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
命名定义:
文件夹、文件名、变量、函数、方法、类、接口、参数、工具类型等命名言简意赅、合理清晰
命名遵循范式可视化库的命名规范
英文命名合理运用缩写、简写,没有拼错单词

代码格式:
同一个代码块(以{}为单位)中合理运用空行划分区域
代码缩进、空格等符合规范并保持一致
大括号、分号使用合理、一致
注释格式符合可视化库的注释规范

函数/逻辑结构:
函数、方法等长度适中,拆分合理;不存在过长情况
类、方法、模块、组件、函数、接口定义等职责单一
层次设计合理,至少满足先整体再细节的划分。

逻辑复杂度:
函数、条件判断、循环等不存在过于复杂情况。计算代码的圈复杂度
函数、方法、辅助类拆分合理。

风格一致:
命名风格统一,都统一用英文或中文
相似变量等定义与组件库内、业界命名一致
迭代过程中的历史遗留代码有单独的存放空间,并解释清晰

文档规范:
遵循文档编写规范
commit、PR描述等遵循组件库规范
配置、事件、action、抛出方法等都有清晰可读文档

整体性检查:
整体通过esLint检查
reviewer整体上能较容易看懂代码的目的和工作原理

可扩展性/可维护性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
模块化:
相似功能合理拆分为可重用模块、组件
不同模块间依赖低
替换模块或扩展成本低

对内扩展:
预留扩展点位,包括但不限于配置、事件、生命周期钩子、扩展方法等
添加新功能成本低

对外封装:
内部计算、布局、缓存等实现细节对外隐藏,不可修改,必要时不可访问
对外接口集中稳定

测试:
有完整且方便的测试流程框架,组件添加测试用例容易
测试覆盖率较高

组件库依赖:
引用的依赖数量适中,不存在变化特别快、特别大的依赖
锁定依赖版本,并可以用过提待办/issue等更新依赖

健壮性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
输入校验:
包括但不限于配置项、回调函数、数据、入参等输入有完整校验代码
对于异常输入,有完全覆盖情况的处理代码,日志、错误抛出、警告等

边界条件处理:
包但不限于空值、负值、非法值、极大极小值、越界值等有充分考虑和处理边界情况

错误处理:
对已知错误有完善的捕获机制
抛出的错误信息是否有意义,信息是否对调试测试帮助较大
对可能的错误有兜底处理

性能/压力处理:
对组件有完整的性能测试用例
对计算量较大的算法进行了合理优化,使用了最优算法
对数据的加载、解析、转换等步骤中,没有冗余重复的计算

跨平台适配:
对不同的系统环境有相同的表现,针对不同平台有相应的兼容代码

历史遗留代码:
版本更新考虑向下兼容
对破坏性变更有遗留代码兜底

逐文件、逐问题分析

1
2
3
4
5
那extension.ts该怎么修改?请给出具体的代码

那“配置规范设计不够优雅”该怎么修改?请给出具体的代码

那“缺少统一的错误处理机制”该怎么修改?请给出具体的代码

CR 要点

https://zhuanlan.zhihu.com/p/111848763

差的要提出,好的要鼓励

CR 不是一味的找茬。

Good CodeReview 会给出建设性意见,而不是发表强硬措辞要求对方改正,或认为自己的意见是唯一正确的答案,因为这样的评论其实具有一定攻击性,激发对方的防御心理,产生敌对心态,这样会从内部瓦解一个团队。最好能给出建议,或者多个选择,给对方留有余地。

Better CodeReview 永远是考虑全面且正向积极的,会对写的好的地方进行鼓励,对写的不好的地方也体现出善解人意的关怀,考虑到对方可能花费了很多心血,以一种换位思考的鼓励心态进行评论。

好的 CR 应该是这样的:

更全面,从正确性到系统影响评估。
注意语气,从给出建设性意见到换位思考
及时完成审阅,从充分讨论到随机应变。
加强交流,从面对面交流到灵活选择最高效的沟通方式。
区分重点,从添加标记到利用工程化工具自动解决。
对新人要更友好

审核的内容和标准,应该从历史问题中提取。

用苛刻的标准去做 CodeReview,从长期来看,带来的回报是很大的。

CodeReview 千万不能流于形式,否则就是浪费大家时间。

一个正常的程序员,应该有大约一半的时间花在 debug 上。

当你觉得功能已经基本实现的时候,这个项目大约就完成了一半了。

要想 CR 别人,首先自己得形成编码肌肉记忆,将编码需要注意的内容自己去实践足够多的次数,这样后面你看别人的代码,马上就能识别出是否有问题了。

另外针对印象深刻的 CR,一定要做好案例记录,这样才不至于后面遗忘了。

(精)编程到底难在哪里?

作者:阿莱克西斯
链接:https://www.zhihu.com/question/22508677/answer/276595266
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  1. 做出来容易, 做正确难,这里做出来指没 bug 且完成需要的功能,这是最基本要求,不多加讨论。这里正确,不是指功能正确,而是指程序可以很容易推理理解,理解意图, 理解如何做到的,理解为什么系统不会出错。理解为什么要这么做。正确是现在怎么写不会挖坑害将来的人,现在怎么写能让别人1 年后看你代码时候不可能理解错你现在的意图,现在怎么写能在别人将来犯错的时候提示他你错了。
  2. 编程是给未来的未知人讲故事,你无法知道将来这个人是谁,他都懂什么,他经历过什么,这个系统将来已经是什么样子了。我们需要在这种无知,缺乏信息的情况下做决定,从千万种把这件事做出来的方法里,选出你觉得最能把这个故事给讲好的那种方式,把故事写下来。编程是一种沟通,沟通是一种艺术,用程序跨越时空之沟通则是一门属于程序员的特有的艺术(就好比数学家用数学公式来沟通) coding is all about the art of communication(引用)。
  3. 坏的决定会导致坏的决定,甚至导致人们去扭曲一个好的决定去迎合坏的决定。垃圾会制造垃圾,一个放在系统里不经清理的额外复杂度,会导致更多的额外复杂度的生成。
  4. 每个人甚至同一个人的不同时刻都有自己的不同的制造额外复杂度的缺陷,比如我每年去看去年自己写的代码,觉得都是垃圾。

我们所在的部门,所在的组,公司,它们的文化,到底是关心作出了一个东西,还是关心做好了一个东西。一个总是给系统添加垃圾,留坑给后人,但是能很快做出能跑起来的系统的程序员,我们到底认为他是做了好事还是做了坏事?我们到底认为他很强,还是他很弱?用超过必要而为了突显技术实力(或者练手)的复杂工具,技术框架搭建系统,做完跑路,在一个组,一个部门,一个公司,那里的文化,到底应该是鼓励还是抑制这种行为?我们又应该如何在一个环境中,去倡导推崇什么样的文化,相遇什么样的人?

人与文化,决定了什么人留在这里,什么人离开,什么人吸引什么人,什么人成长成什么样子。而设计/技术这些枝末细节则必顺应此中的人与文化而自然变化,或自愈,或走向毁灭;哪怕在恶劣的环境中,向下引导,向上规谏,潜移默化,最终改天换日,此为编程之大道也!**

(精)程序员的能力差距体现在哪里?

1、设计程序/方案时,是否能看到全景,是否会一叶障目

2、思维,用程序设计的方式解决问题,而不是用搬砖,累代码的方式解决问题,做苦力活儿

3、用抽象思维解决业务问题,实际世界的问题

思维模式,建模!

如何辨别一个程序员水平的高低?

什么是干净的代码(Clean Code)

The Top 10 Tips to Write Clean Code - Software

如何快速提升编程能力?

高频重构

每隔 2 个月重构一次核心项目的核心代码。

我就重构 SD 和 VISALL,这才是我该干的活儿。

原则

每次 CodeReview 都必须有一个主题

参与 CR 的人,应该提前针对这个主题做好准备,不管是看代码也好,补充所需的知识点也好,这样才能保证 CR 的目的性明确、效率高。

评审模型

核心问题关键功能的实现。

  • 这个需求的难点是什么?
  • 核心的问题是什么?关键的功能是什么?
  • 如何从程序设计角度解决这个难点的?

确定维度以及每个维度的标准。

就像现在的 CR 扫描工具,也是分了不同维度的。

要想深入 CR,还得了解业务才行。

流程

0、看一下README文档

1、看package.json文件,了解技术栈和依赖的库

2、讲一下整个程序的执行流程
3、看一下路由
4、看一下 HTTP 请求的处理
5、关键问题是什么,如何解决的,说下方案

检查点

静态资源,包括大小、依赖的包是否有冗余

卷面分

基础下限就是代码的“卷面分”

整体的架构图(有哪些模块、关联关系)

核心功能/问题的主要流程(流程图),比如图表渲染流程

全局功能的设计(路由、存储、接口)

边界情况是否考虑

极限值、无值、else 等情况

路由

路由怎么设计的?常见错误有哪些,是否都避免了?

API 接口的请求

是否有集中管理?

是否超时处理?

是否有异常提示?异常提示的交互是否友好?

存储

是否封装了统一的本地存储?

文件目录结构(每个目录的职责)

职责是否清晰?组件的管理?

模块的实现描述(参考期货的例子)

是否有按照设计去编码

通信机制

异常处理

异常上报,关键节点是否有针对性处理?

提示信息是否友好,用户是否可理解?

是否都有空值校验?

性能

打包的静态资源拆分问题,单个文件不大于 200K

第三方库是否有冗余,是否可以去掉一些依赖

是否存在类似操作调用多次,比如 localStorage 的存取?应该用变量缓存

动画卡顿,用 transform 替代直接修改 top 等属性,或者用图的方式来实现

HTTP1.1 有 6 个请求并发的限制(thsi.cn),建议静态资源 combo 合并

离线包的使用(先去了解下)

复用

该函数方法是否可复用,是否应该抽取放到其他地方?

端技巧

移动端用 viewport 替代 rem.js,基金 19 年全部换成了 viewport;rem.js 官方不维护了,推荐大家换成 viewport

下限问题

名、净、硬、释、短

代码是否都符合排版规范,是否看起来很干净?

冗余代码、注释掉的代码、调试用的 console 等,是否都删掉了?

命名问题,是否见文知意?

硬编码(数字、英文、中文等)

注释是否加了?是否可理解?

长代码:应该抽取封装

Vue 钩子函数的逻辑:应该只进行流程控制

编码规范(下限问题)

我们精力不应该放在这部分内容上,因此这部分 CR 应该借助工具来处理掉。

接入 ESLint 和 SonarLint、Pettier 即可,我们要做的是保证大家都去遵循这些规范。

程序设计

可以让开发人员先展示方案设计文档,然后对着文档讲解程序实现。

审核人员需要确认的内容包括:

  • 方案是否合理
  • 代码实现是否是完全按照方案设计来写的

什么样才是好的方案设计?

可调试性

日志

状态码

异常捕获与处理

文件结构

模块化是否合理

性能

对象缓存复用

比如该做单例处理的,没有做处理。

业务特性

平台兼容性

封装特定业务逻辑

比如股市的开盘、收盘

代码的坏味道

重复代码

过长函数/方法/类

触发点:注释、条件表达式、循环、GUI 类的数据行为

特别是注释,看到注释就应该考虑提取函数了;且提取的函数应该基于这个注释去命名

缺乏数据对象的设计

前端开发是基于数据驱动行为的,所以应该有个数据实体的设计过程在里面。

这样也能避免长参数的问题。

if/else 和 switch/case

如果只是一个函数内部用到一次,那不用重构

如果多个地方都用到类似的 if/else 和 switch/case,则应该考虑用多态来优化了。

用过多的注释掩盖糟糕的代码

编程技巧

对方法分类:流程控制方法和逻辑实现方法

比如 Vue 的生命周期方法(created、mounted)就属于流程控制方法,里面就只应该进行其他方法的调用

对属性分类:计算属性、静态属性

比如我给海外组画横条柱状图的例子,里面我要计算圆角相关的 3 个点的坐标,总共一个图形元素有四个这样的点。

我一开始是这样设计的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Bar {
constructor() {}
pointsLeftTop: Points = <Points>{};
pointsRightTop: Points = <Points>{};
pointsLeftBottom: Points = <Points>{};
pointsRightBottom: Points = <Points>{};

drawLeftBar() {
// 计算四个点的坐标值,赋值给上面四个属性
this.compute();

// 应用四个属性,绘制图形
}
}

而整个图形总共由 3 个图形元素构成,实际上我会将这四个属性计算 3 次。那么这种情况,这四个属性就是计算属性,不应该作为类的属性,而是应该在具体方法内部中,通过局部变量赋值即可:

1
2
3
drawLeftBar() {
const { pointsLeftTop, pointsRightTop, pointsLeftBottom, pointsRightBottom } = this.compute();
}

GUI 类,将数据和行为提取出去

这是前端开发人员经常遇到的问题。

前端页面经常不复用,就只能做这样的抽取,保证结构清晰,方便维护。

JS 最佳实践

《JavaScript 语言精粹》

Vue 最佳实践

不同项目的 Review 侧重点

业务代码

组件库

模板

形成自己的模板,这样才能融入自己的思考。

不同框架的 Review 侧重点

Vue 框架

参考官方风格指南 — Vue.js

1、从 views 下面看起

2、分为 DOM、JS、CSS 三大块

2.1 DOM 中是否正确理解了 Vue 的设计,是否有按照官方推荐的最佳实践去写?

2.2 JS 中,重点看业务逻辑是否存在隐患,特别是数据请求的异常处理、数据存取等;可复用的内容是否有抽取为组件库

2.3 CSS 是否考虑主题风格

比如:

1
2
3
4
5
6
1、不和数据绑定的样式不应该写在DOM中,应该放在组件内部的style中,应用组件的地方填写class名,这样方便复用和统一管理
2、没有用到数据绑定的style,建议不要用v-bind,否则容易造成误导
3、常量命名不够直观,比如用了数字来区分不同的form表单元素
4、通用工具函数,比如isZh()、各种表单的处理函数,应该提取出去放到公共库里面
5、css的命名不统一,有驼峰也有短横杠
6、样式穿透不应该用全局样式(没加scoped)的方式,建议用Vue官方和CSS预处理框架推荐的穿透方式:v-deep、/deep/等

React

组件抽象是否合适?是否该抽成纯组件的没抽取?

状态数据放得是否合适(state & Redux)

如何 Review 其他组的人的代码

前置准备

了解对方的业务信息、主管评价、解决的核心问题

让对方提供能体现程序设计、解决核心难题的代码的目录

给我开通内网 GitLab 权限

Review 重点

程序设计

解决核心难题

如何对陌生代码做 Review-找到一个切入点

找到一个功能的入口文件,跟着程序流程走。

记录

2024.01.31

虚拟人 DYL:

1
2
3
4
5
6
7
8
9
10
11
12
CR的代码:vtuber-platform 仓库下的packages\PlatformSDK

总评:
代码具备技术深度,具备抽象封装思维,对底层功能和业务做了分离。


可读性:代码原子化,模块拆分很细致,结构整体清晰可读,类型定义比较完整,用到了一些新的JS特性
技术深度:代码复杂度不高,但是具有专业深度(渲染管线的重定义及修改,自定以后期处理的Shader模块等)
程序设计:程序设计思维良好,有做抽象和分层设计,针对渲染流程做了队列设计,对用户输入交互做了规范化设计
健壮性:异常情况做了显式处理
复用性:分层的方式拆分了业务和底层功能模块(底层渲染管线、中层通用组件模块、上层业务),复用度高
性能:资源在合适的时机进行了释放,避免了内存泄漏问题(应该是为了解决Unity导出的WebGL在移动端因为内存而崩溃的问题)

2023.12.28

失败的 Review,在不了解其业务的情况下,只能找问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
【SQX】
总评:整体代码没有亮点,代码质量普通T2水平

可读性&可维护性:
命名问题,大量无含义命名,如: key和key2变量命名
基本没有有效注释
默认手机号没有说明是否是测试数据
有很多数字、计算类硬编码,没有说明业务逻辑

程序设计:
函数副作用比较多
没有体现程序设计,业务流水账

健壮性:
接口异常处理不完善
接口异常没有上报
没有做不同平台兼容性处理

2023.12.25

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
【LC】
总评:

能通过技术手段解决业务复杂度问题,对基建和业务做了分离,程序设计能力较强,代码质量较高。

子项:

可读性:代码原子化,模块拆分很细致,结构和逻辑比较清晰
程序设计:项目业务复杂性较高,程序设计思维良好,拆分了业务和基座模块,提取了公共业务,有分层设计,复用度高;通过注入规范的方式保证了样式规范的可执行性;有设计调试方面的辅助功能;对事件做了规范化设计
健壮性:统一的异常上报、展示、错误码封装
复用性:微前端的设计保证了基座的通用性和业务子模块的复用性
性能:有做缓存设计,静态资源可以实现配置化按需加载

建议:
1、存在少量硬编码
2、支持html等接入模式,降低业务方接入成本
3、自研微前端方案,需要预先考虑版本迭代问题以及后续的AIGC结合问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
【MHB】
总评:

有想法,具有工具化思维,通过技术手段解决问题的能力较强,编码上有一些细节可以完善下。

子项:

可读性:代码命名清晰,函数折分和封装比较细致
程序设计:基于AST的方案设计比较巧妙,程序具备配置化能力,命令行参数设计全面,兼顾了调试输出需求等,功能和逻辑比较全面
健壮性:逻辑分支全面,考虑了各种异常情况
性能: 图片上传有考虑设计队列,并发执行

建议:
1、部分代码缺乏注释,可以酌情补充,提升可读性
2、将流程代码和实现代码进行分离,提升可读性transformJs.ts
3、if判断的条件较长,建议将条件抽象为不同的节点对象,这样更利于理解
4、优化嵌套较深的if/else
5、图片上传增加失败重试机制,提升健壮性
6、国际化转换这个功能比较通用,建议和其他组交流下,封装为SDK或者工具包,推广出去

2021.09.06

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ZFY:
代码没有抽离和封装,都放一个文件了(比如点击添加之后的动画、客户端协议、埋点、localStorage等等)
埋点建议可以和后端的数据键保持一致,方便后续维护;且埋点可以考虑将埋点id设置为DOM节点属性,通过事件监听来统一处理掉
有较多硬编码,建议抽取为常量
一些特定的计算和潜规则逻辑,建议增加注释,否则后期难以理解和维护
if/else较多,建议通过提取函数优化下
recommendCheck函数的if逻辑已经return了,没必要用else if

CJH:
标准化是解决可视化的关键,建议后续做类似大量的可视化图表的页面时,按照如下流程精简配置代码,提升维护性和开发体验:
1、跟设计师以控件(比如坐标轴、tooltip、线等)为单位确认设计标准
2、以控件为单位进行模块化配置
3、通过引入模块化的控件来组装成最终的图形
这样可以保证组件的UI交互一致性,且能大幅度减少配置代码,提升程序复用性和维护性、提升开发体验

参考资料

尤雨溪关于计算机基础的看法:

https://www.zhihu.com/question/35703265/answer/64229731

How to Make Good Code Reviews Better:

https://stackoverflow.blog/2019/09/30/how-to-make-good-code-reviews-better/

腾讯前端 CodeReview:

https://mp.weixin.qq.com/s/yyqGipUGMbfcLmXcQ2QBcA

长期软件开发:
https://berthub.eu/articles/posts/on-long-term-software-development/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
有些领域的软件会持续运行几十年,比如发电厂、起搏器、飞机、桥梁、重型机械的软件。它们可能几年都不会改动,然后推出一个新的大版本。

如果一个软件的开发周期长达几十年,需要长期维护,那么最好做到下面几点。

(1)尽量减少依赖。

软件的依赖项越多,长期越难以维护。依赖包括开发时依赖和运行时依赖,都是越少越好。

现在,很多软件在运行时会调用云服务,这也不利于长期维护。

(2)完备的测试用例。

测试对于重构、删除/添加功能,会提供极大的帮助。当你中断3年后,重新开始开发,测试也会让你快速了解系统。

(3)减少复杂性。

复杂性是软件开发的头号敌人,会让最好的程序员和团队都铩羽而归。

由于熵增定律和人类行为,除非你有意识地遏制,否则复杂性总是会增加。

因此,你需要养成严格的开发习惯:尽早和频繁地重构,删除不必要的或重复的代码,花时间简化。

(4)编写简单无趣的代码。

代码越简单越好,重点是代码的运行逻辑要显而易见。你永远不会后悔编写了简单的代码。

那些看上去很聪明、很高深的代码,会让后期的调试和理解变得复杂。特别注意那些高性能代码,只有当你正确理解它们时,它们才有效。

另外,那些眼下时髦、被热炒的明星技术,如果没有得到充分验证,也需要规避。

你最好只使用至少有10年历史的可靠技术。有一条规则是,某项技术的寿命与它们当前的年龄成正比,即存在越久的东西越可能继续存在。

(5)日志、遥测和文档

如果软件不是持续更新,开发者的注意力就会转到其他地方,不会立即跟进,所以需要有日志和遥测,能把运行过程记录下来。

文档则可以帮助我们理解几年前、甚至十几年前,编写原始代码时的想法。可能的话,记录所有事物,不仅仅是代码,还有理念、想法和为什么。

(6)团队

团队人员变化是很常见的。在许多地方,在一个团队呆三年,就已经很久了。虽然你可以用良好的文档和出色的测试,来抵消这种人员变化,但这很困难。

软件长寿的最简单办法之一,就是让开发成员长期稳定,保持工作十年。这意味着,你必须给你的程序员提供良好待遇,否则人们会离开。

在某些地方,软件是外包公司或咨询顾问写的,他们将代码丢到你的系统中后离开。对于长期运行的软件,这是非常糟糕的安排。

(7)开源

让你的代码暴露在外界的眼光,是保持代码可靠的好方法。一个有趣的事实是,只有质量良好的代码,人们才愿意对外分享,也就是说,如果不开源,人们会愿意在组织内部接受质量更差的代码。

开源代码有更高的标准、更多的测试,这是让代码不过时的绝佳机制。

make it run, make it fast, make it beautiful.