我叫丹麦金利,这就是我在坑里。我目前在一家名为Mailchimp的公司工作。之前在Etsy,因为在Etsy待的时间比较长,后面会多说说我在这家公司的经历。离开Etsy后,我实际上在其他几家公司工作过。我在大公司工作过,在小公司工作过,也开过自己的公司。在浏览了这些公司之后,我注意到了一些事情。大公司有自己的做事方式。它们提供了一个“沙盒”环境。在这种环境下,会有人满足你的需求,解答你的疑问,让你感受到“方方面面都被爱”。但我也经历了一些过渡时期,一些棘手的问题需要我自己解决。首先,如何选择合适的技术?另外一个我比较关心的问题是:如何让开发者乐于使用这些技术?由于我自己是开发人员,所以这对我来说更重要。如果可能的话,我尽量让自己开心。如果您问开发人员什么会让他们开心,他们通常会说“如果我可以使用Clojure作为开发语言,我会很开心”。我不否认,当他们说出这些话的时候,他们脑海中应该有着最激动人心的体验。但我相信他们描述的状态是他们可以达到的最高精神状态。我以前也喜欢那样。比如Etsy早期的应用就是用PHP开发的,而开发这些应用的人恰好当时也在学习PHP。但是我花了几年时间尽量不去碰这些PHP代码,我什至尝试过用Scala和MongoDB重新开发这些服务,因为我认为它们是更好的技术栈,可以解决所有开发效率问题。但事实上,没有任何迹象表明我在做正确的事情。我这段时间做的一些丢人的事,网上还可以查到,大家可以搜一搜,用来取笑我。现在的Etsy员工还在拿这件事取笑我。后来我使用Clojure创办了自己的公司。虽然,这家公司已经不在了。不过不用想太多,公司倒闭不是因为用了Clojure。不过我还是乐于分享这段经历,毕竟我也是一个体验过函数式编程乐趣的人。我不是一个倾向于沉迷于开发技术的工程师。我的其他演讲中很少有关于工程的。我还不够大,也不够脾气暴躁。但是通过总结Malois的需求金字塔理论,我也有自己的看法。简单地说,马洛需求金字塔是指在满足更高层次的需要之前先满足低层次的需要。连肚子都填不饱,哪有心情吟诗?虽然这个比喻不一定很贴切,但在软件开发领域,确实如此。如果您还在忙于争论使用哪个数据库,您怎么可能有时间担心整个产品蓝图?幸运的是,在我经历过的一些场景中,已经满足了基本的需求,所以我希望能把其他项目也带入这个状态。要达到这种境界,首先要集中注意力。人类关注细节的能力是有限的。我的朋友安德鲁总是穿同一品牌的黑色T恤。他认为,如果把花在选衣服上的精力囤积起来,就可以花在其他更有意义的事情上。不知道这样做是不是没有品位,但我觉得是有道理的。接下来我谈谈我的想法。假设我们手头有一些代币,但是数量有限。这些代币代表了我们创新或解决困难挑战的能力。在一个公司的早期,我们可能有三个这样的代币。那么你们公司是做什么的呢?Etsy,我之前工作过的公司,号称要重塑整个世界经济。我不知道开发人员如何看待一家科技公司的既定使命,我只是认为根本不应该认真对待它。不过现在,让我们“天真”一点,看看如果这家公司真的想改变世界会发生什么。重塑整个世界经济非同小可,可能要付出象征性的代价。离开Etsy后,我加入了另一家想要“增加互联网的GDP”的公司。这看起来也很重要,因此可能还需要花费一个或两个或所有代币。即使您认为创新是一种稀缺资源,对于已经完善的数据库或编程范式来说也没有多大意义。问题不在于他们的创新不起作用;事实上,他们确实如此。但是在软件开发领域,越晚出现的东西越需要引起重视。为了找出原因,我想从哲学方面入手。我对一项技术了解多少?我不喜欢唐纳德·拉姆斯菲尔德(美国前国防部长),我希望他下台。但他与我们要讨论的问题相关,所以我不得不忍受他的恶魔般的存在。面对未知,通常有两种情况。一种是“已知的未知”,即我们知道我们不知道的东西。还有“不为人知的未知”(unknownunknown),就是那些我们不知道的事情我们不知道。这是“已知未知数”的一个例子。当数据库出现故障时,我们可能不知道确切的原因,但我们知道网络分区可能是导致故障的原因之一。因为我们知道有这种可能性,所以可以进行有针对性的检测。或者我们可以双手合十,希望这与网络分区无关。无论哪种方式,我们都知道存在这种可能性。还有一些是“未知的未知数”。这是我最近看到的一个例子:一个人花了四个月的时间试图弄清楚为什么他会遇到GC暂停,结果证明是因为他正在将统计信息写入文件。显然,他事先并不知道会发生这样的事情。很多软件的bug都是这样的。我们不知道系统中存在这些错误,它们是“未知的未知数”。现在,我们知道软件系统中存在这两种“未知数”。一个10年的软件系统通常在JIRA中有很多相应的工单,而且没有人会修复这些问题。除了这些,系统中还会有很多未知的bug。但并非所有技术生而平等,新技术更有可能兼具两者。我选择了“无聊的技术”作为标题,后悔了好几天。因为有人说:“无聊是不好的,为什么说它是好事呢?”但是我所说的“无聊”和CSPAN(美国总统电视连续剧)的无聊是不一样的,我所说的“无聊”是指我们已经非常了解的东西。如果你觉得一个技术还不够好,这是因为您已经知道原因了。您可以只使用Postgres并且一切顺利吗?不,您选择的技术组合有问题。假设您已经使用了以下技术堆栈:Python、Memcached、MySQL和Apache。那么您有一个新问题要解决。那么,你认为将Ruby添加到你的技术堆栈中会帮助你解决问题吗?几乎每个人都会说,“天哪,这怎么可能!”我们知道添加Ruby的边际收益不会超过复杂性,因为Python和Ruby基本上是类似的东西。好吧,那么加入Redis怎么样?我们已经有了MySQL和Memcached,还需要添加Redis吗?根据我的经验,这是问题的症结所在。在出现问题时调用多语言编程就像和一群人冲进巴士底狱并说,“你不能阻止我们使用最好的工具来完成这项工作。”当人们开始屈服时这种本能会说服自己:这是给开发者更多的自由。的确,这是一种自由,但实际上是一种狭义的自由。那么,幕后发生了什么?让我们来探讨一下。当我们想在项目中加入一些半冗余的技术时,我们通常会这样想:“这种新技术在短期内会让开发变得更容易,而且它给我们带来的收益要比采用新技术所产生的成本高”。我们可以换一种结构化的思维方式来考虑这个问题。假设你的工作就是我朋友Coda所说的:使用技术解决业务问题。因为我们的领域和计算机科学有一定的关系,我们不妨假设自己是计算机科学家,用二分图来描述我们的问题。我们需要将左图中的所有点与右图中的点连接起来,这样问题就解决了。连接边表示已做出技术决策。每一个技术决策都有一定的维护成本,但同时享受新技术带来的好处。也就是说,每一个技术决策都会给我们带来收益,同时也需要我们承担一定的成本。我们可以使用我们已经选择的技术。也可以选择其他技术。选择一项新技术会产生一定的成本,但如果它能加快开发速度,那么这是值得的。我们试图最小化这个成本函数。总成本等于总维护成本减去开发速度增益和从这些技术决策中获得的收益。我们的行为实际上取决于等式中的哪一项在现实中占主导地位。如果技术的维护成本很高,那么成本就占主导地位。如果技术极大地改变了开发的方式,那么技术的好处就会占主导地位。因此,您可能会使用如图所示的不同技术解决所有问题。如果每项附加技术的成本很低,这很好。这是另一种策略。我们只选择了一部分技术来解决所有问题。只有当新技术会给我们带来巨大负担时,我们才会这样做。实际上,新的技术决策通常会带来很多负担。随着时间的推移维护一项技术的成本往往超过它给我们带来的便利。所以,通常我们选择能够解决所有问题的最小的一组技术。把技术维护做得非常专业,其实是非常难的。一开始可能很容易,但随着你的前进会变得越来越难。为什么?加入新技术容易,维护好却不容易。例如,我现在可以用brew安装一个数据库,然后开始编写代码。但是在生产中运行整个系统是另一回事。因此,技术多元化并不是我们追求的自由。如果将局部决策权委托给各个团队,就会损害全局。从某种角度来说,这确实是一种自由。你给了开发人员一堆乱七八糟的锁链和挂锁,并告诉他们他们可以自由地做出技术决定。这些技术决策一直伴随着他们,直到死亡来临……更糟糕的是,技术多样性不仅为我们造成了重复工作和维护开销,而且还消除了使用共享平台的积极好处。以Etsy网站的活动页面为例。Twitter和Facebook都具有相似的功能。经过多年的风投,Etsy想要一个类似于他们的功能。所以,在2000年,我开发了这个小功能。开发一个活动流函数,可以这样:从外部获取事件,并将事件写入数据库。然后另一个进程(比如机器学习)聚合这些事件,把结果写入Redis,最后前端流量就可以访问到Redis中的数据了。我们刚开始开发这个功能的时候,没有Redis,所以我们选择了Memcached。它们的功能非常相似:存储二进制对象,然后通过类似的API获取对象。但它们在某些方面有很大的不同,对我们来说最大的不同是Redis支持持久化,而Memcached不支持。也就是说,我们在使用Memcached时需要做一些额外的工作。因为也许当您需要一些数据时,Memcached只是为您丢失了它。为此,我们需要做很多额外的开发工作。但我们将这些额外的工作与添加新数据库可能带来的运营成本进行了比较,并决定硬着头皮继续使用Memcached。这样过了几年,我们很少去想它。有一天,我忍不住想到了这个功能。然后我惊奇的发现这个功能的使用流量比开始的时候增长了20倍。这个功能的用户增加了2000%,我都不知道。当然,这无疑是我技术生涯中的一个巨大成就。发生这种情况是因为我们使用共享基础设施。共享基础设施将由某人照料,根据需要添加更多MySQL实例或其他资源,以及将新机器运行到数据中心并将它们添加到基础设施的人。这是一种水平缩放。然而,这些人都不知道我们开发的应用程序。如果我们一开始就使用Redis,我们可以肯定,在用户流量增长20倍之后,一定会在某个时候出现瓶颈。如果是这样的话,我们就得自己处理Redis的扩容了。或者更可能的是,让其他人去做,因为我们的团队在一年后解散了。但我发现人们实际上并不喜欢擦别人的屁股,所以这对任何人来说都是一件苦差事。我想用这个例子告诉大家,请尽量选择成熟的技术,尽量不要使用太多的技术。但这只是一个建议,请不要以此为指导,因为有时候需要在技术栈中加入新技术。问题是如何选择新技术。简单的说:你要跟大家商量。因为在公司层面采用新技术涉及到整个公司的利益,而不是个别工程师的利益。在讨论过程中,你可以问:“如果你不使用新技术,你如何解决手头的问题?”这个问题实际上是采用新技术的症状。“可能是因为我们没有使用Cassandra,我们为什么不试试呢”。只要迈出这一步,后面的讨论就可以停止了。假设你在现实中遇到这样的问题。例如,如果你在生产环境中部署了一项服务,你认为不使用新技术就无法实现新功能,这可能是因为你想得还不够。你可能需要使用一些特殊的方法,但无论如何你可以通过简单的技术堆栈获得更好的结果。你可以把需要做的事情列一个清单,你会发现情况并没有你想象的那么糟糕。即使它们看起来很糟糕,也肯定不比维护新技术差。当然,也会出现另一种情况:当你把一切都列出来后,你发现采用新技术可能更值得。如果您决定采用新技术,那么请找到一种将风险降至最低的方法。不要试图一次重写整个应用程序,而是逐渐建立信心,一次一点。如果你在技术栈中加入一个类似的技术,那么你就得想办法替代旧的技术,而不是同时维护两种技术。这是一个长期计划。如果发现新技术不合适,也有回滚的能力。总结选择众所周知的技术。选择的技术应该能让您专注于有价值的事情。把问题作为一个整体来考虑,你选择的技术应该覆盖整个问题域,解决所有的问题。掌握您选择的技术是关键。我发现几乎所有的软件系统都遵循这个规律。一开始你认为他们很糟糕,因为你有很多问题。如果您是新手,请尝试在实践中验证此定律。你可以尝试把新开发的功能部署到生产环境,然后你会想:我要为下一个新功能尝试新技术。但使用新技术并不一定更好,因为你永远不知道它们还会出什么问题。可能是因为您跳过了曲线的“精通”部分。虽然这个阶段还有问题,但是你会觉得这些问题是可以解决的。这条定律有一个可怕的悖论:也许你应该使用你最讨厌的技术,因为你越讨厌它,你就越了解它。在使用新技术时,需要遵循一定的流程,比如先与其他人讨论。你应该试着沿着Malos的需求金字塔往上爬,站在全局的角度看问题,而不是每天都在思考是用这个数据库还是那个数据库。如果这是你每天都做的事情,那就有问题了。做有意义的工作会让你充满快乐。好吧,你现在能把我从坑里救出来吗?
