You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
12 KiB
Markdown

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 22 | 如何为项目做好技术选型?
你好,我是宝玉,我今天分享的主题是:如何为项目做好技术选型?
在架构设计过程中,肯定绕不开技术选型这个话题,大到架构、框架、语言选择,小到用什么组件、设计模式。
这也是最容易引起争议的话题无论是现实中还是网上到处有各种语言、框架的争论Java好还是C#好前端框架是Vue好还是React好跨平台手机开发该选React Native还是Flutter……
虽然这种争论从来没什么结果,但当你做技术选型时,却很容易受到这些信息的干扰,尤其是你身边有几个某种语言或者框架的狂热粉丝的话,他们会不停地在你旁边吹风,说他喜欢的语言或框架的各种好处。
包括我们自己做技术选型时也会有很多个人偏好在里面。比如我以前对微软技术栈特别熟悉也特别喜欢做技术方案就会偏向微软技术栈我喜欢React做前端技术选型也会偏向React的方案。
通过上一篇架构设计的学习,我们知道,**架构设计的主要目标,是要能低成本地满足需求和需求变化,低成本地保障软件运行。**然而对技术的个人偏好,很可能让你在技术选型时,忽略架构设计的目标,导致满足需求的成本变高,或者运行成本居高不下。
所以今天,我们一起来探讨一下,在软件工程中,怎么样才能避免这种选型的倾向性,科学客观地做好技术选型。
## 技术选型就是项目决策
技术选型,就是在两个或者多个技术方案中选择适合当时项目情况的方案。**技术选型看起来是个技术的选择,但其实是一个和项目情况密切相关的项目决策。**
在项目中,除了技术上的选型,类似的选择也有很多,比如说产品设计中:某个功能该不该加?该选哪种动画效果?比如制定测试方案的时候,选择哪一种压力测试工具?选择哪个测试框架?这些选择,本质上就是一种项目决策。
要做好技术选型,就是要做好项目决策。那么怎样从做项目决策的角度来选择合适的技术选型呢?
#### 受制于时间、范围和成本的约束
我们在《[08 | 怎样平衡软件质量与时间成本范围的关系?](http://time.geekbang.org/column/article/85302)》中学习了项目金三角的理论,也就是项目受制于三个因素:时间、范围和成本。
技术决策作为一种项目决策,也要受制于时间、范围和成本,在决策时不能超出这三者的边界。
比如说在项目时间紧时,决策上就要偏向能提升开发速度的技术;在成本吃紧的情况下,要多用成熟的免费的框架、工具,避免用贵的商业软件或者自己造轮子提升成本;在范围大、需求多的情况下,架构就要考虑如何能简单快速完成需求。
还要注意一个问题就是随着项目的推进,其实制约项目的三个因素一直在动态变化,需要及时根据情况调整技术决策。
举个例子来说2004年飞信PC客户端做第一个版本的时候那时候主要的约束是成本只有一个C++程序员,这个程序员会用什么技术就用什么技术,谈不上选型。
到2005年做第二版本时有了几个人但是时间上要求快所以就选择了能提升开发速度的C# Winform技术方案。到2008年做第三版时人手充裕了也没有进度上的压力这时候主要就追求用户体验、性能所以又选择了C++的技术方案重新开发。
#### 要分析可行性和风险
我们在专栏前面的内容中学习了可行性研究和风险管理的知识。如果在项目决策时,不考虑可行性,不预估风险,就极有可能导致决策失败。
就像在《[09 | 为什么软件工程项目普遍不重视可行性分析](http://time.geekbang.org/column/article/85730)》那篇文章中的案例技术选型时没有考虑到License的法律问题导致项目失败。还有在《[14 | 风险管理不能盲目乐观凡事都应该有B计划](http://time.geekbang.org/column/article/87787)》那篇文章中的案例选择React时没有考虑到可能导致的风险导致项目延迟。
当然,换个角度说,如果在项目中,选择新技术的风险可以接受,也能满足时间、成本和范围的约束,还可以达到丰富团队技术栈的目的,那也是可以的。
#### 要考虑利益相关人
在做项目的决策时,如果决策时没有人代表利益相关的人,就可能会做出不考虑他们利益的决策。
选择适合的技术选型时也要考虑到这一点。比如说光顾着选用新酷的技术而没有考虑客户的利益导致成本增加进度延迟比如在选择UI组件时只想着哪个调用方便而不考虑产品经理的利益导致产品体验不好。
#### 项目决策中常见的坑
无论是技术选型也好,还是其他项目决策,经常会遇到一些坑,一不小心就会踩上去。
* 把听到的观点当事实
现在网上充斥着各种观点一个React的粉丝会给你描述React的各种优点而不会告诉你学习曲线有多陡峭一个不喜欢微软技术的程序员会把.Net贬低的一文不值一篇鼓吹Mongodb多好的文章可能是收了钱的软文。
每个人都有自己的观点没有问题,但是不能把观点当成事实,尤其是在做决策之前,至少需要验证一下。
* 先入为主,有了结论再找证据
在做技术选型或者项目决策时还有一个问题就是可能心中已经有了答案后面所谓的决策不过是寻找有利于自己答案的证据。比如说我特别喜欢React在做技术选型时就会拼命寻找对React有利的数据作为证据这其实可能会导致结论并不客观。
所以当你选择技术选型的时候,要像做项目决策一样思考分析。要想你的决策能正确,就要注意项目中范围、时间和成本的约束,要分析可行性和风险,要考虑利益相关人,最后还得要避开常见的一些坑。
## 如何做好技术选型?
现在我们知道了要像做项目决策一样,去选择适合自己项目的技术选型,那么具体该怎样做呢?
我们在《[02 | 工程思维:把每件事都当作一个项目来推进](http://time.geekbang.org/column/article/83277)》中学习了工程思维和工程方法,在《[12 | 流程和规范:红绿灯不是约束,而是用来提高效率](http://time.geekbang.org/column/article/87129)》中学习了流程规范。对于技术选型问题,我们一样也可以考虑借鉴工程方法设计一套流程,基于流程去做技术选型或项目决策,来保证整个过程能科学可行,充分考虑项目决策的特点,避开常见的坑。
对于技术选型包括项目决策类的问题,我们可以分成:问题定义、调研、验证、决策这几个阶段。
#### 问题定义
在问题定义阶段,需要搞清楚两个问题:为什么需要技术选型?技术选型的目标是什么?
以前看过一个技术漫画《[The problem is not the tool itself](http://www.commitstrip.com/en/2014/06/03/the-problem-is-not-the-tool-itself/)》。
“我想我们已经达到MySql的极限非常慢…我们得面对数据巨大的事实”“我们应该迁移到NoSQL我已经准备了一个3个月的战斗方案瞧瞧这”“框架重构、培训、内部工具升级”“等等让我检查一下”“你忘了建索引加上索引可以让速度提升20倍”“忘记索引你可真行。”
[![](https://static001.geekbang.org/resource/image/fe/f3/fe1f72418d928840b0412e25e734b3f3.png "图片来源Commitstrip")](http://www.commitstrip.com/en/2014/06/03/the-problem-is-not-the-tool-itself/)
这种事情在软件项目中可不少见,很多时候为了解决问题引入一个新技术,然而真的需要吗?也许我们可以基于现有技术方案进行优化,根本就不需要引入一个新的技术或新的框架。
还有一个就是技术选型的目标需要明确,你的技术选型目标是为了使用新酷技术呢?还是为了提升开发效率?还是为了降低开发成本?
**只有明确了技术选型的目标,才能有一个标准可以来评判该选择哪一个方案。**
就像上面例子中提到的第二版的飞信PC客户端目标就是要提升开发速度所以就选开发效率高的C#。
#### 调研
在明确技术选型的目标后,就可以去调研,看有哪些技术选型可以满足目标,包括开源的方案和商业的方案。
在调研时,可以参考前面“项目决策的特点”中的内容,从几个方面去分析:
* 满足技术选型目标吗?
* 满足范围、时间和成本的约束吗?
* 是不是可行?
* 有什么样的风险?风险是不是可控?
* 优缺点是什么?
在调研结束后可以筛选掉明显不合适的最终保留2-3种方案留待验证。必要的话可以一起讨论最终确认。
#### 验证
一个技术是不是合适,如果不够了解,没有应用过的话,实际用一下是很有必要的。可以通过一个小型的快速原型项目,用候选的技术方案快速做一个原型出来,做的过程中才能知道,你选择的技术选型是不是真的能满足技术选型的目标。
就像前面举的飞信PC客户端的例子在决定第二版本是否使用C#开发时,其实做了大量验证工作。当时.Net Framework还不普及要打包整个.Net Framework到安装包里面这体积就太大了这是一个很大的问题。
后来发现有一个产品叫Salamander它可以只打包程序所需要的dll库文件这样体积就可以控制在20mb以内最后在制作安装包时用7zip压缩就可以让安装包控制在10mb左右。在验证阶段证明了安装包体积是可以缩小的基于C#开发是可行的才最终选定了C#的技术方案。
#### 决策
在调研和验证完成后,就可以召集所有利益相关人一起,就选择的方案有一个调研结果评审的会议,让大家提出自己的意见,做出最终的决策。
必须要承认,对于技术选型来说,是有不确定性的。即使通过上面的流程,也一样可能会做出错误的决策。但有一个科学的流程,至少可以保证提升做出正确决策的概率。
如果遇到很纠结的情况,就需要负责决策的人来拍板了,这时候其实并不一定有对错,重点的就是做出一个选择,然后按照选择去执行。有时候迟迟不选择、不拍板才是最坏的结果。
在项目结束后,也要对之前技术选型和项目决策做总结,不断的完善技术选型和项目决策的机制,帮助未来更好的进行决策。
## 总结
今天,我带你一起探讨了技术选型的问题。技术选型,本质上是项目决策的一种,也符合项目决策的一些特点。也就是说,技术选型的选择要受制于范围、时间和成本的约束,要分析可行性和风险,要考虑利益相关人。还有一些坑要小心避开,比如要避免把听到的观点当事实,要验证;要避免先入为主,不要有了结论再找证据。
要做好技术选项,要有一个科学的流程,首先要明确技术选型的目标,避免没必要的引入新技术;然后要充分调研;还要对备选的方案进行验证;最终和利益相关人一起决策。
技术选型,也不要太过于纠结,要勇于决策,选定了就坚定的去执行。
## 课后思考
你所在项目中是如何做技术选型的?有哪些不错的方法和原则?你在技术选型时,通常是选择保守的还是新酷的?欢迎在留言区与我分享讨论。
感谢阅读,如果你觉得这篇文章对你有一些启发,也欢迎把它分享给你的朋友。