zoukankan      html  css  js  c++  java
  • 技术​选型的艺术---湖北技术价值分享会

    生命太短暂,不要去做一些根本没有人想要的东西。本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈、MyBatis、JVM、中间件等小而美的专栏供以免费学习。关注公众号【BAT的乌托邦】逐个击破,深入掌握,拒绝浅尝辄止。

    前言

    各位好,我是A哥(YourBatman)。以下文章来源于softech华山论剑 ,作者徐凌云

    技术选型是个很大的话题。「灵活」与「高开发效率」是技术选型最看重的两点。感谢徐总的分享,很受用。


    正文

    关于技术选型,我们不少技术从业的朋友容易进一些误区,而这些误区大多俗话是某种技术开发思维定势在作怪。选型怕遇到喷子,也怕诋毁性总结。

    技术选型没选好,每往前走一步,都可能变成挨揍的理由,也是让人心碎得理由。


    技术选型

    我相信自驱动的团队学习,意识提升,分析度量,团队信任,勇敢能做好选型的更好实践。当然技术选型中也存在着天时、地利、人和。技术选型的能力是一个各方面综合作用的能力,而不是仅仅我们认为的技术范畴。

    很多技术同学对新技术有天生得冲动,有时候开发人员自己玩的很high,但项目却玩死了,这是作为技术管理者需要面对的魔鬼。这是件很悲哀的事情,我们需要抑制内心深处的魔鬼,技术只有跟业务有机的结合起来,产出所追求的价值,才是有意义的。

    在工作中完成一次技术选型,绝不能简单的仅仅从纯技术角度出发思考。一次看似偶然的选型会给后续工作带来方向性的影响,这里的影响指的不光是技术层面,更多的是管理层面。这就如同在公司一次公开的项目招标中,考虑绝不仅仅是解决方案本身的优劣,更重要的考量方案的成本是否符合预期,方案提供方的实力、诚信度,甚至还要从商业模式上去思考未来的合作方式是什么,等等。而这一切,都能在一次技术选型的过程中,得以体现。下面就从几个主要阐述下选型中遇到的常见问题。团队的稳定性重要性要远大于一些其他的因素的重要性。


    技术选型误区与雷区


    做任何决策时,搜集资料,无论是在简书,掘金,公众号还是csdn这些平台上,亦或是开源项目地址和官网上,请记住:最重要的不是它告诉了你什么,而是它对你隐瞒了什么,这些隐瞒的信息最终会置你于险境。

    搜集资料的时候如果资料的作者对某项技术具有显著的倾向性时,请深入想想,他向你推荐的每一项优点是否真的“对你”有价值,以及它背后的代价是什么。比如,推崇“自由”的技术往往不够“严谨”,如果你的产品需要严谨,那么请把“自由”看做减分项而不是加分项。比如,推崇“体积小”的技术在现在动辄几T硬盘、几M带宽的环境下,到底对你来说有多大价值?它是不是因为没有其它的优点了才把这种细枝末节亮出来吸引你?

    如何避免减少技术选型踩坑或者踏雷呢,在这里我们需要一些原则和意识进行精确的指导。


    技术选型原则


    我们为了团队影响力适度使用新技术,也鼓励在各方面情况需要的时候造点轮子,但是前提是稳定第一,并且还要善于应用新技术和自己造成熟了的轮子。


    技术选型的意识

    生命周期的意识

    《聊聊架构》这本书,贯穿全书的词恐怕就是生命周期了。系统都有他系统特性所带的生命周期,从生到死,经历少年、中年、老年三个阶段。复杂度的管理贯穿系统的整个生命周期,就像进化论的自然选择一样,不停的优化着系统,不停的断舍离,保持着系统的生命力。

    度量意识

    《人月神话》是把软件工程的过程量化的国内最早的一本书。没有度量无法说服自己,更别谈说服团队。

    突破定势思维

    突破自己的技术思维定势的意识个体技术认知是有局限的,如何来打破这种局限? 学习,分享,交流,提升,这也是技术创新的基础。

    权衡取舍意识

    选型也是一种精细化选择,权衡取舍意识我们技术和工程领域的朋友很多都是完美主义者,追求完美,但是我么要明白没有银弹。

    技术选型的取舍也是一种取舍的艺术。不仅仅是限于技术视野的综合判断力的体现。

    有时候不必纠结于技术本身的挑战踩坑的认可自己的观念,而是在遇到技术难题,长时间无法解决的时候,可以选择绕口,曲线超车。不把过多经历放在细微之处,而把精力聚焦到核心问题上。

    职责划分意识

    做好选型也需要格局,不仅仅是深深认识到业务规模是发展变化的,技术是演进迭代的,还有企业的商业战略(技术人也要培养商业敏感度)。还有技术选型谁主导,谁参与,谁监督。

    运维需要参与吗,测试需要参与吗,安全部门需要参与吗,当然谁需要参与取决于选型的对象的规模和选型的目的。

    风险意识

    需要识别好风险,在清楚风险的基础上,考虑推进过程中的影响面以及推进过程需要把握的度。特别强调关于已知的未知 和 未知的未知进行区分,一个人花了四个月时间试图弄清楚为什么会出现 GC 停顿,结果发现是因为他往文件中写入了统计信息。显然,他事先并不知道会发生这样的事情。软件中的很多 bug 都是这样的。我们并不知道系统里存在这些 bug,它们都是"未知的未知"。

    一个项目最好超过30%得新技术,对于完全未知的新技术,很难控制使用过程中出现的风险。如果技术leader不能得到下属的尊重,很可能受到惩罚。

    产品意识

    作为使用者是否有能力解决问题,给你一本亿级流量,但是需求是只需要做个管理系统给国企下面一个部门的办公室几个行政人员使用,而且可能一个月也就使用几次。这其实反应了技术人员的产品意识。

    很多技术人员喜欢玩酷的东西,愿意探索新的领域,把不可能的变成可能,但是很多时候,他们做出来的东西很难使用。

    技术发展的史学观意识

    中国近现代是一部师夷长技以制夷的历史,而当年的中国逐步从这种现状转变成自主创新的国家,虽然完全自主创新的科技少之又少,但是这种变化标志着中国对科技的认知和科技长远发展树立了一个里程碑,而这一点在计算机应用领域更是淋漓尽致,造福每一个当代人。我深信多读历史才能增长智慧。

    只有了解技术的发展历史,才能更好,更精准,更稳的做好技术选型。喜欢深入研究技术的从业人员多半会喜欢读一些技术发展史,如《数学之美》这本书就是历史的看从信息论到计算机的发展史。这本书是本不错的计算机从业人员的计算机启蒙书籍。


    技术选型考量因素

    成本考量

    在开发层面,造轮子和开源是我们技术从业同学绕不开的两个问题。很多技术领导害怕重造轮子, 大多数技术领导层希望尽量避免造轮子。我们都知道重造轮子会耗费人力和时间成本。前段技术琐话右导组织过一场造轮子的讨论,有几个同学的观点挺有意思。一个同学提出,造轮子的几个正面论调:自我展示和他人超越;自我保护和代码安全;自我超越和代码专利。

    还有个同学说到开源不易,做得不好没人用,做得太好又投入不起。所谓的造轮子是小事,重要的是解决开源能更好的提供服务,商业更好的服务开源,只有达成良性循环才能有更好的开源,有更全面的服务,商业与开源相辅相成。还有个同学聊的很多,大体提到三点,认知问题和商业利益以及自我能力提升,认为自己的需求独一无二,现有的库就是在某个点上满足不了,对现有的轮子理解不知比如老轮子没有规格说明书,或者接口太复杂,不知道怎么用,搞明白太难,不相信老轮子。

    譬如老轮子可能有后门、漏洞(想想OpenSSL的心脏出血漏洞)、后期万一要修改没把握等,反正是觉得自己造轮子心里更踏实,需要对老轮子上添加新功能,然而老轮子代码难读无人可问,不知道何时能弄明白,看不到结果,容易放弃,眼界有限,不知道已有这样的轮子,版权原因无法使用第三方库,比如Google Android实现JVM(Google曾因为一行代码而和Oracle打官司),比如阿里YunOS自己实现JVM不想让自己产品的关键技术掌握在别人手里,也不想让自己的核心用户数据流经别人的系统,别人的轮子不开放,我就是要赶紧造(山寨)一个出来以便获得话语权或商业利益,就想锻炼自己,因为造轮子对自己的设计、编码能力有很大好处,对理解业务也有很大好处。

    当你造轮子的时候,你要考虑到总有一天还可能会换轮子,互联网行业换轮子是一种高风险操作,有时候我们也偶尔要说服自己,自己造轮子反倒是可能挖坑了。因为确实遇到了一些技术小伙伴参数调优没研究透,遇到问题就认为组件或者框架不好,想自己造轮子的。之所以提到造轮子和开源的问题,是因为做技术选型很多时候我们都会遇到这两个问题。无论是造轮子还是开源项目,代码的可读性和可维护性也是很重要的考量因素。

    开发效率还是执行效率,这个选择是个老生常谈的问题。对于不同阶段的公司和项目会有不同的选择。新的商业项目更趋向于选择开发效率优先。因为商业模式的尽早验证比其他因素更重要。老项目优化更多提到执行效率,性能调优等问题。

    团队考量

    选大家熟悉的,方便开发,排查问题。

    康威定律深刻地影响着很多方面,技术选型也不例外。特别是做宏观技术选型时,必须考虑它在最终技术架构中的位置,以及与团队沟通结构的匹配程度。即使是一项很先进的技术,假如它与体系中的其它技术栈不匹配,也可能导致翻车。

    当选择多个第三方库的时候更要加倍小心,因为它们开发时互相不知道彼此的存在,特别是对于一些较新的技术,可能都没人把它们搭配使用过。除了开发架构之外,还要考虑更广泛的运维架构。

    除非你是个前后端 + DevOps 全栈,否则就需要尽早对组织架构方面的因素进行验证并排除风险。也就是说,在一个可控的演习环境中,用一个小型案例,完整地走一遍开发、上线、发新版的流程。在这个过程中,一些显著的风险将会暴露出来,要评估其影响,来决定如何选型。

    我认为技术管理者身上必须有一个特质:技术布道。充分激发团队的技术热情,感染团队里的每个成员,是技术管理者必备的人格魅力。一项技术适不适合团队,只有用了才知道。但是技术管理者大可不必亲力亲为,尤其是CTO,总监级别的管理者,只需要指定技术目标,保持一定的技术热情即可,最后再积极配合进行技术布道。

    不同的企业,不同的部门,不同的团队管理模式不同,技术文化不同,当然就很可能在技术选型上发生不一样的故事,像一个技术同学的团队teamleader+业务架构师+技术架构,进行民主决策,少数服从多数。这个方式体现了组织架构的重要性,技术架构师和业务架构师以及teamleader。有的企业有技术架构委员会,会参与大项目的技术选型的评审,有些时候可能他们对待选型的对象所选择的技术并不太熟悉的时候,他们最差也能站在自己技术经验的角度考量一些可能会遇到的问题。提到这个主要强调组织架构对技术选型的影响力,《架构即未来》这本书,对弹性,高效的组织架构做了很详细的阐述。

    方案1/2/3...N,综合评价,倾向选型优缺点详细列明,如果某个环节可能会出现问题,风险备案是什么。并且附上开发计划排期,关键事件的里程碑和时间截点。相信上面也是能看得懂的,这个时候就看要你个人游说能力了。那这样好不好,有一句话说的好,人捋顺了,事就好办了。但是也有另一面,因人而废制度,就变成了人治,谁的嗓音高,谁的权限大,谁就有话语权,这样的组织长久不了,团队会潜移默化的形成个因人而成事,因人而废法这样的团队你呆个两三年出来之后基本就知会唯唯诺诺,很难养成自己的独立思考和决策能力。

    那究竟事制度重要还是人重要呢,这是另一个层面的讨论。这个话题的思考从《大江大河》里面老水的因人成事,因人废事那句话开始。因为我认为错的人好的制度,未必能办成好事,但是犯错误的可能性会低一些。对的人好的制度是比较完美的状态。

    先客观的从团队各维度梳理团队现状,然后据此选型,要知道选型错误只能团队来承受。阿波罗神庙上镌刻着一句警世名言-了解你自己。千万不要懒于梳理,懒于总结盲从潮流。惰性确实是技术发展的驱动力之一, 而过于懒惰却不是。

    团队技术选型自然会选择团队所有成员熟悉的技术,否则会出现开发节奏问题。比如所有人熟悉 Java,小部分人熟悉 Scala 的情况下,需要忍痛割爱选择即使从其他层面考虑更适合的 Scala 语言。一般情况下,某项技术至少需要 1 – 2 位高级工程师解答遇到的所有相关问题,这位工程师需要从源码级别理解这项技术。优先选择成熟技术。

    技术选型一定要考虑当前团队人员的技术组成。对于一些比较基础的技术的选型,比如语言和框架、数据库等等,往往最合适的选择就是团队最熟悉的技术。如果打算选择不同的技术的话,那就要考虑下团队是否有人能够 Hold 住了。另一个必须要考虑的是招聘,如果使用的是比较小众的技术,那么当需要扩充团队的时候,招聘人员会比较困难。

    还有一点就是,虽然技术选型需要考虑团队人员的喜好,但千万不要因为某几个人的个人喜好,来决定技术的选型。还是通过细致的分析和实验来进行选型。而决策者也需要看的更长远一些,推动团队技术向前发展。

    我们经常会遇到,一项新技术在公司内久久难以推行,因为业务主管的阻挠。即使排除利益纠葛,仍然会发现一种发自内心的不信任存在。而这种不信任,又往往来源于对同事工作的不认可。

    对于技术管理者,在技术选型时,重点还需注意团队人员流动性。人员流动带来的损失比大多数人所认为的要大得多。人员流动会带走知识和文化。企业要避免损失,就要把这些知识和文化尽可能记录在代码中。

    当然,这并不意味着应该要求大量写注释,而应该使用那些能留存知识的技术,比如类型系统和规范化命名。类型系统和规范化命名可以半强制性地要求开发人员把原本只存在于自己脑子里的知识记录到代码中。如果更有追求一点,可以再尝试普及单元测试。这样,当他离开的时候,即使没有文档,这些知识也仍然能留存下来。从效果上说,代码往往比文档和注释更好。而文化的留存则更加困难,事实上,代码中的奇葩注释往往留存的是负面文化。应该在代码中留存的文化,是严谨、专业的工作态度。虽然自由也是文化的一部分,甚至在管理领域是非常值得向往的文化,但在工程领域,它往往是一种负面文化,因为软件开发领域并没有公认的法律甚至道德。你可以想象一下管理领域中没有约束的自由会导致怎样的后果。

    所以,要想应对人员流动的风险,除非你有信心留存知识与文化,否则就应该在技术选型时,倾向于选择更加严谨的、隐式信息更少的技术。

    项目产品考量

    短生命周期的产品通常要求快速起步:门槛低、书写自由、不强制遵循任何最佳实践。当它的使命结束时,代码会被直接抛弃。所以,对于这类产品,“快糙猛”的技术是较好的选择,当然,能做到“快精猛”更佳。

    而长生命周期的产品则会强烈要求可维护性,因为它们在很长时间内都是不可报废的。甚至对于一些生命线产品,连重写都会要求在重写期间线上系统平稳过渡,一点点迁移到新技术。

    这种要求对团队的工程化能力是个极端的考验。如果没有相应的工程能力,其代价甚至会高于用新技术重新写一个功能相同的系统。

    稳定第一的项目比如银行项目,虽然不少银行也研究新技术,但是较少用在生产,因为银行受到评级和监管约束,一旦将新技术引入线上,会导致评级下降,监管问询等。

    探索型产品往往也是短周期产品,但是同时也有自己的特点。它要求快速,但往往同时会要求高质量。探索型的产品如果证明了可行性,那么过渡到长生命周期的可能性很大。

    这就要求它最好是一个微内核系统,提前留出一些扩展的空间。当然,设计微内核系统对架构师的能力具有相当的考验,如果没有一个优秀的架构师,建议还是不要刻意做任何预留,优先保障系统的简单性。

    除此之外,探索型产品的技术栈必须支持可靠的、自动化的重构。因为探索型产品的迭代速度很快,如果完全靠人工去添加功能并手动重构,那么一旦出现 BUG,将给此产品的用户体验带来严重的负面影响。

    所以,除非由于人才储备等原因而被迫做出折中,否则探索型产品的技术栈一定要快速而严谨。而对守成型产品的选型则会侧重于与现有技术栈的相似程度和无缝整合能力。如果整合时需要借助很多技巧,那么可能你就是在给自己挖坑。

    在引入新技术的过程中,要尽可能符合现有的开发流程、基础设施和开发习惯。当然,如果现有的这些已经严重过时,那么应该找新老技术的专家,共同帮你设计一个路线图,让你可以平稳地引入新技术,这份投资绝对值得。如果老技术已经有新版本,则应该优先考虑升级它。不要幻想换个技术栈就能解决一切问题,事实上,它带来的问题往往会更多。

    业务考量

    所有脱离业务需求的技术方案,都是耍流氓。
    只有真正契合业务上下文的方案才是好的方案,而每个项目都有自己的特殊性,需要把项目上下文尽可能了解清楚,找出项目成败最核心的1到2个标准,以此作为基础来做选择题。譬如说,创业项目,灵活是明显的述求,产品推出后必然会面对朝令夕改的需求,如何快速反应是选型的重点。再譬如说,陈年项目性能遇到瓶颈需要重构,再往下挖可能原有系统吞吐量不成问题,但瞬时响应太差,选型时就需要特别注意这个点。


    如何做好技术选型


    如果我们从天时,地利,人和这几方面去梳理当前业务的情况,会发现很多我们原本没有注意的问题。我们必须从业务角度去梳理企业业务规划,业务战略以及当前业务遇到的痛点和难点,组织架构。团队成员的技术特征以及技术栈偏好。还有当前使用的技术情况等。

    梳理当前能解决我们需求的开源项目或者工具,并分析一些核心指标能满足我们大部分的需求进行筛选并列出表格。从中我们梳理一些选型中会考量的核心指标,并把核心指标对应的权重做出表格,让相关人给对应的指标分配合适的权重,综合相关人的权重算出合适的权重。做出指标和权重的表格,让参与选型的相关人进行指标值打分。对打分结果进行计算,对不同的待选项的得分高低进行筛选。切记筛选核心指标要细致准确。

    技术选型最好罗列至少3个以上的待选,并在选好型之后,还附加一个备选技术方案来兜底。我们应该了解选型对象的不同,有时候核心考量指标可能差距偏大。以大数据平台为例:

    这些指标是我和技术分享@华山论剑@湖北群组中的大数据平台架构师wander聊过后梳理的。因为在从业早期,对不同的选型对象,所偏向的指标在某几个点上是有很大差距的,大数据平台,中间件,云平台等等。

    有一个点可能是共通的,就是无论是什么技术产品或者项目,我们都需要有个人能体系化的熟悉选型对象涉及的技术并了解相关生态,基于这点我们排除团队,成本等因素更可能做一个靠谱执行顺利的技术选型。


    常见选型案例

    开发语言,开发工具,项目管理工具,知识库,中间件,框架,存储,监控运维平台的选型是我们经常会遇到的。

    通常我们选型会考虑一些通用的选型指标,具体的选型可以在通用选型的基础上具体化对应的指标,亦可根据选型的特殊性在通用选型的基础上筛选核心指标。

    以API网关为例,在某公有云公司的时候,当时开发一个人,运维属于跨部门沟通没有垂直SRE,由于当时公有云在发展初期的样子,规划是整个公有云的开放平台和网关,IAAS和PAAS部门几十条产品线陆续在开发结束等着接入API网关把能力开放给大客户。IAAS部门高级中间和产品高级技术总监对项目赶的很紧,但是人力投入不够,为什么人力投入不够,这个涉及到领导各方面意识的错位,这点错位一直到半年之后的一次公司重大组织架构调整之后才有所改观,对于网关和开放平台的主要研发来说,一个人从各部门沟通,方案,设计,维护,测试各个层面来讲,承受的压力都不小。2017年的时候可选的开源网关不如如今这么多,当时比较多的zuul1被技术圈的朋友在设计上和性能上诟病,sc gateway。从技术栈上看,lua栈的有kong和orange,基于OR自研。go栈的悟空,tyk,自研。java栈的zuul1,sc gateway刚开始版本v1在进行中(下半年才开始推广中小企业应用),zuul2一直未发。

    面对当时的情况,有几个想法:1 找一个功能强大,口碑较好,方便易用的(如kong)快速验证上线,后期做二次开发。2 基于内部的RPC框架做开发,但是当时公有云部分正在去集团的RPC框架,纠结了一会。3 基于go语言改造一套,但是问题是我们部门多是java栈的,我对lua的比go熟一些,公有云很多是go栈的,又是一个纠结。真是天时,地利,人和三点都不沾。当时的处境如同,老板给你递了两个烂核桃,你还不得不吃。

    还是得一步一步来,而且要快速去验证,于是快速对kong的社区和源码进行查阅,并快速部署,去验证。任何新东西的引入都会踩坑,我验证的过程中发现对于kong集群的通信,节点数据一致性,konga管理后台的配置和使用,kong的部署安装,数据库的支持,运维部署的复杂度等等都或多或少要不就是坑,要不就是不符合国内使用习惯和架构设计风格,但是唯一就是插件很丰富,功能很多。其实如果时间充裕一点,不是一个人做,我宁可选择java自研或者go自研。或者说当时kong不成熟吧,与kong的国外研发团队沟通的过程中却是也觉得,他们技术的深度可以,然后再不断的踩坑中进行着kong的二开之路。我相信这次选型不是一次充分的选型,当下可选的API网关很多,开源的也太多,soul,APISIX进入Apache基金会,sc gateway的成熟等等新成员陆续出现。

    API网关除了上面通用的选型要素还应该注意什么呢。大多数人会说协议支持,路由粒度及策略,负载策略,安全扩展,高性能这样几块,这些属于技术要素里面我们需要考虑的细项。

    我们根据通用选型指标给出对应的专家打分权重,筛选了几个备选的API网关:APISIX,soul,kong,tyk等。注意三个以下备选行不算有选择。

    接下来基于通用指标考量之后,我们进行细化指标考量。

    带着以上指标去快速调研和验证,并填充上面表格,根据当前的选型背景选择合适的。至于具体如何量化的对网关进行选型,因为考虑到不同的团队面对的情况不一样,将在下一篇 API网关的设计中去聊API网关的量化要素。

    题外话,最近和一些技术圈的兄弟准备发起《技术价值分享会(湖北) 暨老乡会》的聚会,希望技术朋友们,特别是老家在湖北的技术从业朋友,不管你在北京还是深圳,广州,或者在杭州,苏州,成都,武汉,我们都很欢迎和期待您的加入。


    总结

    凌云:技术价值分享会(湖北) 暨老乡会发起人。湖北武汉人,计算机硕士研究生,在校期间主要研究方向是人工智能算法的优化算法和软件质量度量模型。相关论文《脉冲神经网络图像分割的编码方法》发表于计算机工程期刊,《改进粒子群的软件质量综合评价方法研究》,《粒子群算法改进策略研究》也被一些论文和期刊引用。岗位从研发到架构到架构管理,涉及行业包括在线教育,数字社区,智慧交通,公有云,电商,重资产长租等领域。同时也参与中间件开发及负责开放平台,服务框架,安全威胁建模等领域。在新华网负责过教育平台技术架构,后被朋友推荐去京东,在京东云和京东商城主要致力于API网关,流量网关和开放平台方面的研发和架构,目前是重资产长租领域独角兽企业技术架构委员会委员,softech华山论剑作者。致力于最有价值的技术传播分享,推动轻松高效的技术氛围建设,希望能顺利推动湖北地区技术氛围建设与技术坏境的良性转变。同时也希望组建我们的技术从业者足球队和篮球队,提升技术从业人员"健康第一"的意识。

    特别值得介绍的是我们的发起人团队都是87到95的一群年轻阳光的小伙子。如果您自驱动的学习,乐于分享,热爱开源,并执着于技术,如果你是一个利他、阳光、正气、勇敢、执着、创新的技术从业者或者在校学子,欢迎扫码加入。如果你是湖北地区或者漂在一线城市的湖北技术从业人员或学子,我们也欢迎你加入,我们在这等你。

  • 相关阅读:
    winform 剔除空格与换行显示
    编码
    todo
    react高阶函数组件
    Docker-compose Setup for Self-hosting Development & Deployment Tools
    Self-hosting Sentry With Docker and Docker-compose
    how does Array.prototype.slice.call() work?
    todo reading
    a better git log
    https://coderwall.com/p/7smjkq/multiple-ssh-keys-for-different-accounts-on-github-or-gitlab
  • 原文地址:https://www.cnblogs.com/yourbatman/p/13354199.html
Copyright © 2011-2022 走看看