背景
对于追求效率的程序员来说, 影响工作效率的事情, 是深恶痛绝的, 当大家拿到任务的时候, 其实对于工作量的评估, 心中大致都是有一个数的, 然而, 为什么我们交付的时候, 大部分情况下会比估算的时间长呢, 有时候还会长达几倍之多?
我总结的几个会影响交付进度的关键问题
工位周边的环境干扰, 例如把销售人员和研发人员放一起;
电脑的软件环境或硬件环境出现问题, 例如 go 的版本和其他人的不一样, 编译他人的代码时会报错;
需求变更或理解不到位;
庞大的技术桟; 不同团队不同的开发语言, 甚至有的是同一个团队不同的开发语言和框架,吐血..;
架构上有重大设计缺陷, 例如有些功能无法通过某种方式实现, 后期又得修改, 此路不通;
前几周都在写 Bug, 后几周在改 Bug, 你看我工作多饱满;
在测试时或发布时阻碍较大, 例如 Bug 多, 研发环境和生产环境环境不一致.
这里不谈技能 Level 问题, 我们统一认为水平为中级程序员即可
如何解决?
本文主要是解决研发顺畅度问题的, 从开发 -> 测试 ->发布的效率问题, 当然, 既然上面提出了几个影响效率的因素, 那我就先说一下这几个问题我们是怎么解决的, 虽然不是最优方案, 但一定是适合我们自己的团队的, 我们团队人较少, 情况大致如下:
后端 4 人
前端 3 人(ios+android+web 采用 ReactNative)
测试 2 人
但是产品内容较多, 比如我们需要和第三方存管系统对接, 第三方资产系统对接, 需要提供管理员系统, 手机 APP, 官网, 以及其他周边的服务系统, 如果不好好解决效率问题, 仅仅凭借这些人员数量, 是远远不够的, 因为这里仅仅是包含了开发的任务, 后续还有上线和解决线上问题的任务.
我来简单说一下我们是怎么解决这些问题的吧, 希望大家能够给予建议, 同时也很高兴能帮助到大家.
工位周边的环境干扰
我们是小公司, 这个问题.... 解决不了, 大家都在一个特大开间里, 只能带耳塞和耳机了... 不过我们的客服大部分是在微信上服务, 以及出去跑业务的, 因此干扰度不是特别大;
电脑的软件环境或硬件环境出现问题
我强制给大家配备 Macbook Pro Retina, 强制大家使用如下工具:
- iTerm2
- brew
- autojump
- Sublime Text
- oh-my-zsh
同时, 我要求编译环境的库版本必须是某个特定版本, 比如 go 必须使用 1.9.4, 这些都是硬性要求, 其他的大家是可以自由发挥.
大家可能会认为配备 Macbook Pro Retina 笔记本的成本太高, 但是我想说的是, 这真的是一个提高研发效率的途径:
大家使用相同的操作系统;
命令行 unix-like,linux 上能用的命令, 大部分都移植在 mac 上了, 不需要搞什么 cygwin 了, 那玩意搞得真心难受, 最后效果也不是很好;
流氓软件目前还没那么多, windows 上动不动就是全家桶...;
比 linux 的 ui 系统好用;
xcode 只能在 mac 上用啊;
如果和同事共享文件, AirDrop 就搞定, 方便, 而且也不用上传到某些聊天服务器上做中转了, 心里踏实.
协作时, 随便拿一台笔记本都像是在操作自己的笔记本一样, 嗯, 这个电影是?
总之, 好处多多, 一定要说服你们的老板啊.
需求变更或理解不到位
一定要要求程序员做需求反讲, 先是产品经理讲需求, 然后是技术消化, 最后研发给产品经理反讲, 确保双方理解一致, 对于频繁改需求的问题, 这个没有太好的解决办法, 因为有时候需求就是变了(这里不是说按钮要放到别的位置, 颜色要换成什么, 主要的是指功能性的需求)
庞大的技术桟
我们的要求就是后端只能用 go, APP 开发 iOS 使用 ReactNative, 打包自动化用 gulp, Web 使用 React, Android 就使用原生开发, 主要技术桟列表如下:
- Go
- ReactNative
- React
- Gulp
- Android Java
- Docker
- Git
这么罗列下来, 其实已经很多了, 我们应该尽可能减缓技术桟列表的增长, 要做好技术选型的把控工作, 不要随意使用某个语言, 某个框架.
架构上有重大设计缺陷
架构本身是随着环境的变化而发生变化的, 需求, 体量, 痛点是推动架构变化的主要原因, 我之前做的是广告行业的技术架构, 当时的痛点有如下几点(有些记不清了):
服务器多, 当时 Docker 尚未兴起(我离职前不久还是很初级的版本, 14 年初, 但 Docker 也是在那个时候快速崛起的);
我们后端使用 Erlang 开发, 招不到人也是痛点;
由于没有 Docker, 部署是个大问题, 从研发环境 ->测试环境 ->生产环境都有差异, 因为这些差异, 找问题需要找很久, 有新服务器加入那更是痛上加痛了, 上百台的服务器啊....;
因为是个大公司, 所以一直在沿用 SVN, 后来给大家做了 GIT 的培训, 搭建了 GitLab, 使用了 GitFlow
当时没有使用 CI, 你就说痛不痛? 其实大公司要使用某个工具, 某个架构, 某个流程, 做大批量的更换是挺难的, 所以很容易就这么痛下去, 都 2018 年了, 我一个同事入职某 60, 这些给研发人员使用的基础设施还很原始呢, 我同事的原话: 完全没法和我们现在的开发环境相提并论.
再说说我们 P2P 行业的痛点:
我们不跑路, 我们是一家很正规的 P2P 公司, 是金融办审查过的
P2P 的业务特点如下
需要和第三方资产对接;
需要和银行, 支付渠道对接;
需要和金融办要求的监管系统对接, 比如合同, 标的信息等等, 都是要传过去的;
需要给客服提供客服平台;
需要给管理员提供管理平台;
有 APP,PC 这些自然是不用说了;
活动推广的体系你得有吧?;
用户活跃度追踪的体系你得有吧?
安全体系你得做吧?
最主要的特点是: 不能错!! 每天的交易都要和银行, 资金通道对账, 每天清算.
对了, 大家如果忘记了我们有多少个人, 可以往上面再翻一下, 另外, 这仅仅是我们的一条产品线, 我们之前希望把控更多的资产, 自己也尝试开始做资产管理, 嗯, 做了一个类似钻石抵押的借款平台, 反正产品线多...
除了业务上有痛点, 公司体量小, 本身也会有一个致命痛点
招聘难: 好的人才可遇不可求, 我们面试到的程序员也大多是初级或中级的, 高级的不多见. 由于我们使用的是 go 语言作为后端语言, ReactNative 作为前端 APP 开发框架, 能找到合适的就是微乎其微了. 大家别看这些概念都已经很火了, 但在我们小公司里, 几乎是招聘不到有这些实战经验的程序员的, 大部分是只有一点开发基础的, 只会一门语言, 甚至没做过项目的, 怎么办? 培训 + 实战, 没有别的出路.
基于这些问题, 我们就有了一个架构设计的思路:
无论对外的服务还是对内的服务, 统一使用 API 调用, 这样我们可以用 postman 进行测试, 或写自动测试工具进行请求;
能快速搭建, 要像乐高组件一样;
要像市面上兼容乐高组件的盗版乐高一样, 我们一部分用正版乐高, 一部分用盗版乐高也无问题, 其实这一点很重要, 我们是希望, 在将来有时间, 有精力了, 能快速换掉质量不好的组件, 因为一开始为了赶进度, 质量把控可能就没那么严格了;
根据上一点的描述, 我们可以进行服务降级, 比如压力大的时候, 将有复杂逻辑的组件替换成简单逻辑的组件
方便本地调试, 也方便自动化部署运维;
压力大了可以做横向扩展, 即无状态;
由于某个功能组件未实现, 我们先放个 Mock 组件进去做测试, 或做初期联调.
为了增加把控度, 我们自己造了轮子, 此框架适用于我们的应用场景, 同时也是开源的, 所以, 非常欢迎大家使用, 并给出建议:
https://github.com/go-spirit/go-spirit
想要快速入手 go-spirit 请戳这里 https://github.com/go-spirit/tourist
前几周都在写 Bug, 后几周都在改 Bug
Code Review
这项任务是必须要执行的, 但仍然解决不了初级程序员, 尤其是入门级程序员犯这个错误, 第一是要提升这位程序员的技术水平, 在每日例会上要碎碎念, 多跟他讲讲设计, 讲讲哪些东西合理, 哪些东西不合理, 经常讲讲行为规范, 比如:
我们不要在 for 循环里一条条去执行 sql 来查询结果, 而是应该在 for 循环前先一次性查回来再处理;
涉密的内容不要提交到代码库;
......
真的很碎, 但这是规范, 也是文化的传承, 小公司可以这么做, 因为人少好叨叨, 大公司则需要有严格的行为准则和制度, 但也应该拆团队, 培养主管对规则和文化的重视.
撸代码前做技术设计
做完需求反讲后, 产品经理和研发人员都对需求有了一定的理解, 接下来最好做一下技术实现上的设计, 先做好磨刀的工作, 再做砍柴的事. 尤其是对于初级程序员, 应该先听听他们的设计思路, 应该给予及时的帮助和纠正, 总比在最后让他们改 BUG 强.
一定要做好 BUG 数量的控制, 否则技术债务会像滚雪球一样越来越大, 本来我们可以好好做研发的, 却要去解决焦头烂额的线上问题, 这是不能容忍的.
在测试时或发布时阻碍较大
大致会有如下的阻碍:
致命性的 BUG 多, 解决同上一个问题
上线过程中一堆环境问题
上线后一堆问题, 和测试环境, 开发环境表现不一致
我们是这么做的
MOCK
尽早稳定好 API 接口的定义, 测试人员开始写 MOCK(只需要写个 javascript 脚本即可, 对请求内容进行判断, 然后返回特定内容), 这样就可以了, 为什么要这么做?
后端开发 API 的实际逻辑实现会比较慢, 前端需要使用 MOCK 来完成对接, 快速实现各个页面的逻辑联通;
方便前端人员做前后端的集成测试, 如果大家都按标准走, 后续对接只需要更换服务器地址的配置即可完成无缝的切换工作;
测试人员在写 MOCK 脚本的时候, 会把业务场景都过一遍, 增加了测试用例的品质;
嗯. 你还可以拿着 MOCK 给客户演示
容器化, 自动化
一定要使用 Docker, 包括编译代码的编译环境. 比如 gulp 编译网站的时候, 研发人员自己的机器能编译通过, 放到别人的机器上编译就不行, 因为安装的环境, 类库版本有差异. 如果放到指定的 docker 里去编译, 则不会出现这个问题;
测试人员是对部署后的 Docker 容器进行测试, 测试通过后, 则是部署被测通过的镜像到线上, 确保环境是一致的(只是配置文件获取的数据源不同, 出现异常时调整配置即可);
无论是哪个端, 发布到测试环境和生产环境的程序, 编译, 自动测试和部署的任务均在 CI 服务器上进行, 而不是开发人员自己的机器, 除了上面提到的环境问题, 还有就是: 放到 CI 上做, 就需要写好 CI 脚本, 一切都是按照预定的计划执行.
所以, 研发人员的研发环境, 是一种习惯, 文化, 更是一整套生态, 从物理上的工作环境到电脑里的系统环境, 从功能到架构, 从研发到上线, 每个环节都可能出现效率上的杀手.
后续
我主要会为大家讲解, 如何搭建一个完整的从 开发到上线的环境, 并且为大家讲解几个 CI 案例, 同时实战 gitlab-ci.yml 的写法, 让每个团队享受 CI 带来的便捷和乐趣.
我们用的是阿里云(小公司嘛, 哪有钱搞机房), 因此, 后续的部署讲解均是基于阿里云的, 大家也可以按照自己的需求, 开发出部署其他云平台的模块, go-flow 是插件化的.
涵盖的内容大致如下(后续根据实际情况做调整):
使用 https://github.com/gogap/go-flow 搭建一整套研发环境
使用 gitlab-ci 编译一个 APK
使用 gitlab-ci 编译一个 todo 程序的示例(go), 从代码提交到发布的整套流程
使用 go-spirit 快速发布 mock 服务
PKI (Public Key Infrastructure) 证书使用
一句话: 不玩虚的, 实战! 实战!
详解前的 Demo
先给大家放几张我们现在正在使用的系统的图片, 全当时给干涩的文字配个图了...
使用 go-flow 搭建下面这些环境的执行截图, 嗯, 我给大家带来的是全家桶, 当然这些是基础环境, 每个公司都会有自己的环境需要搭建, 大家可以为 go-flow 贡献插件哦
大家不用尝试访问图中的地址啦, 因为我迅速的使用 go-flow 释放了这些资源
我们研发所有的服务都做了客户端证书的双向认证, 以防止外人的访问 (PKI) 访问服务时, 会弹出如下提示:
没有客户端证书的人是无法访问的.
Gitlab
每次提交代码, 都能触发自动编译和测试
部分任务可以指定为手动触发, 比如部署, 因为不是每次提交代码都需要部署
有编译的详细过程
不同的 Runner 用于跑不同的项目, 比如编译苹果应用的 runner 就需要跑在 mac 上, 我们公司有一台专门编译 iOS 应用的 MacMini
LDAP
研发人员登录公司内部系统, 都是使用的 LDAP, 用户可以自己登录修改密码.
Graylog
日志系统, 我就喜欢 graylog, 好用, 结合好 https://github.com/gogap/logrus_mate 就可以往不同的系统打日志了.
Redmine
简单易用.
来源: http://www.jianshu.com/p/4e774c78cf8d