技术选型是项目的根基,如果选择了不适合自己业务场景的技术。初期由于业务复杂程度和业务量都比较小,所以可能感受不是十分明显,但是到了后期这将会是一个噩梦。会导致系统问题频发,极不稳定,甚至导致项目迭代举步维艰,甚至有的团队会停止新功能的开发,专门修复bug。严重时可能造成重大的经济损失。
如下所述的几种场景是典型的“凑热闹”解决问题的方式。它很容易导致错误决策,无论是糟糕的架构决策,还是糟糕的技术栈决策,对团队的影响都常常持续数月甚至数年。最坏的结果是造成极其严重的软件工程问题,只能推倒重来。但推倒重来而成功的案例几乎没有。
在技术选型时通过博客、Github等社区学习热门技术或知名博主的文章,然后应用到项目上。然而技术讲解上可能是正确的,但是其中的一些负面因素却没有得到阐明。在后期迭代的过程中在业务场景和实际环境的影响下可能会出现各种各样的问题,为日后的灾难埋下伏笔。
我们可以通过技术大会学习到最前沿的技术、最新的设计理念能够开拓眼界等一系列好处。但是这些新的技术,学到了之后可能并没有足够的研究。就已经开始使用这些新的框架、规范、技术、类库。
有人整天谈论新框架、类库、技术,但是自己又没有实际经验,但是反复念经使得团队最终决定采用他的意见。
在做一个需求时发现需要一个功能,这个时候出于对时间利用和代码健壮程度的考虑,就引入了一个新的框架来解决这个问题。然而这个框架的其他功能完全用不上。久而久之,积累的框架越来越多。但却对后增加的框架了解不够深入,产生了各种问题,甚至出现依赖冲突的情况,软件包也变得臃肿不堪。技术升级时也会因此处处受困,比如升级jdk大版本,几乎所有的框架和工具包全部都要升级,而且随着新版本api的变化,要进行大量的改造。
ps:例子内容来源于网络
庞大的单体系统很难扩展。在某个时候我们可以把它拆成多个服务。如果各个都用QPS之类的指标来衡量,扩展就容易很多,也更容易拆分给多个团队。
热闹关键词:可伸缩性、松耦合、单体系统。
让我们重写所有的服务!我们的单体系统已经是一锅粥了。得把所有东西都拆成微服务。
见鬼!现在系统开发的速度变慢了,部署的难度提高了,我们还花了不少时间在多个系统之间追踪bug。
微服务需要团队有充分的DevOps能力,还需要权衡增加系统和团队扩展性,保证投入划算。在你遇到严重的规模问题之前,这样的投资是超前的。微服务是提炼出来的,不是重写出来的。按照Martin Fowler的说法,微服务的门槛可不低。
在应对高压力和处理非结构化数据时,关系型数据库有不少问题。全世界的团队都在研究新一代数据库。
热闹关键词:可伸缩性、大数据、高性能
我们的数据库太慢,而且容量不够。我们需要NoSQL。
我们还需要联表查询?这可不行。简单的SQL操作现在都越来越有挑战了。开发速度越来越慢,我们的核心问题还没解决。
NoSQL是用来解决特定问题的(要么是海量的非结构化数据,要么是非常高的负载)。如果专业水平足够高,关系数据库也是应对高负载和处理海量数据的好工具。非得使用NoSQL的情况,在2016年仍然不多见。
有良好技术背景的人——那些人了解不同的范式,理解编程的理论(算法和并发),受过良好工程文化熏陶,这样的人很少去凑热闹。
有经验的人——年轻的开发人员更喜欢凑热闹。如果有多年的开发经验,见过许多技术,踩过许多坑,在技术决策时就更容易做出客观的判断。
技术选型时的注意事项
适当的选择熟悉的技术
软件开发的世界里,几乎每天都有新框架、新理念诞生,对于花样繁多的技术中,因为你不会对每种技术都掌握的非常深入。所以在使用这些新技术的过程中会存在不可控的风险。但是也不能完全摒弃新技术,在如今对软件要求标准和开发速度要求越来越高的时代下,一味的保守,可能会延误赢得市场竞争的时机。
一、扬长避短
二、关注这项技术的发展前景、是否会在将来能够很好的生存下来。
有很多能力比较强的开发人员会以个人名义开源一些框架,但是背后却没有开源社区或商业组织的支撑,再未来的时间里,项目很容易死掉或停止维护。而且稳定性没有得到市场的验证,冒然使用风险过高。
社区不活跃的框架尽可能不要选,没有社区的支持也就代表了它的相关资料比较少,项目也更容易被废弃。
确保技术前进步伐
选择一个技术的最低标准是,技术的生命周期必须显著长于项目生命周期。
技术的前进不仅仅取决于它本身,而是和大环境发展、上下游用户也密切相关。比如AI,60年代其实就已经提出了相应概念,为什么直到今年才进入发展元年?因为芯片的计算效率、数据样本规模没有达到要求。而Functional Language为什么这么多年一直默默无闻,而从前几年开始逐渐盛行?因为机器学习来了,AI来了,它们有了用武之地。
总的来说,你需要使用你所选择的软件技术,快速地实现应用程序的构建。记住一句话:好的技术栈永远跑在用户需求前面。
学会从业务端开始思考
技术选型必须贴着业务来选择,不同业务阶段会有不同的选型方式。处于初创期的业务,选型的基准是灵活。只要一个技术够用并且开发效率足够高,那么就可以选择它。初创的业务往往带有风险性和不确定性,朝令夕改、反复试错是常态,技术必须适应业务的节奏,然后才是其他方面。等业务进入稳定期,选型的基准是可靠。技术始终是业务的基石,当业务稳定了技术不稳,那就会成为业务的一块短板,就必须要修正。当业务进入维护期,选型的基准是妥协。代码永远有变乱的趋势,一般经过一两年就有必要对代码来一次大一点的重构。在这种时候,必须得正视各种遗留代码的迁移成本,如果改变技术选型会带来遗留代码重写,这背后带来的代价业务无法承受,那么我们就不得不考虑在现有技术选型之上做一些小修小补或者螺旋式上升的重构。
正因为技术选型和业务相关,我们能够观察到一些很明显的现象:新技术往往被早期创业团队或大公司的新兴业务使用;中大型公司的核心业务则更倾向于用一些稳定了几年的技术;一个公司如果长期使用一种技术,就会倾向于一直使用下去,甚至连版本都不更新的使用下去。这现象背后都是有道理的。
回到我们的主题,学会从业务端思考。首先我们需要充分地理解业务,理解用户需求,理解当下需要解决的首要问题,以及可能的风险有哪些,再将目标进行分解,进行具体的技术选型、模型设计、架构设计。
举个例子。假设我们需要解决的核心问题是并发,则可以通过各种缓存手段(本地缓存、分布式缓存),来提高查询的吞吐,这样虽然会一定程度上需要在数据一致性上做出牺牲,由强一致性变为最终一致性,但是,如果数据一致性不是核心需要解决的问题,那么,此问题的优先级则可以先放一放,反过来如果核心问题变为数据的一致性,如交易系统,那么再怎么强调数据的一致性都不为过,由于分布式环境下为了应对高并发的写入以及海量数据的存储,通常需要对关系型数据库进行分库分表扩展,这也给数据一致性带来了很大的挑战,原本的单库事务的强一致性保障,在这个时候升级为跨库的分布式事务,而通过二阶段或者三阶段提交所保障的分布式事务,由于分布式事务管理器与资源管理器之间的多次网络通信成本,吞吐及效率上很难满足高并发场景下的要求,而这实际上对于交易系统来说,又是一个很难回避的问题,因此,大家又想出很多的招来解决这个问题,通过可靠消息系统来保障不失为一种方式,变同步为异步,但是,又引入新的问题,消息系统为保证不丢消息,则很难保证消息的顺序性以及是否重复投递,这样作为消息的接收方,则需要保障消息处理的幂等性,以及对消息去重。
先验证后使用
对于未经验证的新技术、新理念的引入一定要慎重,一定要在全方位的验证过后,再大规模的使用。新技术、新理念的出现,自然有它的诱惑,慎重并不代表保守,技术总是在不断前进,拥抱变化本身没有问题,但是引入不成熟的技术看似能带来短期的收益,但是它的风险或者是后期的成本可能远远大于收益。
重视经验
术选型是个很需要经验的活,得有大量的信息积累和输入,再根据具体现实情况输出一个结果。我们在选型的时候最忌讳的是临时抱佛脚、用网上收集一些碎片知识来决策,这是非常危险的,我们得确保自己所有思考都是基于以前的事实,还要弄清楚这些事实背后的假设,这都需要让知识内化形成经验。
经验的本质是什么,有什么方法能够确定自己的经验增长了,而不是不断在重复一些很熟悉的东西。我现在的结论是,经验等于知识索引的完备程度。
我们一生中会积累很多的知识,如果把我们的大脑比作数据库的话,那我们一定有一部分脑存储贡献给了内容的索引,它能帮助我们将关联知识更快的取出来,并且辅助决策。经验增长等同于我们知识索引的增长,意味着我们能轻易的调动更多的关联知识来做更全面的决策。
要想建立好这个知识索引,我们得保持技术敏感性和广度,也就是要做到持续的信息输入、内化,并发现信息之间的关联性,建立索引,记下来。说起来容易,做起来还是挺有难度的。
首先难在信息输入量大,忘记了怎么办。我们的大脑不是磁盘,不常用的知识就会忘记,忘记了就跟没看过是一回事。我的经验是一定要对知识进行压缩,记住的是最关键的细节,并且反复的去回味这个细节。
整体的技术选型流程
“列出需求”-“细分需求”-“明确搜索方向”-“网络搜索”-“明确评判标准”-“分头执行”-“汇总材料”-“初步选择”-“进一步调研”-“会议评审”-“做出决定”
参考文章:
http://www.infoq.com/cn/articles/points-for-attention-with-technology-choice
http://www.infoq.com/cn/news/2017/02/Technology-selection