我总结了一些软件开发准则。在这些准则中,大多数都是以简化零碎为外围。在我看来,简略的零碎会更牢靠,更容易批改,而且个别更容易应用。当观点产生扭转时,我心愿更新它们。
1 剔除有效状态
我把这一点排第一,是因为我认为它是最重要、最弱小的准则之一。
你可能在定义类型时听到过这个词,但其实这个准则实用于所有与示意数据相干的中央——例如数据库设计。
它不仅能够缩小零碎的状态数量(从而变得更简略),还能缩小有效状态的数量!你的零碎不须要解决这些有效状态,因为它们在你的程序中实际上是不可示意的。
这不只是一个小技巧,它能够极大简化你的零碎,并防止出现各种类型的 bug。这有一些例子。
2 数据一致性让零碎更简略
对数据施加一致性规定,缩小了零碎须要解决的状态数量。这是从上一个准则派生而来的。
定义
这里说的是一致性的广泛含意:即数据遵循某些规定,并且在任意时刻都始终遵循这些规定。这一定义与 ACID 无关,但不要与 CAP 混同起来了。
规定能够是任何货色,例如,你的信用永远不能变成正数,或者私密的帖子不应该被其他人看到。它不仅限于外键或惟一索引,只管它们也是无效的规定。
和数据库一样,应用程序也能够通过应用 ACID 事务来增强一致性。如果能在数据库级别强制放弃一致性是最好的,但在理论中,对略微简单一点的货色来说,这样做并不常见。
实用倡议
任何限度或侵害一致性的行为都会导致复杂性。这就引出了以下这些实用的倡议:
让零碎更简略:
- 更少的数据库 (现实状况下是一个)
- 规范化,缩小冗余数据
- 一个“好的”数据库设计
- ACID 事务
- 更多的数据束缚
让零碎更简单:
- 多个数据库
- 冗余或非正规化数据
- 蹩脚的数据库设计
- 较少(或没有)数据束缚
当然,有时候让零碎变简单也是有正当理由的,我并不想让复杂性变成一个“恶浊的”词。请参阅前面的一个准则“杀鸡不要用牛刀”。
我认为这个准则是当今软件工程中最被低估的准则之一。一致性问题常常被忽视。很多问题,我敢说大多数问题,基本上都是一致性问题——数据不合乎某些冀望。
3 数据设计后行
这个问题,“代码还是数据?”,哪一个在 10 年后更有可能持续存在。
代码能够被丢掉重写,但数据很少会这样。
数据比代码更重要。代码的惟一目标是转换数据。
在设计新零碎时,最好先从数据库和数据结构开始,并在此基础上开发代码。要思考能够在数据上施加的束缚并施行它们,现实状况下是通过示意数据的形式进行的。
代码设计是数据设计的下一步。数据模型越简略、越统一,代码就会越简略。
你们把流程图给我看,但把表藏起来,我就一头雾水。你们把表给我看,通常我就不须要你们的流程图,它们会不言自明。—— Fred Brooks
蹩脚的程序员关怀代码。好的程序员关怀数据结构和它们之间的关系。—— Linux 之父 Linus Torvalds
4 杀鸡不要用牛刀
这是软件开发人员最常犯的谬误。
这个准则是说,当你在做须要付出复杂性代价的衡量时,要确保衡量的必要性失去教训证据的反对。
常见谬误:
- 试图构建一个简单的“可伸缩”零碎,能够伸缩到你可能永远都不须要的规模。
- 在不思考需要或老本的状况下,让服务尽可能地小。
- 在非性能瓶颈的中央优化性能,减少不一致性或复杂性。
倡议:
- 尽可能从最简略、最正确的零碎开始
- 对性能进行度量
- 如果不能解决理论问题,就不要付出复杂性代价或违反其余准则。
- 有些优化能够不进行度量,因为它们的老本非常低或为零。例如,为了保障你想要执行的操作具备你想要的性能,应用正确的数据结构。
- 确实,有时候教训自身就能通知你是否做出了正确的衡量。但如果你能证实,那就更好了。
- 当你必须做出抉择时,请抉择正确性和简略性,而不是性能。
- 在某些状况下,正确而简略的代码是性能最好的代码!
真正的问题是程序员在谬误的中央和谬误的工夫花了太多的工夫在放心效率上。过早优化是编程中所有(或者至多是大部分)邪恶的本源。——计算机科学家 Donald Knuth
5 防止为了部分简略性而减少全局复杂性
也就是防止为了让零碎的一部分变得更简略,而导致整个零碎变得更简单。
这种替换通常是不平等的。谋求部分的简略性会导致全局复杂性的减少,而且是数量级的。
例如,应用较小的服务能够让这些服务变得更简略,但一致性的升高和对更多过程间通信的需要让零碎变得更加简单。
6 辨认外在的复杂性
有时候事件自身就很简单,你不能把问题简单化。
任何这样的尝试都只会让零碎变得更加简单。
7 应用的技术越少,零碎就越简略
深刻了解一小部分技术要比只是外表了解很多技术好。
更少的技术意味着更少的货色要学习和更少的运维复杂性。
8 集中精力学习概念,而不是技术
不要太关怀技术的简单细节,因为你能够随时查阅它们。你要学习底层的基本概念。
技术会变动,概念却是永恒的。你学到的概念将被用在更新的技术中,你就能够更快地学会新技术。
例如,不要太关注 React、Kubernetes、Haskell、Rust 的外表细节。
重点学习:
- 纯函数式编程
- 关系型模型
- 标准的办法
- 逻辑编程
- 代数数据类型
- 类型类 (通用的和特定的)
- 借位查看器 (仿射 / 线性类型)
- 依赖类型
- Curry-Howard 同构
- 宏
- 同像性(Homoiconicity)
- VirtualDOM
- 线性回归
- ……
9 代码一致性很重要
有时候,具备一致性的代码比“正确”的代码更重要。如果你想要扭转代码库中某些代码的行为,就要批改它所有的实例。否则的话,就只能忍耐。
代码的可读性更多地与一致性(而不是简略性)无关。人们通过模式识别来了解代码,所以请反复 (和记录) 模式!
10 分享准则很重要
如果你和队友之间的独特准则越多,就能越好地在一起工作,而且你会越喜爱和他们在一起工作。
11 附录:不一致性导致的复杂性
这是我能想到的最简略的例子,心愿能毫不费力地与事实问题分割起来。
假如一个数据库有两个布尔变量 x 和 y,你的应用程序有一个规定,即 x = y,能够通过应用一个事务批改这两个变量来执行这个规定。
如果这个规定被正确执行,那么数据只有两种状态:(x = True,y = True) 或 (x = False,y = False)。
基于这个规定的函数“toggle”就非常简单。你能够读取其中一个值,并将两个值都设置为反向值。
当初,假如你将这两个变量放到不同的数据库中,并且不能再被一起批改,那么会产生什么?
因为你不能确保 x = y 的一致性,所以数据能够有两种以上的状态:(x = True,y = False) 或 (x = False,y = True)。
- 如果你的零碎处于这些状态中的一种,你应该应用哪个值?
- 当处于其中的一种状态时,“toggle”函数的行为是怎么的?
- 在写入新值时,如何确保两次写入都胜利?
这些问题没有正确的答案。
当然,如果咱们一开始就遵循“剔除有效状态”的准则,那么将只有一个变量!
以上就是本次分享的所有内容,想要理解更多 python 常识欢送返回公众号:Python 编程学习圈,发送“J”即可收费获取,每日干货分享