恶性功能 (Wicked Features)
原始链接: https://www.seangoedecke.com/wicked-features
为什么在大型科技公司开发软件这么难?1
这是因为有一小部分“恶性功能(wicked features)”主导了整个系统。假设你在开发一个待办事项 App,给待办加上“上传图片”可能算个大功能,但这不算“恶性功能”。但是,如果要把你的 App 做成网页版和独立客户端双版本,那就是个“恶性功能”了。区别在哪?恶性功能指的是:每次你开发其他任何新功能时,都必须顾及到的功能。
常见的恶性功能包括:
- 增加一种新的用户类型
- 提供私有化部署(On-premise)版本的 SaaS
- 将客户数据分片(Sharding)存储到不同的数据库
- 支持严格的数据本地化(Data locality)
- 支持客户在不同区域间迁移账号数据
- 国际化(I18n,将界面文字翻译成客户的母语)
假设以上功能你都做完了,现在你要开发“上传图片”功能。你得考虑:新的用户类型能发图片吗?平时图片存在 S3 里,那在没有 S3 的私有化部署环境里,图片存在哪?如果客户数据分片了,你的 images 数据表有跟着正确分片吗?每个用户所在的区域都有对应的 S3 存储桶吗?如果客户跨区域迁移数据,图片能自动跟着迁移吗?你有没有把所有跟“上传图片”相关的新文案提取出来,并预留好翻译的时间?
为什么恶性功能很难搞?
恶性功能就像密码游戏(Password Game)。在这个游戏里,新规则(比如“你的密码必须包含密码长度的数字”或“密码中所有数字相加必须等于200”)不能孤立对待。你必须把它们当成一个整体来解决,因为满足了一条规则,往往会打破另外几条。密码游戏还算仁慈,会立刻告诉你打破了哪条规则以及原因。但在大型技术项目中,你通常是通过用户客诉或生产事故才会发现问题。
这也是工程师常常低估工作量的一个普遍原因。大家很容易忘记一两个恶性功能,从而导致实现过程变得复杂,然后在别人问“那 X 功能怎么办?”时傻眼。对于刚入职、还不了解系统里有哪些恶性功能的新人来说,更是如此。公司里的“老员工”之所以有价值,很大程度上就是因为他们对所有的恶性功能了如指掌。
这是技术不行吗?
恶性功能纯粹是因为设计太烂吗?代码写得好一点能不能避免?有时确实可以。哪怕是普通功能,只要代码写得足够烂,也能变成恶性功能2。但我认为有些需求天生就是恶性的。
比如“让 SaaS 支持私有化部署”。不管你多小心,哪怕你把构建流程做得对私有化极其友好,让你再也不用维护两个版本——“必须小心翼翼地维护这个构建流程”本身,就是一个你在未来修改构建流程时必须时刻牢记的恶性功能。
再比如“添加一种能做 X 但不能做 Y 的新用户类型”。即使你把权限系统重构得很完美,再也不用写 if isUserTypeX(user) 这样的代码。但“未来的新能力必须适配你自己发明的这套权限框架”本身,也是个恶性功能。
这些功能的“恶性”不在于代码实现,而在于核心的业务模型。它是产品逻辑层面的恶性。无论代码多优雅,你都必须回答上面列举的问题(比如“所有用户类型都能用我正在写的这个新功能吗?”)。
为什么要开发恶性功能?
如果能避开,公司肯定不想做。问题在于,那些付费能力最强的用户非常喜欢恶性功能。支持私有化部署的 SaaS 通常利润极高,因为这迎合了那些财大气粗、愿意支付高昂企业软件合同价(而不是便宜的 SaaS 订阅价)的客户。同样,数据本地化和分片功能也备受大客户青睐。
但有些恶性功能是懒惰或能力不足的开发者搞出来的。比如,有些公司只有 5 个用户,工程师却搞了一套完整的数据分片系统,仅仅因为觉得这样“好玩”。我还见过有些工程师因为想不到更好的方法(或者觉得这就是“正确”的做法)而硬造出恶性功能。比如给一个只准备支持单语言的 App 提取所有的界面文案,就是一个典型的低回报案例。
作为工程师,你能产生的最大价值之一,就是尽量阻止团队开发不必要的恶性功能;如果非做不可,那就通过合理的代码结构来限制它的破坏力,始终在心里问自己:“这会不会影响以后在同一个系统里开发完全不相关功能的同事?”
总结
- 恶性功能是每次开发其他新功能时,都必须顾及到的需求。
- 它们会极大地增加开发复杂度和沟通成本。
- 有些恶性功能是不可避免的,特别是当你要把产品卖给高付费的大企业客户时。
- 另一些则是由于过度工程、盲目教条或品味糟糕造成的“自作自受”。
- 优秀的工程师会控制其破坏范围:阻止不必要的恶性功能,并把必要的恶性功能隔离好,防止它们污染整个系统。
如果你喜欢这篇文章,可以考虑订阅我的邮件更新,或者[在 Hacker News 上分享](news.ycombinator.com/submitlink?… features)。这里有一篇相关标签的预览文章:
大型遗留代码库中工程师常犯的错误
在大型遗留代码库中工作是软件工程师最难学的事情之一。你无法提前练习(不,开源项目给不了你同样的经验)。个人项目也教不会你,因为它们必然是小巧且从零开始的。顺便说一句,我所说的“大型遗留代码库”是指:
我在这些代码库里工作了十年。以下是我希望自己一开始就能知道的经验。
继续阅读...