使用 GitLab + Docker 搭建持续交付系统

环境要求

  • GitLab CE > 8.0
  • Docker > 1.0

步骤一,开启 Runner

Runner 是 GitLab CI 的任务执行单位,GitLab 以服务发现的方式来将 Runner 分布在不同的主机上。根据官方文档的说明,你可以选择任何系统的主机来部署 Runner。这里我为了图方便就直接采用 Debian 源来安装了。

由于我们需要让 Runner 在 Docker 中运行,所有首先安装 Docker

curl -sSL https://get.docker.com/ | sh

然后安装 Runner

1
2
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash
sudo apt-get install gitlab-ci-multi-runner

然后我们需要启动 Runner 并提交它的服务信息给自己的 GitLab 站点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sudo gitlab-ci-multi-runner register

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com ) (如果是私有部署的 GitLab,填写自己的域名地址)
https://gitlab.com
Please enter the gitlab-ci token for this runner (在 http://{your.gitlab.domain}/admin/runners 下可以找到共享 token,这样注册的 Runner 可以给所有项目共享,你也可以在项目配置中找个每个项目专属的 token,这样注册的 Runner 就只能由这个项目独享了)
xxx
Please enter the gitlab-ci description for this runner (描述)
my-runner
INFO[0034] fcf5c619 Registering runner... succeeded
Please enter the executor: shell, docker, docker-ssh, ssh? (我们用 docker)
docker
Please enter the Docker image (eg. ruby:2.1): (Docker 镜像,也是该 Runner 的运行环境,如果你有一些特殊的需求,例如添加 ssh 访问私钥,配置预安装软件等,可以自己做一个镜像提交到 docker hub 上面)
ruby:2.1
INFO[0037] Runner registered successfully. Feel free to start it, but if it's
running already the config should be automatically reloaded!

步骤二,分配 Runner

然后下一步我们就可以在 http://{your.gitlab.domain}/admin/runners 下找到刚刚注册的 Runner 了,这时候 Runner 处于共享状态,我们可以通过编辑来指派 Runner 的特定项目,或者给 Runner 加标签来方便以后更灵活的分配这些 Runner。

然后再看一下项目的配置,将 Build 选项开启,这样每次提交时 GitLab 机会自动调用 Runner 来执行任务了。

步骤三,编写 .gitlab-ci.yml

.gitlab-ci.yml 是 GitLab 提供的一种配置文件,对于熟悉 travis 这类 SaaS 型持续集成服务的开发者来说这种配置是相当亲切的了,而且文件跟着代码库,编辑起来非常方便。

下面就这个简单的配置文件说明一下各部分的作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
before_script:  # 在所有任务之前执行下面的脚本
  - node -v && npm -v

services:  # 使用 docker 时,runner 会自动下载这些镜像并以 link 的方式将它们连接进来
  - elasticsearch:1.6.2
  - mongo:3.4
  - redis

stages:  # 指定任务阶段,在一个阶段中可以配置多个任务,各阶段按顺序依次执行
  - test
  - deploy

cache:  # 在各任务间缓存文件
  paths:
  - node_modules/

# 一下非关键词开头的配置就代表各个任务了
test:
  stage: test  # 任务可以通过阶段来决定执行顺序
  script:      # 任务的执行脚本
    - npm prune && npm install && npm run test-gitlab
  tags:        # 通过 tag 可以指定由相应的 runner 来执行这个任务
    - docker

# 由于是为了搭建持续交付系统,所以我配置了两个任务阶段,测试阶段结束后进入到发布阶段。
# 因各人发布环境的不同可以选择不同的命令发布代码,填写在 script 中即可
deploy:
  stage: deploy
  script:  
    - env && pwd && ls -a
  tags:
    - docker

这样,我们就实现了在每次代码提交时自动测试,通过后将代码发布到服务器环境的目的。

遇到的问题

  1. 使用 Docker runner 时,git clonenpm install 有时候会遇到「检测到未知的 host key」提示,而中断 build 进程

这个问题有两种方法可以解决,一种是用 ssh -o "StrictHostKeyChecking no" [email protected] 关闭指定用户和域名的检测。另一种是 ssh-keyscan host >> /root/.ssh/known_hosts 将检测结果写入。上面在 Dockerfile 中用了第二种方式:

RUN ssh-keyscan github.com >> /root/.ssh/known_hosts

  1. Container 遇到 Couldn't resolve host 问题

这个问题我没有找到真正的解决办法,因为它是个偶发的问题,可能你什么都没干,过段时间再试试它就自己恢复了,可能与 Host 主机的 DNS 设置有关。我的解决方案之一是删除所有由 GitLab 创建的运行状态或等待状态的 Container,再重新开始任务。这里提供一个便捷的命令来删除所有由 GitLab 创建的 Container

docker ps -a | grep gitlab | awk '{print $1}' | xargs docker rm

假期学习计划

看到这个标题,有人要以为是一篇计划清单了,然而,我恰恰是反对罗列清单的,尤其是学习。

不管在哪个时期,总有人感叹,没有时间学习,看着一山比一山高,人家学英语,学编程,不亦乐乎,心里却早给自己找好了理由,无外乎工作忙啦,家里事多啦,环境不利啦。好不容易到了一个假期,可不能浑浑噩噩荒废咯,想起买了几年包装都没拆的书,终于有重见天日的一天了。

实际到了假期,大抵就成了两类

  1. 没计划,没行动,随随便便就过去了
  2. 有计划,没行动,感叹理想终究输给了现实

很明显,还有两种情况怎么丢了呢。因为我觉得「没计划,有行动」实属天赐良缘,可遇不可求,概率太小,不足以作为讨论的条件。而「有计划,有行动」,这样的人,平日里一定是十分自律的,断没有到了假期突然努力充电的理由。这种人也许就是平日里大家所说的「学霸」,可闻而不可见了。

那么剩下的两类情况,就构成了我看法的依据了,假期学习计划,是多么的不靠谱。

假期是什么,于国,是刺激消费,拉动内需,于己,是调整节奏,放松身心。任何人都明白张弛有道的道理。在假期一开始就给自己列了一个必学清单,平白给日子加了一层压力,结果心心念念着这些事,学没学好,玩没玩好,又留下了一堆的惋惜。

学习是个循序渐进的过程,仅靠假期的那点时间,就算天天投入,收效也高不到哪里去。不如在平日里,养成一些小习惯,例如每天留一个小时读读写写,一年就是 365 小时,相当于一个半月的假期了。

在 APP 当道的时代,也可以利用一些小工具来帮助自己养成习惯,在这里我推荐一下Streaks,满足了我的所有需求,最重要的一点是,没有社交。

最后,我的假期学习安排:无

怎样和开发者交流

项目做多了,总会碰到很多争论,特别是在需求交接的时候。今天说一说如何与开发者交流的话题。

通俗易懂

人懂得多了,难免会有点掉书袋,一方面是习惯使然,另一方面也有卖弄的嫌疑。譬如海龟喜欢聊天中蹦几个外语单词,产品会找来一堆方法论和缩写,程序员也喜欢说术语。

当面交流不像书面,阅读者遇到不懂的时候可以随时 Google。遇到有人听不懂的时候,就需要停下来解释这些词是什么意思,打断了本来需要表达的内容。大多数时候,没听懂的会装作听懂,然后在心里骂了千百遍。

通俗易懂是基本原则,把意思表达的小孩子也能听懂,没有人会觉得啰嗦,反而会避免不少误解。

可能的话,边画边说。

逻辑清晰

开发者对逻辑的敏感程度非常的高,如果有自相矛盾的地方,可不是用一两句话就可以糊弄过去的,一定要注意逻辑清晰。

开会中我听到最多的一句话就是,「这里走不通啊」。开发者的思维就像水流,总是尽可能的流向每条支流,如果哪一条无路可达,就会揪着不放。

所以,请一定将逻辑思考清楚,为了达到目标,少绕弯子,找到捷径是最好的方式。如果一个问题自己都没想清楚,就不要忙着公开讨论。

学会 Coding

如今的代码世界已经不是一群胡子拉碴头发很长的大叔们的专利了,在未来,编写代码可能会变得和使用锤子一样平常,我很好奇有人会因为太难或没有必要而拒绝使用锤子。

开发的学习成本已经降得非常低,有很多不错的网站和文档可以查询,如果你想做互联网应用开发,入门 JS 也不过就是一周的事情。

学会 Coding 带来的好处是显而易见的,忽略语法的因素,任何语言都是单纯的逻辑表达,如果你能通过代码将思考过程表达出来,胜过写上一千页的 PRD。同时,和开发者找到了一门共同语言,就不会让他们将你拒之门外。

纯粹的 API

前不久有同事和我谈论起现下 API 维护的困难,抱怨诸多,总结起来大概就是两点,一是需求考虑不完善,很多地方需要在开发中补充条件,二是向前兼容困难,很多历史遗留无法修改,代码臃肿。

在我看来,这些问题的产生,都只有一个原因,就是现有 API 的设计和开发理念,不够「纯粹」。API 的设计就好比凿山开路,必须沿着最短的途径到达目标。有些人为了「Flexible」,喜欢在开发中「留一手」,假象出很多未来可能出现的情况,用额外的代码来做兼容。例如设计一套简单的权限系统,本来简单的 ACL 就能实现,非要觉得以后可能会增加更多的管理员类型,而去赋予各种角色,关系,权限表,这是需求上的多余。再比如设计一套 CURD API,在刚起步的时候就考虑缓存,异步,Job 等等,这是架构上的多余。

如今的 Web 设计趋势是去芜存菁,去掉繁复的视觉效果,注重排版,留白,突出内容,因为 Web 最重要的功能还是让用户获取信息。API 设计有相通之处,一个「纯粹」的 API,应始终保持单纯与直观,一个叫「Create user」的 API,目的就只有一个,创建这条用户信息。至于是否要给这个人发邮件,要帮他初始化哪些业务资料,这些统统都拆分到 Service 中去做,如果需求中没提到这些,那么这个 Service 更没必要存在。这样简单设计的代码将具有更长的生命力,在历经无数次需求修改之后,这些代码能像水中冲刷的基石一样,屹立不倒。

现实已经如此复杂,API 还是让它单纯一些吧。

工具软件的未来

上一篇工具软件的困境分析了我对工具软件现状的看法,归纳一下就是两个问题:1. 使用体验难创新。2. 用户需求难覆盖。下面说一下我的解法。

新的平台

颠覆性的创新更容易出现在新的平台上,移动设备的普及让人们习惯了手势操作。但在今天,移动设备上做交互创新已然不是一个明智的选择,而新的平台其实就在我们身边。

一个叫 Pokemon GO 的游戏火遍了全世界,其最大的特点就是利用了增强现实技术,让人们在现实世界中寻找游戏的乐趣。

增强现实和虚拟现实之所以有吸引力,是因为他能给人带来新奇的同时又不感到陌生,天然的容易上手。工具软件在这个领域大有作为,例如,如今许多人喜欢用电子名片,或者把自己的信息发布在互联网上,如果软件能通过摄像头识别出对方并且显示信息的话,对于我这种永远记不住陌生人名字的人来说,实在算是一种福音。同样适用这种技术还有地图,视频,社交,以及很多意想不到的地方,充斥着生活的方方面面。

如果觉得新的平台实验性太强,那么在旧的平台上,也可以用新的方式来创新。在我看来,语音在移动平台上还没有完全发挥出应有的作用,目前的技术对于语音识别的准确率已经完全没有问题,难点在于对语义的分析和揣测用户的目的。Siri 大家都觉得好玩,但是不好用,问题就在于人们不知道能用它干什么,Siri 也「听」不懂你想干什么。而这在目标比较单一的工具软件中就能得到很好的应用。如果有一款应用是用来推荐餐馆的,那么我更乐于通过自然语言的方式让他为我推荐附近好吃的餐馆,而不是每次想好了关键词再写在输入框里。

海纳百川

工具软件需要应对用户提出的各种需求,这些需求零散,独立,无法整合在一个应用中,然而对于留住用户又必不可少。传统软件的做法是自己开发,然后发行一款配置无限繁琐的软件,或者针对大客户做定制化开发。这种做法在工具匮乏的时代可以在市场中站稳脚跟,如今成本这么高的做法是走不通了。

于是就出现了开放 API,各个软件将自己的 API 开放出来,供其他软件接入。这在工具类软件中尤其鲜明。一款好用的软件,只需要做好自己的核心功能,并接入其他优秀软件。

仔细想一想,这其实就是各种软件在做的「应用平台」。但是我不愿意将它称作「平台」,而更乐意称作「协议」。「平台」意味着大家只能加入到我的软件生态中来,「协议」则表明了一种开放的态度,大家可以自由的选择与我的协议对接,或选择其他应用的协议,甚至利用我的协议,和其他第三方应用对接。

服务至上

软件作为一种看不见摸不着的产品,天然的隔绝了用户和开发者,用户看不到开发软件背后的付出,于是很容易低估软件的成本。现实的软件发行方式也增强了用户的这种观念,大部分软件都以免费的方式发行,软件变得和说明书一样,成为了「载体」的附庸。

而在其他领域,用户的付费意愿则比软件高得多,用户拿到一台相机,很容易通过做工和质感估算出这台相机的成本,而其附带的软件则看起来一文不值。甚至改变了世界的 iPhone,大部分用户还是直接将它和手里的手机划上等号,而很少有人去了解 iOS 的成本。

这种观念根深蒂固,那么工具软件该从另一个角度出发,找到自己的「载体」。如果工具软件没有对应的硬件,可以将与软件配套的服务作为「载体」来出售。例如给用户的咨询,培训,发展线下的社区,一方面可以给开发者带来直接的收益,同时也大大提高了用户粘性。一款软件能否和竞争者拉开差距,更多的是看与软件配套的服务,我想这也是「软件即服务」的定义。

写在最后

在软件这个行业,每天都能看到很多很棒的点子,希望这些点子能尽早变成现实,而不是像我这样的拖延症患者,挖了一堆,离完成却遥遥无期。

工具软件的困境

这个话题改成「软件的困境」,我觉得也没什么不妥,但是船小好调头,从一个领域说起,总能更有说服力。平时写的最多,用的最多的就是工具软件,现在来分析一下工具软件的困境。

工欲善其事,必先利其器。随着互联网的普及,软件从一个专业领域的工具,飞入寻常百姓家,成为了人们生活的一部分。软件界的摩尔定律依然有效,曾经动辄上百万的解决方案,如今也能找到免费的替代品。而这些成熟的软件背后,是几百人在键盘面前的敲敲打打,软件的人力成本节节攀升,盈利就成了一个很大的问题。

匮乏的盈利模式

软件的收费模式基本可分两类,一类贩售软件本身的价值,给软件一个定价,由人去下载,例如 App store 上的一票收费软件。另一类是贩售软件附带的服务,例如依靠购买会员,道具等虚拟物品盈利的网站。

上面这两类盈利方式都有局限性,第一类本身造就了一个很高的门槛,大部分人不肯为素未谋面的软件买单,而且这类软件如果能在自己的行业内做到占有量第一,也就意味着触到了天花板,难以发展新用户,老用户也不再买单,这时的出路就只有推出新产品或进行大版本升级,接下来造就的产品,要么华而不实,要么臃肿不堪。

第二类收费模式通常会带一个免费版,满足 80% 用户的需求,然后让另外 20% 用户为软件买单,养活所有的用户和开发者自己。这就很容易造成需求的失衡,为了追求「转化率」,开发者肯定优先考虑付费端的需求,对于大部分用户需要的功能则被「列入计划」迟迟得不到开发。开发者大部分时间在做的都是给需求排优先级,而忘了考虑软件本身的定位。这也是为什么很多软件刚面世时非常惊艳,迭代了几个版本之后却变得平庸。

固化的使用体验

工具软件如何从一并同僚中脱颖而出,使用体验起到了相当重要的作用。软件的发展过程就是一个去繁化简的过程,早期糟糕的软件培养了糟糕的用户习惯,例如常见的顶部菜单就是一个错误的存在,懒惰的开发者将所有的功能藏在菜单里面,让用户通过反复点击去寻找。如果当初的工具设计者能够合理的布置空间,用户使用软件的效率必能得到一个极大的提升。因为用户已经习惯了这种操作,往后的所有桌面端软件都沿袭了顶部菜单的模式,因为改变习惯需要冒较大的风险,体验好坏很难说的清楚,于是用户继续忍耐着打开一个文件需要点击 4 次的操作。

好在如今的移动端应用已经很少用到菜单模式,工具软件很容易在一个新的平台上面找到创新点,例如 Clear 就靠着方便的手势操作获得了大批拥趸。而到了今天,经过了大量 App 的锻炼之后,用户在移动端的使用习惯也已经固化,新的软件将很难再依赖使用体验来吸引用户。

难以满足的需求

关于工具软件应该是大而全还是专注于一个功能,一直难下定论。有意思的是,这个问题在国内外呈现出完全不同的两派做法,在国外我们发现了很多小而美的工具软件,例如前面提到的 Clear, sunrise, paper 等,在国内知名的软件都是功能完备的,例如做支付的微信和做社交的支付宝,似乎每家都觉得能把自家的软件做成操作系统。

一个软件获得了一批种子用户,证明了这个软件的价值,也带来了各种稀奇古怪的需求。工具应用本身的目标是提高用户效率,而如果每个软件只能满足一个需求,用户就不得不在一大堆的软件中频繁切换来满足日常所需,这本身就非常低效。所以我认为工具软件迭代了几个周期之后,免不了加入很多不曾计划的功能,以至于同质化越来越重,竞争对手越来越多,想要脱颖而出,光靠软件自身的素质是非常难的了。

写在最后

如今想要盈利,开发工具软件实在不能算是一门好生意。固化的使用习惯,难以满足的个性化需求,都会让开发者入不敷出。然而市场依然在,需求依然强烈,仔细思考一下工具软件的未来,成为这个领域的黑马也未可知。

生活的品质

说起程序员,在众人眼中可能是最不注重生活品质的群体了,每天穿着印有各种 Logo 的T恤,头发乱糟糟,工作在显示器的包围中,这大概就是对这些人的固有印象了。

现实中,其实每个人心里都有着自己对生活品质的追求。我认识的很多程序员,在工作之余也有着丰富的生活,有的喜欢健身,有的喜欢远足,还有的可能觉得吃烧烤就是最大的乐趣。懂得生活的人,在工作中表现也不会差,因为这些人有着积极乐观的态度,知道去追求更好的生活,也知道工作是提高生活品质的基础。

下面来说说我对于生活品质的理解。

舒适

平时所用未必需要美酒佳肴香车豪宅,舒适是基本的标准。

前不久我在某粗粮品牌电商上买了几条毛巾,号称使用了更好的原料,达到了 A 类的标准。到手之后感觉果然比以前用的好很多,柔软度和吸水性都很好,价格也不贵。以小见大,在购买每件日常用品时,多考虑一下舒适性,比以前的标准提高一点点,那么整个生活品质就有了极大的提升。

便捷

学生时代没有钱,但有时间去折腾。所以需要用一些软件或玩游戏的时候,就会想方设法的去找破解,实在找不到破解时,宁可使用质量较差的免费替代品,也不愿意出钱去购买。我想大多数 80 后都有同样的体验,也逐渐形成了国内软件必须免费才有人用的大环境。

然而不同的时代有不同的消费观,如今软件影响到生活的方方面面,如果一款软件将你每天的计划事项安排的井井有条,节省了大量的时间。如果一款游戏让你爱不释手,陪你度过了大量无聊的时光。那么就它们带来的价值而言,价格就显得微不足道了。

与其花大量的时间在寻找破解上面,不如花少量的钱,获得更好,更早的体验。在虚拟世界如此,现实生活中亦是。

兴趣

就如上面所说,有人喜欢运动,有人喜欢宅,这与性格相关。每天能有几个小时自由的时间,做着自己爱做的事,就是最大的乐趣了。

小的时候,为了融入集体,发展自己兴趣的时候往往也要受别人看法的影响。就拿足球这项运动来说,很多人为其痴迷,也有很多人认为这是一项无聊的运动,但是一旦到了某些大赛的时候,足球就变成了每个人的话题,仿佛所有人都成了球迷。其实大可不必如此,既然是兴趣,就得由自己做主。我喜欢 RTS,喜欢看书,喜欢台球,有段时间还迷过 F1,即使同好的人再少,也能乐在其中。

生活的品质需要以经济作为基础,但是品质的提升却发自内心。如果没有了对美好生活的期待和追求,那么即使腰缠万贯,不过就是金钱的奴隶,成不了生活的主人。

好好享受每一天吧。

存在的意义

外公走的时候 79 岁,从我上次见到外公已经有一段时间了,对于亲人的突然离去,本以为会是一件很难接受的事情,然而真的到了那时,内心却是非常的平静,仿佛一瞬间参透了生命存在的意义。

人这一生,大部分时间都是为别人活着。在社交中在意别人的眼光,在家庭中考虑家人的感受,很少有完全出于自主意愿的生活。这在心理学上也早已有了解释,只有在婴幼儿时期人们才会完全由「本我」驱使,而一旦进入了社会这个大熔炉,大部分的日常行为就由「超我」来驱使。

对于长生不老,自古以来就是人们的终极追求之一,而往常所说的长生基本等同于「本我」的长生。现代医学的发展确实也让人类的平均寿命在不断的提高,但是人力终须遵循自然的规则,生老病死也是人生完整的一个组成部分。与其期待形体的长生不老,不如常常思考怎样让自己的「超我 - 精神」绵延不绝。

纵观历史,有很多人确实做到了死而不朽,例如到现在还在折磨着广大考生的牛顿高斯等辈,让江山如此多娇的各代能人志士们。他们的思想和事迹传颂了千百年,而且想必还能传递到更久的将来。可以说他们的「超我」已经达到了永恒。

然而毕竟不是每个人都能达到这样的高度,即使有人有这样的天赋,也未必时运能济。所以我觉得只要让自己的行为能真实的符合「自我」的意愿,又能实现「超我」做出一点点努力,那么已经算是实现了自己的价值。

在生活和工作中,如果能保持高产,让家人和朋友感受到有你存在的快乐,自己也能在日常中发现自己的价值,那么这一生就是有意义的。

祝外公在天堂安息。

竞技的乐趣

这本是在 2012 年的时候准备写的一篇文章,当时写了个标题就没下文了,现在想来,应该是忙着「竞技」去了,哪有这功夫来写文章嘛。

时过三年,最近开始常玩星际2,于是又想起这个主题,终于可以补全这篇文章。

打星际你快乐吗,这是知乎上面的一个提问,回答的都是星际爱好者,答案自然是一边倒。如果是半年前,我的答案是模棱两可,因为水平实在是菜,被虐是常有的事情,自然也就很难体会到游戏的快乐。好在一段之后之后,总算入了门,也能和同一分组的人打的有来有回,并且开始思考战术,运营,操作,这个时候仿佛才真正感受到这个游戏的魅力,这种快乐不来自于游戏本身,来自和你对战的人,而最终则是来自自己的满足。

RTS 中你的对手是电脑和人,是两种截然不同的体验,电脑循规蹈矩,打的多了,你就会对什么时候会发生什么事情一清二楚,好比是参与考试,努力总能获得回报。而一旦对手换成了真人,变数就增加了很多,总能在一些比赛中出现意想不到的战术,也就是俗称的大招,将每场游戏的体验都变得不同,就好比是工作中遇到难解的问题,很多无法从书中找到答案,以往的知识解决不了,就要强迫你去思考和尝试。

星际2不是一个适合放松休闲的游戏,一场十分钟的游戏就包含了早中晚三个阶段,必须时时刻刻洞察局势调整战略。当战局陷入僵局时,又需要足够的耐心来等待胜利的时机,有无数次我的对手因为耐不住性子强冲而全军覆没,反之亦是如此。我本是一个不服输的人,然而在游戏过程中,却是胜负各半才能让人真正感受到竞技的挑战和乐趣。现在的游戏阶段中,我学到了耐心,尝到了胜利的喜悦,希望以后还能从游戏中得到更多。

只要比赛还没结束,永远不知道下一秒将发生什么。

最后推荐一个歌单,在上班时听着这张专辑写代码,感觉真是爽到飞起。

OKR 解读

什么是 OKR

关于 OKR(Objectives and Key Results)是什么,网上的资料实在是太多了,为了节省时间,在这里简短的概括一下:

  1. 目标(Objectives),为未来的某个节点(通常为三个月)设定几个目标,这些目标需要可量化,有相关性,并且有一定的挑战性
  2. 关键成果(Key Results),为了达成和量化这些目标,为每个目标设置一些关键成果,例如为了完成早晨起床出门的目标,需要完成穿衣,刷牙,洗脸等关键成果。

从我的了解来看,一个好的 OKR 必须具备的三个特征:周期,创新,关联性

周期

周期是指目标需要在有效的时间内达成,之所以把时间放在第一位考虑,因为任何人面对一个没有明确时间的计划是没有执行力可言的。

一个长久的愿景,适合作为理想,而目标则要求我们只争朝夕。

明确的结束时间可以很好的帮助你回顾和开启下一轮任务,形成一个良好的任务周期能让你的工作习惯更为健康。

创新

好的目标应该能激发你的动力,所以必须有一定的挑战性,而创新则能鼓励你走出自己的舒适区,去挑战陌生的领域,激发自己的潜能。

关联性

目标要有关联性,团队中各人的目标都是可见的,在制定目标时,不妨与其他人交流一下,看看自己的目标是否与团队的战略方向一致,是否目标与他人有重合的地方。如果自己的目标与任何人都无法重合,则很有可能是自己跑偏了方向。

一般而言,上级的 Key Results 很可能会与下属的 Objectives 一致,由此在公司中可以形成一个瀑布式的目标关系链,源头就是公司的总体战略。

OKR upon SMART

SMART 是八十年代提出的一种任务制定方式,OKR 也是源自于此。它要求制定任务时参考下面五个指标:

  1. 明确性(Specific)
  2. 可量化(Measurable)
  3. 可实现性(Attainable)
  4. 相关性(Relevant)
  5. 有时间限制(Time-bound)

可以看到 OKR 对于目标的大部分要求都与上述条件契合,但是弱化了”可实现性”,提升了”挑战性”的比重,以激发成员对任务目标的追求。因为 OKR 强调与绩效考核分离,成员在制定更有挑战性的目标时也会少一些顾忌。

然而我却觉得绩效仍然是不可缺少的一环,如果 OKR 不能作为绩效的评估依据,则需要寻找其他的方式来评估绩效,例如 Peer Review 或 Focal Review。但是这又增加了成员的负担和时间成本。而且,无关绩效的目标,实现的动力也将大打折扣了。

OKR vs KPI

OKR 和 KPI 最大的区别就在于 OKR 分离了绩效考核的部分,而 KPI 则使用更突出的量化标准将目标与绩效严格挂钩。这也是 KPI 最为人诟病的一个地方,会导致成员只关注绩效而忽略了本该有的创造性工作,甚至出现绩效造假的情况。

不管 OKR 还是 KPI,让每个成员各尽所长才是制度的目的,而且,找到合适的人,比任何制度更有效。