- 本文的有一些哲学是摘自互联网中他人所撰写的,还有一些是与同行探讨获得的建议,其中一部分建议来自 bolasblack
- 本文主要针对多人协作开发的大型项目的场景,并且是基于 Magickbase 的一些项目进行的思考
- 本文默认读者是具备一定英文读写能力和开发能力的开发者
- 不要只是去背下这些规则,而是要尝试理解它们的意图(解决什么问题)和手段(怎么解决)
-
思想很重要,思想会指导你如何开发、遇到问题时做出怎样的选择(做决策)
-
编程是为了解决问题,所以解决问题的质量、速度就是最重要的核心指标
-
一切设计模式、开发流程,都是为了提效、提质或者两者之间平衡,所以开发时带着这些问题去思考是否要做某些事情
-
高内聚,低耦合对于可维护性、可扩展性有很大影响,所以设计代码时要好好思考
-
我们一共有哪些抽象层级,新的这段代码的抽象层级应该是在哪,是否合理?
-
它的影响(耦合)范围有多大,能否降低?
-
-
在开发(修复)一个功能时,读代码与写代码的时间比例往往超过了 10 : 1,这意味着提升易读性也会提升编写新代码时的速度
-
避免 bikeshedding(浪费时间和精力讨论无意义的或意义不大的技术问题),将注意力集中在重要的事情上
-
尽量遵守规范的开发模式
-
规范的实现是为了能更好的利用社区生态,让代码能与社区的库和工具链生态互动
-
使自己与他人拥有共同的心智模型,减少 bikeshedding,合作起来会更容易(提效)
-
-
工程避免不了做脏事的情况(比如各种兼容、底层的 bug),好的工程会让这些脏事的处理更加合理
-
世间无穷的现象都可以用有限的原理解释,如果只停留于现象就会陷入经验主义,这就是为什么要学习原理(不管是编程领域还是其他领域)
- 了解一项事物的来龙去脉是我们做出创造性工作的关键
-
通过 rebase 整理 commit 来提升 reviewer 的效率和 review 出问题的概率
-
通过文档约定或自动化工具来统一开发者们的代码风格和开发哲学来避免 bikeshedding
-
降低一些代码设计的耦合程度,让内部的或者隐式的耦合改为通过双方的接口去显性的处理
-
需要自定义组件外观或行为时,应通过接口(属性)显式的达到目的,不应该通过组件未暴露的实现细节(如 data-* 属性)去实现。 如果利用子组件内部细节来实现自己的功能,会导致隐式耦合。
-
CSS 可以通过 data-* 的属性来获得一些 JS 层面的变量,但 JS 不应该直接依赖 data-* 来获取数据(比如点击事件从元素上获取 data-* 字段),可以通过其他方式获得,或者显式的为 data-* 提供类型。
-
-
提升一些代码设计的内聚性,比如
-
组件拆分为多个子组件时,这些子组件预期上是仅自己使用的,那么它们应该内聚在这个组件的文件夹下面,而不是提升到 components,那样做的话会改变它的抽象层级。
-
某个组件仅自身使用的函数、资源,没有特殊原因都应该内聚在组件自己的文件夹中,避免提升层级。
-
组件自身的 i18n 也应该内聚在自己的文件夹下,只有公共的 i18n 才提升。
-
-
加强使用 storybook 的程度,逐渐导向 storybook 驱动开发,这会让组件在开发时就偏向于低耦合
-
尽量缩小 CSS 的影响范围,这对于提升可维护性和可读性有较大帮助,也会避免预料之外的代码行为
-
避免使用大范围的选择器
- 比如标签选择器,可以用 classname 替代,或者通过直接子级选择器来约束影响范围
-
避免使用 important,这会造成不可预估的影响范围,并导致后续的代码如果要覆盖它也需要使用 important,如果后面的代码 important 也无法覆盖了,仍然会回归到基础的选自器级别、排序等规则。
-
考虑使用原子化 css 的可能性,或者约定一套规范,来限定开发时使用的样式,避免 css 造成的耦合,规范比如
- 组件一定有一个包裹的外层,并通过允许传入 style、class 或其他任意暴露出能够控制的接口去调整大小、位置、变换等样式。组件内部非特殊情况不允许对包裹层做位置和大小处理,这也会让组件开发趋向于响应式。
-
避免随机制定 zIndex 的值,应该有一个标准的层级值设计,预计 3 个不同的层级就足以完成普通的项目
-
设计样式时尽量自适应,避免使用固定的宽高值
-
-
代入思考一个开发者可能会以什么方式阅读代码,然后按照这个方向去提升他的效率
- 确保代码是尽量线性的,而不是从 a 跳到 b 跳到 c,让阅读时发生的跳转次数尽量少
-
代码应该优先表现出它要做什么(目的、意图),为什么要这么做,最后才是怎么做
-
当一段代码的意图不够明显时,可能是
-
多段代码的边界混淆在了一段代码中,要理清楚它们的边界将他们拆分开来
-
名字或注释不够清晰,造成了理解不畅甚至误导
-
-
当一段代码需要注释时,应先确认它是否真的有必要注释,有可能是代码写的不够清晰,而不是业务过于复杂
-
举例(非实际的场景)
-
bad code
if (user.level > 10) ...
good codeconst isAdmin = user.level > 10; if (isAdmin) ...
-
bad code
function setUserLevelTo10(user) { user.level = 10 }
good codefunction setUserToAdmin(user) { user.level = 10 }
-
-
-
做了某个技术决策(或其他决策)后,好好想想会投入多少成本,有哪些收益,而不是按感觉来
-
提供一些个人工作流上的建议
-
TODO 可能会有很多 git 相关的建议