yunghoover 2018-11-11
作者介绍:胡键,超过 15 年软件研发经验,先后任职于中兴和 SAP,现专注于工业物联网创业,任上海圭步 CTO。具有丰富的产品研发和项目实施经验,擅长围绕设备资产和生产管理提供物联网端到端解决方案。他同时还是 CSM 和活跃的社区活动组织者,在西安组织过多场 HiBlock 区块链技术社区活动并做分享。
作为技术人员,对于“技术选型”一词应该不太陌生。简单的说,技术选型就是技术决策,只要你在团队中稍微有点地位,独立承担某项任务,就会面临选择,需要做出相应的决策。当然,这种细粒度地决策级别不是我要讨论的重点。在本文中,我想分享一下我对于公司层面技术选型地观点和看法,更确切得说是面向创业公司的技术选型。为何要重点突出“创业公司”呢?很简单,因为到目前为止,我一直走在创业的路上。
好了,言归正传。在重点去谈创业公司如何做技术选型之前,咱们先来看看技术选型的一般性原则。
选择并不像看上去那么美好,没有选择和选择太多都会让人痛苦,尤其是在当今技术大爆炸和开源项目满天飞的今天,“选择麻痹”应该是最让技术决策者头痛的毛病。要缓解它,就必须建立起我们自己的技术选型标准,或者说原则。
在经历了这些年多次“艰难的抉择”之后,我总结出了适合我个人的技术选型原则。
原则 1:能否简化开发任务?
这条原则显而易见,如果选择的技术无法帮助我们高效地达成目标,似乎没有理由去选择它。注意这里的关键词:简化。完成开发任务的手段并不是唯一的,在众多手段中间我们只关心哪个能够让我们生活得更容易。
同时,这里还要避免一个不那么显而易见的陷阱:虽然简化了手头的任务,但带来了其他方面的复杂性。比如,引入 Kafka 确实带来了一系列的好处:流量削峰、简化了任务分配和服务异步化等等,但由此也带来了一系列其他的复杂性,比如:运维的复杂性和事务的复杂性。那么,作为决策者就要评估是否需要这样一个复杂的方案,是否采用简单地方案就能完成目标,如:日志表 + 定时任务。
原则 2:是否符合组织内的主流技术路线?
大多数组织都会有一个主流的技术路线,技术团队如果采用的技术五花八门,会大大增加技术管理的成本。技术路线,是在进行技术选型时必须要面对的问题,尽可能地选择符合公司技术路线的技术或工具,这样有助于工作的快速推进。
当然,凡事无绝对,当可见的好处远大于学习新技术的成本和风险时,在可控范围内冒险一试未尝不可。但需要提醒的是,除非是极端情况,这种情形其实并不多见。因为当前丰富的开源工具已经提供了充分的选择,在大多数情况下时能够让人找到既满足自己要求同时又符合组织技术路线的工具。这里我假设贵公司的技术路线并不是那种剑走偏锋类型。
原则 3:是否普及程度高或者学习曲线平缓?
普及程度高,有利于很快找到合适的人直接上手开干;学习曲线平缓则有利于在缺人时快速将现有人员切换到现有赛道。一般来讲,普及程度高的技术或工具,大都没有陡峭的学习曲线。反过来就不一定了,比如我公司一直使用的 Grails,在国内的普及程度就远低于所谓的 SSH 或 SSM。但其学习曲线一点都不高,而且开发效率数倍于前者。
这条原则直接着眼于技术选型对于人员管理的影响,满足这两点的技术或工具都将大大降低人员管理的成本,对于招聘和人员流动都有积极的影响。
原则 4:能否得到有效地支持?
这里的支持可以来自于两方面:外部和内部。能够方便地获得外部支持一方面说明了项目的普及程度,另一方面也反映了项目的活跃程度。前者的好处在上面已有说明,至于后者,则说明项目在与时俱进,对于新出现的使用场景大概率有较好的支持。
即使有很好的外部支持,也不意味着就应该放弃内部支持能力的建立。原因很简单,随着使用的深入和业务的发展,迟早会遇到自己公司特有的需求,而这个需求还没有广泛到从外部就可以直接获得很好地支持。此时,只能借助自己的力量把坑填平,这样才不至于以往的技术投资打水漂。
从获得支持的角度来讲,这条原则相当于对于上一条原则的补充说明。
原则 5:是否有助于规范开发流程?
这一条原则的可能并不是那么明显,在此我想表达的观点是:要么有助于建立开发流程或套路,要么对现有的流程有支持。
还是以前面提到的 Grails 为例,典型的 Grails 应用开发主要就是:
通过将应用本身拆解成这样的关键组件,从某种程度上来讲既规范了开发内容和流程,同时也可以让开发者快速地抓住要点,建立大局观,迅速进入状态。
另一个例子则是以太坊 Dapp 开发框架 Truffle,其对于咱们习以为常的开发流程提供了直接支持:
正是由于这样的支持,使得 Truffle 成为以太坊开发的不二之选。
最后,作为第一部分的结束,我简单谈谈架构选择和工具选择的差异。这里,我不会教条的去大谈特谈架构和工具差异,因为这类带学术性质的讨论本来就不是我的喜好。
在我看来,架构更多地落在方向层面,而工具则着眼于执行层面的细节。既然如此,那么两者的选择顺序和差异就一目了然了:先定架构再选工具,而架构的选择由场景决定。比如,面对高性能要求的场景,我们首先要做的是选择哪一种架构模型:Actor 还是 STM;在定下来 Actor 之后,再选择用 AKKA,还是 Erlang,或是 Vert.x,又或是 GPars?
技术选型工作并不会因为创业公司就变得轻松,相反,由于创业公司本身的不确定性和阶段性,反而有其独有的特点,在不同阶段对于上述原则的优先程度和取舍也会有所变化。在本文的第二部分,我将针对处于不同阶段的创业公司给出我自己的技术选型标准和建议。
处于草创阶段的创业公司技术队伍一般不会超过 10 人,在这个阶段,公司最主要的目标就是尽快将核心业务快速上线,让其接受市场的考验。作为技术领导,我们通常会面临:
现有的人手永远难以满足不断增长的业务需求,这句话有几层含义:
对于质量的要求只要达到基本可用即可,但要求队伍具备快速地填坑能力。
请注意,这里指的质量基本可用并非是指低质量,而是指某些非功能性的质量要求并非那么高,比如高性能、高可用等等。只要基本得到满足即可,并不要求你在这个阶段就造一个淘宝或京东。
鉴于以上的基本事实,对照前面的原则,可以很容易地排出优先级:
能够简化开发,帮助快速开发;
普及程度高或学习曲线不那么陡峭,从而降低人员管理的成本
有助于规范开发流程,对业界广为人知的工程实践有直接的支持;
能够有效地获得支持,有助于快速填坑;
这里,我来说说为何当初选择 Grails 作为我司的主要开发工具,而不是市面上烂大街的 SSH 或 SSM。
简化开发,Grails 在这个层面提供了数倍甚至 10 倍于后者的开发效率,究其原因:
无处不在的 CoC(惯例优于配置),对于常见的编程实践以惯例的方式引入,基本消除了繁琐配置的需求;
提供了各类高效的开发部件,极大程度降低了开发人员的要求,即使是小白,按照手册进行开发,也能快速开发一个像模像样的应用。由于已经将常见的最佳实践内置,按照这种模式开发出来的应用天然就对常见的开发问题免疫,较之 SSH 或 SSM 之类已经处于不同的层次。比如:乐观锁、SQL 注入、XSS 攻击等等;
丰富的插件可以快速获得框架本身不具备或者不提供的能力,如 Spring Security 插件和 Spring Security REST 插件可以快速地让 API 应用支持 JWT 和权限验证;
普及程度或学习曲线,Grails 在国内的知名度远逊于其在国外的知名度要拜国内的培训班所赐;
从历史渊源来讲,Grails 本身就构建于 Spring 之上,同时曾经也被 SpringSource 收购,作为其工具链的一员。(注:Spring 幕后的公司 Pivotal 于 2015 年终止了对于 Grails 的资助,但 Grails 目前依旧处于良好的发展势头。前不久,Grails 团队又推出了新一代开发框架 Micronaut。)
Groovy 语法对于 Java 开发者来讲几乎可以做到无痛迁移。
Grails 应用有很明显的规范套路,参见上述原则 5 的描述。
Grails 支持常见的开发实践,如:自动化测试和 DB Migration,可以很方便的跟 Jenkins 之类的 CI/CD 工具集成。
从获得支持方面,看看 StackOverflow、相应的邮件组和它的 Github 仓库即可。
由于时间对草创阶段的公司来讲是最稀缺资源,我强烈建议作为技术领导的你在此方面花些时间和精力。我个人喜欢通过引入好的工具来获得额外时间,即使它显得稍微有点偏门,也无所谓。因为好的工具通常:
不客气的说,选择一个平庸的工具固然没什么大错,但你可能最多获得平庸的结果和效率。
假如熬过了草创阶段,那么发展良好的你将迎来最具考验的阶段,发展期。此阶段,人员不会超过 50 人,同时还要两线作战:
这样的考验对于任何技术团队来讲都是艰巨的,因为在这个历史时期,虽然看似人手有所增加,但具有以下特点:
另一方面,从业务角度来讲,给技术也带来的新的要求和挑战:
在这样的背景之下,作为技术决策者,可以按照这样的优先次序去考虑技术选型:
并且,在这个阶段架构选型将会至关重要,否则难以达到业务所要求的质量目标。这在前一个阶段通常是不存在的,在我看来,草创阶段最重要的设计莫过于数据库设计。至于其他,都可以商量。
同样的,我将以我司的工业物联网接入层的架构变迁来说明一下。
在草创阶段,我们的接入层由以下几部分组成:
随着设备接入数量的增加,这种设计开始捉襟见肘,架构改造势在必行。经过一系列的改造阶段,最终的架构变成:
其中,Socket Server、Processor、Ghost 通过 Kafka 串联起来,后一阶段的处理负责从 Kafka 相应的 Topic 中拿到前一阶段处理好的数据,处理完毕之后再放入相应的 Topic,交给后续的处理器处理。
或许有人会说这就是标准的流处理场景,不如干脆直接用相应的框架算了。没错,我的确曾经动过采用类似 Storm 或 Spark 的念头,但考虑到其带来的复杂性和团队对它们并不熟悉,最终采用上面的土方法应对了。到目前为止,它还稳定的运行着。这里还有一个背景:我们所面对的是大型工业设备,属于 To B 场景,从业务角度讲,设备上云的速度不太可能一夜就暴涨上万台。因此,采用以上的架构足以应付相当长一段时间内的机器数量增长。
其他技术考量:
作为承前启后的发展期,架构选型是其关键所在,稍有差池,在草创阶段积攒下的优势就有可能灰飞烟灭。确定下架构之后,至于选择自建或是符合要求的云服务,这种选择题就好做多了。
恭喜你,达到此阶段的创业公司可谓是有所小成,打过硬仗的技术团队的实力也进一步得到增强(不论从人数上来讲,还是从素质上来讲)。相比起草创阶段的流寇,发展阶段的山贼,现在的队伍可以算得上是一只正规军了。
业务上,开始慢慢稳定,形成了固有的套路和做法,即使有新需求,也并非像以前一样没有参考和不稳定。另一方面,技术上的积淀也越来越多,不论显式地或隐式的,公司已经有了自己的技术路线和规范。同时,在战火里成长起来的骨干也都能独当一面,你不再需要去做低层次的技术决策。
想必各位已经猜到,作为技术领导的你,此阶段地当务之急当是建立技术规范,明确技术路线和要求。有条件的还可以组建架构师委员会,甚至进一步将团队分拆成基础框架和业务应用两部分,将低层次的技术决策下派给相应的技术带头人。此阶段,最重要的原则莫过于:是否符合组织内主流技术路线和是否有助于规范化开发流程。
很遗憾,虽然我很想像前两节那样举一些个人实际的例子来佐证,但由于我所处的公司尚未达到此阶段,故只能在此纸上谈兵。至于例子,只好作罢。
技术选型是技术领导日常工作的一部分,但就不同阶段的公司而言,技术选型的标准并非一成不变的。针对公司不同阶段的关注的重点,本文简单谈及了相应的标准和原则,同时结合自身给出了相应的实例。
说到底,技术要为业务服务,技术选型不能是技术人的自嗨,更不能是“面向简历”的决策结果。只有把握了这个最终原则,我们才能真正客观的看待当前的技术问题,相对客观的履行作为公司技术带头大哥的职责。
最后,虽然全文以“公司”为名,但其实只要将公司两字换成其他,比如“业务线”,其实也未尝不可。比如,成熟公司内部的创新,其整个过程与创业公司的发展其实非常类似,这种情况下,只要大领导支持,当然也可以采用相对激进的做法进行小范围内的“不符合公司当前主流技术路线”的技术选型。