外卖小哥

下班了,天空下着雨。我在十字路口等红灯,一位送餐的外卖小哥拨通了客户的电话,解释道下雨天,路上堵,不能及时送达了,能否先让我点送达,我保证一定帮您能送到。客户挺理解的,也没多说什么。下雨天,又是下班的点,迟些送到是很正常的,一般人都能理解,但平台可不管,不按时送到,估计就得扣除信用分什么的,影响小哥的收入。

中午出去吃饭,电梯口,外卖小哥把餐送到后,立马回到电梯里,等人全部进来后,就拼命的按关门按钮,恨不得电梯立马下到一层。中午又是一个高峰期,为了保证及时送达,那必须争分多秒。一下电梯,立马跑步冲了出去,奔向另一个送餐地。大厦门口,不断有外卖小哥跑进跑出。平常吃饭的时间,却是小哥最忙碌的时候。

看着忙碌的小哥,我不禁想,以后还是尽量别点外卖了,让小哥这样急匆匆的为我送餐,还真有点过意不去。这当然是我一厢情愿的想法,换个角度,对于小哥来说,这是一份工作,跑的越急,说明单子多,也意味着收入高。巴不得一天跑到晚,实际上,送餐也就中午,晚上两个高峰期,这两个点的忙碌程度决定了一天的收入。所以我看着小哥匆忙的跑上跑下于心不忍,人家心里一定是乐的屁颠屁颠的。等高峰期一过,小哥就可以悠闲的找个地方睡一觉,他看我们这些上班的人,吃了饭立马还得干活,说不定也在可怜我们呢。有句话说得好,你受再多的苦,在别人眼里都是故事。

所以,外卖到底点还是不点呢?好吧,我坦白,不想点外卖的原因,其实是实在吃不惯。

Read More

反恐中敏捷

“这次针对污水处理厂的袭击是可怕的,但在2004年的伊拉克,这没有什么不寻常之处。到了12月9,伊拉克境内所发生的重大恐怖袭击的数量10,已经超过2003年全世界所发生的恐怖袭击数量11。在2005年,伊拉克的恐怖袭击总共导致8300人死亡12,是“9·11”事件死亡人数的3倍,要知道伊拉克的人口数量只有美国的1/10。伊拉克的人口占全球人口的比例不到0.5%,但这个国家在2005年所发生的恐怖袭击数量以及所导致的伤亡数量,却占全世界的几乎1/3。13而且事情还在变得更加糟糕:2006年春季,每个月都会有超过1000人因为恐怖袭击在伊拉克横死街头。”

《赋能》一书的作者麦克里斯特尔,美军驻伊拉克特遣部队司令,这样描述当时的情景。特遣队规模庞大,训练有素,装备精良,而他的对手,无论从人员素质还是装备上,都远远不如。在战场上却让美军束手无策。特遣队过去拿些引以为傲的经验,在这里完全失效了。基地组织在美军的眼皮底下实施着各种爆炸袭击。

将军意识到他们处于一个全新的环境中,之前的经验已不再有效。基地组织在战争中表现出了极大的灵活性,而美军的组织则显得笨重,低效。为了赢得战争,必须抛下之前成功的经验,从零开始,同时向对手学习。

到2010年,特遣部队的整体架构,行事方式等都完成了蜕变,在战争中也真正占据了主动。将军在书中详细介绍了敏捷转型的演进过程,这里仅摘录几点:

  1. 建立有效组织 基地组织的纸面实力远低于美国特遣队,但它的去中心化,网状组织机构,具有很强的调整适应能力和韧性。所以能和美军抗衡而不落下风。后来特遣队不得不调整自身架构,从原来的自上而下命令式的结构转变成去中心化的网状结构。

  2. 建立互信和目标共享的团队 在充满不确定性的环境中,计划在制定好的那一刻已经失效了,面对不断变化的场景,等待上级指示再行动将会失去最佳的时机。这时候,只能依靠团队本身。成员之间相互信任,每个人都知道整体的目标,而不仅仅关注自身认为,是打造超级团队的基础。海军“海豹突击队”已经成了一个代号,象征着力量、勇气、技能俱佳的超级团队。但和大多数人所认为不一样的是,海豹突击队最优秀的特质其实和队员们的个人素质没有太大关系。

  3. 突破深井,建立关系 金字塔原理一书中提到了MECE原则,意思是“相互独立,完全穷尽”,就是把问题分成互不相关的几类,然后针对每个分类不断深挖。对于分类问题,这是一种有效的解决办法,但在团队运作中却行不通。特种部队在前方厮杀,把获取的情报信息打包扔上直升机。等后方情报人员拿到包裹时,已经几小时之后了。这时基地组织早已改变计划或者转移目标,这些情报即使破译出来,也毫无价值。

  4. 打造体系思维 体系思维就是:“一个人至少要对整个体系有最基本的了解,才能够把自己的那一部分事情做好”。在“深井”中,无论你有多高的效率,只要接口失灵,导致的损失是前者无法弥补的。项目中一旦涉及接口对接,花费的时间就会成倍增加。阿波罗项目因为简单的接口问题,发射失败,损失1.25亿美元。都是缺乏体系思维的一种表现。

最后,我想说明一点,这些方法不是将军刻意选择的,而是形势发展的需要,不得已而为之。在当时没有第二种选择。如今,选择敏捷的组织一定面临传统做法遇到瓶颈,再不转型就无法发展,甚至将面临淘汰的境地。没有这种外部条件而刻意选择敏捷,纯属玩票,效果并不会好。

前两天看王东岳的哲学视频,他反复强调一点,人类文明的进程,并不是人类选择设计的结果,而是被自然进程严格限定的,是一个自然发生的过程。比如,为什么南方人吃稻米,而北方人吃小麦呢?并不是由人的饮食喜好决定,而是当时的环境下,北方人如果不吃小麦,就无法生存,只能选择小麦,放弃稻米。

敏捷转型,相比人为的努力,更需要一个外部环境。

Read More

被遗忘的测试金字塔

提到测试,大家都会把它归于测试人员的工作。测试人员主要在功能级别上做黑盒测试,基本以手工测试为主。极少的人会使用自动化测试。我们都明白软件开发,越到后期,错误的修复成本越大。测试人员介入测试一般都是项目的后期了,这个阶段的测试成本是很高的。因此测试需要在前期低成本阶段尽早介入,很多同学会问,功能都没有开发出来,怎么做测试呢?其实,测试本身也是有层级的,不同阶段需要的测试也不一样。

2004年左右,Mike Cohn提出了测试金字塔的概念,如下图:

整个测试分成3层,UI层,服务层、单元测试层。处于金字塔顶端的是UI测试,就是文章开头提到的这类测试。旁边的乌龟表示测试速度相当慢;美元符代表着高成本,这个成本除了指测试本身的高成本外,还意味着测试问题修复的成本也很高。中间是服务层,主要指接口或组件级别的测试。金字塔底部是单元测试,单元测试的特点是快速,运行时间在毫秒级别;针对性强,如果测试报错,直接能定位到是哪一行代码的问题。单元测试的粒度又很小,所以能快速的修复。底部的两边画了兔子和美分符,整个金字塔从上往下,速度依次加快,成本逐渐降低。

但在实际的项目中,往往都是下面这种“冰淇淋”模型:

单元测试和接口测试严重缺乏,功能开发完成后,直接进入UI测试。这种模式下,UI测试越多,就越头重脚轻。为什么测试投入了很多,整个产品的质量也不见得有多少提高?因为结构错了。开发和测试人员在无休止的bug 修复/验证循环中,身心俱疲,代码的乐趣在哪?工作的价值在哪?当这些都没有了,何来的质量?

“金字塔”和“冰淇淋”两种模式,如果在建筑行业,我相信没人会选择后者,但为什么在软件行业,“冰淇淋”模式还有大片的市场呢?

软件的质量如何来保证,戴明早已经告诉我们了:“我们应该停止依靠大量检验来保证质量,而是要改进工艺流程,从一开始就生产出优质的产品。”

对于软件项目,所谓的改进工艺流程,就是让测试具备“金字塔”的层次结构。

前两天看到朋友圈里开发在抱怨自己都要变成测试了,不禁想起之前的公司老大给我们讲“eat your own dogfood”,当时不明白是啥意思,“狗粮”这个词,本能的让我感觉不是什么好话。它原本的意思是要求员工尽量多的使用自己开发的产品,从而提高产品的质量。老大对我们开发讲这句话,意思也清楚,开发必须要对自己的代码质量负责。开发吃狗粮的方式就是金字塔的底下2层。我们当时连顶层的UI自动化测试都做了,但效果并不是太好,UI级别的自动化测试太脆弱了。

我一直认为,开发一定要有测试思维,优秀的代码是自己不断测试/重构中产生的,而不是靠外人的测试。

Read More

部署脚本演进

####缘由 系统在外网开发,但测试、生产环境却在内网私有云上,两边的网络不通,像Jenkins之类的持续集成工具都无法使用。内网环境的部署都是通过手工操作的。整个项目大大小小7个包,从外网拷到内网,再备份、部署,花的时间也不少。后期随着用户访问量增加,系统横向扩展是必不可少的。应用部署在多台服务器上,这时如果还采用手工方式,那工作量将成倍增加。其实除了从外网拷到内网这一步需要手工操作外,其他的都可以实现自动化。按照谷歌SRE的标准,部署工作属于琐事,应尽量将时间减少到最小。于是这段时间整理了备份部署的流程,并编写了相关的脚本。

####脚本需求 灵活性: 系统最后将产品化,会在不同的环境下使用。脚本应体现足够的灵活性,满足在不同环境下部署的需要。

支持分布式部署: 产品中的各个应用模块都支持横向扩展,脚本需支持多服务器并行部署,当服务器增加时,部署工作量不应随之增加。

####部署流程 准备一台部署服务器,所有的脚本统一在这里管理,运行。如果没有多余的机器,也可和某一个应用共用一台服务器。备份、部署流程如下:

####单机部署脚本 为保证脚本的灵活性,把可能变化的值都写到一个配置文件里,脚本运行前会先加载该配置文件,以获取相应的参数值。

每个应用一个部署脚本,后面可以灵活组合,也可以做一个简单的人机交互界面,方便小白人员使用。

实现集中式部署,需要解决两个问题:

  1. 部署服务器和各应用服务器之间实现ssh双向免密连接。方法如下: a. 用“ssh-keygen -t rsa” 命令生成公/密钥。 b. 用“ssh-copy-id -i ~/.ssh/id_rsa.pub 用户名@ip”命令把公钥复制到远程服务器。 然后在另一台服务上再操作一遍,就可实现双向免密连接

  2. 脚本虽然在部署服务器上运行,但其中关键的命令是要在远程应用服务器上执行的,用以下方式实现:

    ssh root@$ccuap_server_ip  << remotessh
    # the script here will be run in remote app server
    ...
    ...
    # exit when finished.
    exit
    remotessh # don't leave space at beginning.
    

    另外,脚本中尽量不要使用rm -rf xxx,特别是像 rm -rf $path/这样的命令,有很大的风险。一旦变量path为空,就相当于“rm -rf /”, 如果又恰好以root用户执行的,那后果就相当严重了。我的办法是先mv到临时文件夹中,后面再统一清理。

####并行部署脚本 开始的想法是通过“deployXXX.sh server1 server2”这样的方式来实现多服务器部署。这种方法服务器多了也不太方便,脚本里又需要加各种判断,循环,增加了复杂度,不易维护。后来发现有并行ssh工具,并行部署的问题就变的简单了。我用到的工具是这两个:

  1. mussh 该命令可以并行的在多台服务器上执行一段脚本,用法如下:
    mussh -H hosts -C xx.sh
    

    hosts文件里维护一个主机列表,每行一个主机名或ip。 xx.sh就是要执行的脚本 mussh无需安装,网上下载的压缩包,直接解压就可使用。

  2. pscp 并行scp,可以同时复制文件到多台服务器上,用法如下:
    pscp -h hosts source dest
    

    网上下载pssh安装包,建议源码安装,pscp是里面的一个工具。 有了这两个个工具,把前面的部署脚本修改下,就可以实现多服务器并行部署了。

Read More

场景穿透

有趣的故事更容易被记住,利用场景穿透法可以让场景变得更有趣。

一个人在蹲马桶的时候,拿起了旁边的洁厕灵,背面的产品介绍是这么写的:如果你现在正在看,说明你忘了带手机。这个人觉得很有趣,把它放到了网上,结果这个品牌的洁厕灵大卖。洁厕灵不仅可以清洁马桶,还能让你打发无聊的时间,穿越了固有的场景。

窗外有人在喊:“打死,打死,反了,反了”。乍一听,以为外面在打架,探头一看,原来是丈夫在给妻子指挥倒车。

场景穿越,需要用不同的视角来观察,打破常规的思路,给人以意外的惊喜。

Read More