目前每个月Segment已经为数百个不同的关键业务应用提供了超过500亿次API调用,包括收集、转换和路由等。在这方面我们已经走了很长的路,成立之初我的联合创始人和我仅仅只跑了少数的应用实例。
现在,我们对我们所解决的问题已经有了很深刻的理解,与此同时我们学到了很多东西。为了保持快速对问题的解决并且避免之前遇到过的错误,我们团队已经开始总结一个最佳实践列表。
既然这些大量的"pro tips"已经被全面测试过且已经经受住了生产的考验,我们希望能与你分享这些tips。值得一提的是,我们是站在巨人的肩膀上,不断从《The Zen of Python》、《Hints for Computer System Design》《Twelve-Factor App》等中获得启发。
编者注:这篇文章基于wiki的关于Segment的"pro tips"相关网页,在网页上有更多的建议列表在那里,但是我们只选择一些看起来最广泛适用的部分。这些tips被记录成事实,但我们把它们视为准则,用于在团队中权衡取舍,每个实践都带着解决问题的优点。
耦合比切分更容易
当我们一开始,我们就有了一个臃肿的项目,每一个模块都被依赖完完全全地紧紧耦合在一起并且完全被控制。当我们要更改一个简单的API时,会涉及到整个代码的改动,这时如果越来越多的人同时参与协同开发简直就是噩梦。
所以随着团队的不断壮大我们首要做出改变的是切分所有模块,将它们切分成多个单独的资源。切分是一项巨大而繁杂的任务,但是这使得一个大团队的开发工作大大受益。不幸的是切分工作难以开展,因为我们在一开始就把所有模块都结合在一起了。
事实证明,这种让资源耦合的诱惑因素无处不在,包括各种服务、各种库、各种资源以及各种工具,我们很容易在现有的代码基础上添加一个新的特性,但这个特性存在长期成本。解耦有关联的模块,这就是为什么类UNIX风格的系统如此成功的确切原因,他们提供很多像小积木一样的工具让你根据自己需要组合成更为复杂的程序。
编写结构式的代码方便以后做切分解耦(或者从一开始就切分好)
如果一个服务或一个库没必要共享于现有的那些服务或库,最好创建一个新的服务或库而不是将相关代码引入到已存在的代码中。
测试和文档库是独立成单独模块便于理解。
当相关的服务结合在一起时要特别关注IO,确保正常运行,监控资源消耗和记录监控。
比起框架偏向于使用库,如果可能将他们合并。
明确优于隐式
"聪明"的代码通常意味着"复杂"的代码,这样的代码总是很难理解而且当bug发生时也很难去跟踪,我们更喜欢简洁的代码,简洁的代码明确地告诉我们它的目的是什么,而不是去创建一个看起来很神奇且依赖全局的API,我们喜欢事情看起来不那么神奇。
如何做到具备明确性,需要总是考虑你的代码是不是难于被定位,假设你正在查找post方法的实现在哪里,在代码库中哪个更容易被定位到?
var methods = ['post', 'put', 'get'];
methods.forEach(method){
Integration.prototype[method] = request(method);
});
vs.
Integration.prototype.post = function(){
[...]
};
在可能的情况下,编写简短、直白、简单理解的代码。通常情况下,这取决于将代码分割成若干简单的功能,这些简单的功能方便测试且容易编写文档,甚至一个库也可以仅仅只是实现某一简单功能的库,通过组合这些库实现更加强大的功能。
对于给定的一个过程或程序,描述清楚"为什么"与"是什么",如果一个程序看起来不太合适但又是必要的,可能这个时候就要留个便签描述下为什么他有存在的必要。
避免动态生成代码或过于"聪明"地缩短代码的行数。
以每个函数少于7行和少于2个嵌套回调函数为目标。
没有指标和测试绝不正式运行
没有性能指标和报警就把代码放到生产上去跑就像是盲人摸象,这种情况已经让我们团队吃了很大的亏,所以我们增加了测试的覆盖面和增加广泛的监控,每当用户比我们先遇到一个bug,就会损坏他们对公司的信任,这是相当糟糕的。
作为一个公司,最宝贵的资产可能就是用户对我们产品的信任,一旦失去了用户的信任对于公司就是无法挽回无法恢复的,在商业上我们就失败了,我们的品牌建立在大量的用户信任上,而产品可靠性对我们的成功是至关重要的。
先编写测试用例去检查程序运转状态,再修复发现的bug。
所有顶级应用在生产上运行都必须具备指标和监控。
当系统内部运行不正常且开始影响终端用户的时候要创建"警告"报警提示。
在设计报警时要尽可能想象更多一些想象不到的故障场景。
积极削减范围
在我们构建产品时我们可以在这三方面进行优化:速度、质量和范围。美中不足的是你永远不能同时兼顾这三个方面,牺牲质量而导致更多的修复补丁会增加我们的技术债务,从长远来看更是使我们速度变得更慢,而且我们将遭遇客户对产品信任度的流失,在后期的工作开展将是一个巨大的阻碍。
与此同时我们也不能牺牲速度,作为一个创业公司,速度效率正是我们的主要优势,长期运作的项目就像个累赘不断拖累我们,它消耗了大量的资源而且没有明确定义一个"结束"的时间,而当这个庞大的产品终于完成准备推出时,如何将一个庞大的产品向用户发布使之接受又将成为一个艰巨的过程。
在迫不得已时,最好的做法就是削减范围,这样我们就可以将货物分成更小块,变成更易于管理的块,最后才能真正做到专注于每小块做到极致。
通过比较利益与工作量去评估一个功能。
分析鉴别所有功能可以方便以后对功能的分层。
削减明显会导致技术债务的功能。
Read full article from [译]Segment开发团队的最佳实践
No comments:
Post a Comment