谈谈技术选型

2017 年 2 月 05 日

本文的主题是技术选型,作者总结了他见过的各种不靠谱的技术选型方式,比如有的团队会根据社交媒体上的讨论来决定选择哪种架构,也有的团队会跟风走,哪个热门就选哪个。但总体来看,这样简单粗暴的方式一定会为未来埋下隐患。那为什么这样说?我们应该如何做正确的选择?且听作者细细道来。另本文译者余晟,曾经是主力程序员、技术文章的写作和翻译爱好者,现在在沪江负责研发和软件架构。欢迎关注他的个人公众号“余晟以为”,了解一位非典型 IT 人员对世界的看法。

软件开发团队所做的软件架构或技术栈的决策,很多并没有经过踏实的研究和对目标成果的认真思考,而是不准确的意见、社交媒体的信息,或者就些是“热闹”的玩意。我称这种作派为“热闹驱动开发(Hype Driven Development,HDD)”,眼见它的危害,我赞成更专业的做法,就是“脚踏实地的软件工程”。下面我们一起看看 HDD 的来龙去脉,想想能如何改进。

新技术带来新希望

开发团队把最新最热的技术应用到项目里,这样的情景你见过吗?有人是因为读到了相关的博客,有人是看到了 Twitter 上的潮流,还有人是刚刚在技术大会上听到了关于某门技术的精彩演讲。不久,开发团队就开始采用这种时髦的新技术(或者软件架构设计范式),结果他们却没法更快(就像之前说的那样)开发出更优秀的产品,反而身陷囹圄。开发的速度降下来了,信心受挫了,后续版本的交付也出问题了。有些团队甚至干脆专心修 bug,停止开发新功能。他们“只需要多花几天”就能把事情搞定。

热闹驱动开发

热闹驱动开发有很多流派,也有很多渠道介入大家的项目:

  • Reddit 驱动开发。在选择技术、架构、设计方案时,团队和个人的决策依据是知名博主的文章,或者 Reddit、Hacker News、博客、Twitter、 Facebook、GitHub 以及其它社交媒体上的热门信息。
  • 技术会议驱动开发。仔细观察观察,参会回来的家伙们有什么表现。他们听了演讲兴致高涨。然而这是双刃剑。他们没有做足够的研究,就开始使用最新最热的类库、框架、架构范式,于是可能踏上通往地狱的高速公路。
  • 嗓门驱动开发。有人整天谈论新框架 / 类库 / 技术,他自己其实没有实际经验,但是反复念经终于让团队决定采纳他的意见。
  • Gem/ 类库 / 插件驱动开发。在 RoR 社区里特别流行这种情况,有时候我会发现一个 gemfile 太长,唯一比它更长的只有程序启动时的装载时间。这种流派源自下面的观念:Rails 里的每个问题都应当有个 gem 来解决。有时候分明只要自己动手写几行代码就能解决,但是我们还是一个劲地添加类库 / 插件 /gem/ 框架。
  • 我还希望提到热闹驱动开发的一个常见流派,StackOverflow 驱动开发。开发人员从 StackOverflow(总之就是互联网上)拷贝代码,而没有真正弄懂这些代码。

HDD 就是开发团队自掘坟墓

凑热闹的问题是:它很容易导致错误决策。无论是糟糕的架构决策,还是糟糕的技术栈决策,对团队的影响都常常持续数月甚至数年。最坏的结果是造成极其严重的软件工程问题,只能推倒重来。但推倒重来而成功的案例几乎没有。

一切罪恶的根源似乎都是社交媒体——新观点传播得太快,都还没来得及经过检验。大家还来不及细想有哪些利弊,这些观点就已经传播开了。

凑热闹的起承转合

大多数凑热闹的过程是相同的,像下面这样:

第一阶段:真实问题和解决方案

热闹的来源是,某些公司真的遇到了问题。这些公司里的开发团队认为,现成的技术栈、流程、架构并不能解决这个问题,必须自己动手。所以他们研发了新的框架、类库、范式,问题迅速解决了。

第二阶段:宣示、推广、包装关键词

团队热衷于向他人展示自己的成果。很快他们就发布了博客文章,也去技术会议上演讲。这些问题通常是有难度的,所以解决方案是有分量的,结果也是很可观的,开发团队对此很自豪。其它人也开始对这项新技术有了兴致。唯一的问题是,并非所有兴致勃勃的人都能彻底理解问题本身和解决方案的细节。毕竟,问题有难度,解决方案也有分量,所以不是一条推文、一次碎碎念、甚至是一篇博客就能讲清楚的。利用博客文章、技术大会的主题演讲之类的社交工具,原始信息就很容易走样。

第三阶段:狂热现身

HDD 阴影下的开发人员都会阅读博客、参加技术会议。然后,世界各地的开发团队都开始使用新技术了。因为信息已经走样了,所以有些人会在框架问题上做草率的决定。哪怕新框架没有解决任何具体问题,开发团队仍然期望新的框架会带来帮助。

第四阶段:心灰意冷

新鲜劲头过去了,新技术并没有给团队带来期望的改进,反而增加了很多额外的工作。大家得重写很多代码,花不少时间专门学习。工作的速度慢下来,管理者也没耐心了。大家都感觉被骗了。

第五阶段:反省领悟

最终团队做了复盘,认清了追逐这项新技术的代价,也认清了新技术适合解决的问题。大家都变聪明了,直到再次凑热闹为止。

HDD 举例

来看看几个热闹驱动开发的例子,看看它是怎么发生的。

举例 1:React.js

  1. Facebook 遇到了一个问题,Facebook 自己的复杂单页面应用里会出现各种状态改变的事件,必须追踪到发生了什么,并且保持状态的连贯一致。
  2. Facebook 用几个时髦的词包装新范式:函数式、虚拟 DOM、组件。
  3. 追逐热闹的人说:Facebook 创造了未来的前端框架。我们现在就把一切用 react 重写吧。
  4. 等等!要做的工作很多,但这项投资看不到什么短期回报。
  5. React 非常适用于包含很多实时通知的复杂单页面应用程序,但是对简单应用来说,它不见得合适。

举例 2:TDD 被 DHH 杀死了

  1. David Heinemeier Hansson(DHH,Ruby on Rails 框架的创造者)意识到,Rails 的框架里没有对 OOP 支持很好的架构,所以很难做测试驱动开发。于是他做了个现实的选择:不要提前写测试代码。
  2. DHH 的博客和会议演讲引发了热潮。关键词是:TDD is DEAD。
  3. 忘了测试吧!我们的领袖说过。一个测试也不要写。我们可不是在假装,而是在虔诚地执行。
  4. 等等!以前一些能正常运行的代码现在都出问题了。我们新写的代码错误百出。
  5. TDD 无所谓生死。TDD 是需要权衡的,权衡因素包括 API 变化的风险、既有设计、参与者的水平——Kent Beck。

举例 3:微服务

  1. 庞大的单体系统很难扩展。在某个时候我们可以把它拆成多个服务。如果各个都用 QPS 之类的指标来衡量,扩展就容易很多,也更容易拆分给多个团队。
  2. 热闹关键词:可伸缩性、松耦合、单体系统。
  3. 让我们重写所有的服务!我们的单体系统已经是一锅粥了。得把所有东西都拆成微服务。
  4. 见鬼!现在系统开发的速度变慢了,部署的难度提高了,我们还花了不少时间在多个系统之间追踪 bug。
  5. 微服务需要团队有充分的 DevOps 能力,还需要权衡增加系统和团队扩展性,保证投入划算。在你遇到严重的规模问题之前,这样的投资是超前的。微服务是提炼出来的,不是重写出来的。按照 Martin Fowler 的说法,微服务的门槛可不低。

举例 4:NoSQL

  1. 在应对高压力和处理非结构化数据时,关系型数据库有不少问题。全世界的团队都在研究新一代数据库。
  2. 热闹关键词:可伸缩性、大数据、高性能
  3. 我们的数据库太慢,而且容量不够。我们需要 NoSQL。
  4. 我们还需要联表查询?这可不行。简单的 SQL 操作现在都越来越有挑战了。开发速度越来越慢,我们的核心问题还没解决。
  5. NoSQL 是用来解决特定问题的(要么是海量的非结构化数据,要么是非常高的负载)。如果专业水平足够高,关系数据库也是应对高负载和处理海量数据的好工具。非得使用 NoSQL 的情况,在 2016 年仍然不多见。

举例 5:Elixir 和 Phoenix (或者是你喜欢的语言 / 框架组合)

  1. RoR 之类的 Web 框架不能很好地应付高性能应用、分布式应用、Websockets。
  2. 热闹关键词:可伸缩性、高性能、分布式、容错性。
  3. 噢,我们的系统太慢,我们的聊天系统不是可伸缩的。
  4. 才发现,学习函数式编程和分布式解决方案没那么容易,我们进展真慢。
  5. Elixir 和 Phoenix 是很优秀的框架,但学习成本太高。如果你确实需要高性能的系统,它的益处要很长时间才会显现。

推而广之

在软件开发的小小天地里,已经有太多领域是热闹非凡的了。在 JavaScript 里,几乎每天都有新框架诞生。Node.js(关键词:事件编程),React 编程,Meteor.js(关键词:共享状态),前端 MVC,React.js…… 你可以随便举例。软件工程领域里新概念也层出不穷:领域驱动开发,六边形架构理论,DCI 架构(数据 - 场景 - 交互)。你最喜欢哪一种呢?

正面的例子

如果我们不能相信网上的言论或是其他人的说法,那如何做出聪明的选择?下面是一些好的建议:

先测试、研究,再决定

  • 快速搭建原型,不要从博客学习,而要从经验学习。针对新技术提供的功能,在决定采用之前花一两天搭个原型,然后组织大家分析利弊。你可能会遇到若干能彼此替代的技术,可以让团队里不同人用不同的技术来搭原型。
  • 黑客马拉松,这也是不错的办法,它让大家真正感受到不同技术的代价。对所有兼具风险和诱惑力的技术,都让整个团队花一两天来把玩。这会让大家自主做出聪明的选择,根据自己的经验来决策。

何时开始?

  • 原则上说,应当选择投资回报巨大的时间点开始。大多数技术是用来解决特定问题的。你遇到了那个问题吗?那个问题重要不重要?会不会节省很多时间?新技术带来的好处能不能抵消学习成本和重新的成本?如果我们的开发速度从一开始就降低到正常水平 1/2 甚至 1/4?想想新技术还值得吗?
  • 优秀的团队有更多自主权——一些团队确实比其他团队更快出成果,他们也更容易厌烦自己手头的工作。这些团队可以更多更快地引入新技术。但这不是省略快速搭建原型或者黑客马拉松的理由。相反,如果这样的团队在交付上遇到了麻烦,一定要加倍小心。

找到对的人

  • 有良好技术背景的人——那些人了解不同的范式,理解编程的理论(算法和并发),受过良好工程文化熏陶,这样的人很少去凑热闹。
  • 有经验的人——年轻的开发人员更喜欢凑热闹。如果有多年的开发经验,见过许多技术,踩过许多坑,在技术决策时就更容易做出客观的判断。
2017 年 2 月 05 日 18:007369

评论 1 条评论

发布
用户头像
经验之谈!
2019 年 04 月 29 日 09:56
回复
没有更多评论了
发现更多内容

架构师训练营第四周作业

听夜雨

极客大学架构师训练营

Week 3学习总结

balsamspear

极客大学架构师训练营

自学编程,看书还是视频?

沉默王二

程序员 读书 自学编程 视频

Spring 事务,你真的用对了吗(上篇)?

双儿么么哒

Spring MVC

架构师训练营 1 期 -- 第四周作业

曾彪彪

极客大学架构师训练营

甲方日常 32

句子

随笔杂谈

典型的大型互联网应用方案

garlic

极客大学架构师训练营

架构师训练营第四周学习总结

听夜雨

极客大学架构师训练营

架构师训练营第四周作业

我是谁

极客大学架构师训练营

视读——沟通的艺术,看入人里,看出人外(第四章)

双儿么么哒

Linux的信号

菜鸟小sailor 🐕

c++

Flink时间服务和计时器-6-5

小知识点

scala 大数据 flink

十五、深入Python输入和输出

刘润森

Python

每天都要写吗?

Nydia

第四周总结

Geek_ac4080

给新入职工程师的10条建议

supernova

管理 职场 工作方式

第四课系统架构课后作业

Geek_michael

极客大学架构师训练营

大区块链的必然性

CECBC区块链专委会

区块链技术

三步法解析Express源码

执鸢者

面试 前端 Node Express

迭代开发中的微服务拆分

码猿外

架构 微服务 微服务拆分 架构演进

一次用户故事地图之旅

Bruce Talk

敏捷开发 用户故事 Product Owner 用户故事地图

十六、深入Python字符串

刘润森

Python

week04作业

追风

架构师一期

第11周总结

Vincent

极客时间 极客大学

如何设计大型互联网系统架构

天天向上

极客大学架构师训练营

Week 3命题作业

balsamspear

极客大学架构师训练营

手把手教你分析Mysql死锁问题

捡田螺的小男孩

MySQL 死锁

用Python绘制地理图

计算机与AI

Python 绘图

聊聊「测试分工和测试时间」

清菡

测试

第11周作业

Vincent

极客时间 极客大学

大型互联网系统常用的技术方案

天天向上

极客大学架构师训练营

谈谈技术选型-InfoQ