创业是苦差事,并且风险极高,在这样的条件下,如果还不依据一定的工程原则做事,无异于在黑暗中走钢丝。
虽然哥创业时间不长,且目前尚无过人业绩,但文中所列工程原则却也来自一线实战,如今写出来,既是个人总结,也是经验分享,算得上对这些年奋战的交代。
原则1:不折腾
如今,创业的技术门槛要比以前低很多。随着开源精神的深入人心,目前的绝大多数技术问题都有相应的开源解决方案,而且质量不低。因此,作为技术队伍,主要目的就是能够善用这些工具,快速给出业务解决方案,赢得市场和客户。
然而,话虽如此,选择适合团队的技术工具栈却并非那么简单。有人可能会说“跟着大家一起走就好了”,可问题的关键在于,适合大家的技术和工具是否就一定适合你呢?况且,目前各大巨头的技术营销能力都不差,在这样的情况下,这道选择题就没有那么容易了。
就我个人的原则来讲,技术选择的最高要义就是:不折腾。选择必需结合团队本身的特点和工具本身的成熟度,尽量不要将宝贵的时间浪费在对于这些工具的折腾上。
案例:为何我选择Angular 2作为团队的前端基础?
目前,前端工具的当红炸子鸡当非React和Vue莫属。当初,我曾考虑过是否在团队中引入React,但经过一番考察和思索之后,我毫不犹豫弃之转而拥抱Angular 2。令我做出如此决定的原因主要基于如下考虑:
- Angular 2是一个整体的工程解决方案,从开发、测试、打包和部署,都提供了工具支持。尤其是Angular CLI,对于简化开发起到了巨大的作用。相比而言,React仅解决了V的问题。
- 团队内部移动端的技术选型为Ionic 2,它恰恰使用了Angular 2作为开发基础。相比起React Native,它更成熟。
- AngularJS 1的若干问题已经在Angular 2中解决,这样一来,React显现出的优势并不大。而且,相比起React的使用,个人认为Angular 2更容易让团队成员上手。
注意,这里并非说React不好,而是觉得相比起Angular 2而言,使用React会让团队更折腾,这不是我期望看到的。至于个人是否玩React/Vue,我并不关心,甚至是鼓励。
原则2:守规矩
我曾经看到过这样一句话:“以敏捷的名义裸奔”。这句话非常贴切,而且在创业团队里类似的事情并不少见,只不过“敏捷”两字被“时间紧”替代而已。
正如有些钱是省不掉的,有些做事的原则必需遵守,否则崩溃是高概率事件。个人认为,流程再如何简化,对于开发而言,至少有三件事省不掉:
- 问题跟踪,不论新需求还是错误,都需要用issue tracking system管起来,这样起码能做到对于项目当前的工作量一目了然,它也是计划的基础。
- 版本控制,这个的重要性就不必再强调了,如果连这个系统都没有,那根本算不上是一支合格的开发队伍。在此之下,采用何种工作流程和分支模型,其实并无定论,采用适合自己的方式就好了。
- 持续集成,它是区别“乌合之众”和“正规军”的基本标志,这句话说得虽然武断,但大致不会错。CI系统难以实施的关键点在于缺乏自动化测试,单纯地验证编译通过,价值其实并不大。
然而,遗憾的是,当我向面试者问起有关这三件事的问题时,能清晰明白回答的人寥寥无几。或许这也跟面试者的群体有关:由于目前公司名气不大,愿意来公司面试的人员本身素质大多都不咋地。
案例:我们目前的工程管理工具集
目前,我们的开发流程基本按照SCRUM来走,开发中所有的内容都会落实到以上的三个系统中:
- 问题跟踪:Redmine
- 版本控制:Gitlab
- 只从主库编译打包。
- 团队各自提交代码到各自的开发库之后,再向主库发起merge request,由负责人review代码并合并(没错,负责人必需有开发技能)。
- 开发者严格遵循branch per feature。
- 每次发布之后,负责人会打tag。
- 持续集成:Jenkins
- 代码需要有自动化测试。
- 每次MR会触发测试运行。
- 建立了发布流水线,构建成功之后,发邮件给相关人员,人工确认部署。
对于自动化测试代码,我们并不严格遵循TDD方式,只是规定需要有,但不关心它是先于产品代码写的,还是事后写的。就现阶段而言,我不关心。并且,目前并不强调测试覆盖率,优先核心代码的自动化测试,要求发现错误之后,尽量用测试复现之后,再修改代码让测试通过。
测试并不仅限于单元测试,关键场景的压力测试和功能测试也是要求的。就测试而言,我们的工具集:
原则3:不教条
《孙子兵法》指出:“凡战者,以正合,以奇胜”,这恰恰点明了不教条的重要性。个人以为,这一原则在创业团队身上体现在几个方面:
开发岗位的设置
人力永远是创业团队的稀缺资源,如果不管三七二十一照搬大公司的细致分工,不仅造成运营成本的增加,同时也会因为增加了沟通成本而让“船小好调头”的优势丧失殆尽。
“兵贵精而不在多”,这是小公司克敌制胜的基础,与其照搬繁杂的岗位设置,不如好好找到几个具有高成长性的弟兄,以简单粗暴的方式尽快让产品上线面市,然后想办法边把船造大边修船。至于如何招兵买马,那是另一个话题了,不在本文讨论之列。
开发流程的制定
讲到开发流程,家家都有本难念的经。不论大小公司,似乎在此上面都有说不完的话。既然如此,还何必照搬呢?流程是为事情服务,同时要兼顾团队成员的能力。如果制定流程只是为了让开发显得“正规”,那这样的流程不要也罢!
就小团队来讲,流程宜简不宜繁,将关键的环节卡住,其他放手让队员去干即可。待问题发现时,再思考是否可以通过改善流程来避免和优化也不晚。通过这种方式形成的流程也更容易让人接受,深入人心,也方便老队员对于新进队员的解释。流程这种东西,总得有拥护者才能真正的实行下去,否则就只剩下一层皮,实在没有什么意思。
产品架构的设计
这一点是最容易让人迷失的地方。由于创业者的野望,总是幻想要为海量用户服务,自然那些出自巨头、自带光环的产品架构很容易会落入他们的眼帘。但遗憾的是,这种架构其实并非总是像技术营销中说的那么完美,实做起来对于开发、运维和部署环境都有不低的要求。贸然进入,很容易就陷进去,想退也退不出来。
创业初期,最重要的目的在于验证业务的合理性,找到买单人。这期间,对产品技术上的要求是能够快速迭代、快速发布,而非应对海量用户请求。只有证明业务方向正确,用户访问不断增加之后,大型分布式网站的需求才会浮现。否则,要是一开始就按大型网站的思路去做事,绝对会贻误战机!套句风水上的一段话:“人少屋大,主凶”。
案例:我们在这三方面的做法
相比起来,我们的工种设计要简单很多:Web开发、移动开发、网络开发和运维:
- 在我们这,Web开发必需自己写前端代码,尽管我们也采用前后端分离,但是并没有严格地区分前端开发工程师和后端开发工程师。也正是出于这样的原因,一开始我就会尽量寻找能够降低开发难度的工具:
- 按照同样的原则,我们的移动开发并不区分iOS和Android,而是统一采用ionic 2来搞定。采用这样的思路还有一个原因在于,我们的业务对于移动端的性能并不要多NB,普通的混合开发方式就够了。当H5无法解决时,只需写一个Native插件搞定即可。这种模式跟多年前的“VB【做UI】+VC【做控件】”开发模式没有本质区别。
- 网络开发和运维目前属于合体,因为有不少重叠的知识点,同时也因为初创期间没有那么多运维任务,在将必要的运维任务自动化之后,有大把空余时间。同时,网络开发更偏技术底层,变化的频率并没有那么高。所以这样看来,两者的结合简直是天作之合。
至于其他,如DBA,也主要由经验丰富的老同志和运维兼任,同时通过其他方式降低运维成本:如开发均遵循DBMigration,定期执行典型场景的压力测试,倒逼开发优化查询。
换句话讲,在我们这:“一专多能”是常态。
而开发流程,则基本按照SCRUM,但没有设置那么多的流程角色,基本就是几个关键实践:计划、每日立会、演示和回顾。同时结合自动化测试、Code Review和CI。
讲到产品架构,虽然未来已确定要走微服务之路,但就目前而言,其实业务层代码也就是简单而普通的单体应用,只是为了在未来拆分成服务方便,事先分好了包。
此外,在前端页面和后端服务之间引入了自研的dgate,起到基本的解耦和熔断目的,其他的则通过前置的NGINX去搞定。
只有设备接入层才真正实现了微服务的雏形,初步具备了水平扩展的能力。
原则4:重实利
如果一支创业队伍重虚名而轻实利,那失败是必然的。所谓重实利,最直接的表现就是要考虑投入产出比。看到这里,可能不少看官觉得这是一句能把耳朵磨出老茧的“废话”。可问题是,你真的会从投入产出比的方面思考吗?
在我看来,只是简单地从输入和输出角度思考并不够。一个合格的重实利创业者应该按照这样的顺序来考虑问题:
- 哪种产出对于业务发展是最关键的?
- 从投入到那个已确定的产出,有哪些关键环节?
- 为了打通这些关键环节,需要有哪些投入,并且哪些投入是必不可少的?
- 在众多可能性中寻求最佳组合?
由此看出,这并非是一个简单的求最大最小问题,而是先确定方向,再寻求优化的做事方式。否则,只是按照“做这个很快,做那个要费些时间”的思路来做事并没有什么益处。记住,将你的宝贵资源(包括人力、资金、时间等等)投入到对业务起到推动作用的事情上。有时候,捷径往往比大路要难走得多,但它能很快达到目标。
案例:我们的设备数据采集器和商城
说到硬件采集器,其实并没有什么技术含量,基本的实现都是一个简单的透传模块。但如果要满足下面几个约束条件就没有那么容易了:
- 用户透明性,即用户可以很快在现场安装调试完成
- 设备透明性,即一款硬件、一套代码可以满足市面上大多数机器
- 位置透明性,开发人员不必在现场就能协助安装
以上3点恰恰是我们的设备数据采集器的优势所在,不仅极大降低的运营成本,并且也拥有良好的用户体验。同时也是让竞争对手百思不得其解的地方!
这种设计恰恰是重实利的表现,在关键地方,不能省功。如果当初只是单纯的按投入去考虑,绝对不会有这样的设计。
最后,简单提一下我们商城上线的过程。
一般来讲,商城肯定会分前台业务和后台业务,虽然技术含量一般,但每一块的业务都不会太简单。那么,如果按照一般思路,将前后台业务都完成之后再上线,那么时间会拉的比较长。
而按照事务的一般规律,业务总是从简单到复杂。上线伊始,复杂的后台业务并不会太多,结合一定的人力和自动化工具就能支撑,比如商品上架。那么这个时候,其实将火力集中在前台业务,使之相对完善,即能很快上线,使自家囤积的商品开卖,快速转化成为现金流。
基于这样的考虑,第一版本的商城上线时,我们只实现了前台业务,后台业务通过直接与DB交互手工完成。随着业务运营的不断深入,后台业务逐渐上线,替代人工。这种方式有一个很形象的比喻:
- 当资金有限时,先摆个地摊,将仓库的货先卖起来。
- 随着货品的变现,手头有了多余的资金,地摊升级为小卖部。
- 在小卖部开卖的同时,它的身后在造一间百货大楼。
如此渐进的方式,不仅让运营和开发可以同时进行,而且也缩短了上线时间,方便快速试错和调整方向。
当然,还有看官可能会说:这样会造成一些重复的开发任务。但在我看来,这种重复是可以接受的,而且是一种健康的、螺旋上升的重复开发。相比起一开始天真地本着一劳永逸的方式去开发某个功能,这种方式更可控,而且更能让开发队伍体会到成功的快感。
并且,我还想问:你怎么能够断定你那所谓的伟光正设计就一定适应未来呢?进化和改变才是这个世界的常态吧?!
原则5:常总结
我总是对开发队伍说的一句话是:你去观察那些学习好的同学,他都有一个特点,那就是总结。的确,如果不总结,也就不会有那些公式定理,就连1到100的求和估计都要算半天。
复盘和总结是为了避免将来犯类似的错误,同时将好的经验能够发扬光大。但,如果这些不能得到固化,那效果必然会打折。所谓固化就体现在以下几处:
- 工作流程,流程必需要定期翻新,否则必然人浮于事,最终徒留形式。同时,流程和当前团队的自动化水平息息相关,最好尽可能地自动化。
- 工作代码,将错误解决之道和经验固化成为代码的最大好处就是节约时间,同时锻炼了队伍。它的作用跟数学公式其实是相似的。
同时,为了让队伍养成总结习惯,而不是机械地在每个SCRUM回顾会上才“用心”总结,必要的强制手段是需要的。比如,鼓励队员分享和写文章。
案例:DTeam团队日志诞生记
DTeam团队日志是我创建的团队日志,它的目的就两点:
- 技术营销,方便外界了解我们的队伍。我相信每个有进取心的开发都会希望进入一个有技术氛围的团队,团队日志恰恰非常擅长充当团队的技术窗口。当然,单纯仅靠技术是无法吸引人才的。关于如何招人,未来有机会再谈。
- 强制总结,通过邀稿的方式,逼着队员自我进行总结,养成自我总结的习惯。因为在审稿的同时,我会顺带指出一些思考上的问题,引导他们如何进行自我思考。
原则6:志高远
前面说了那么多原则,其基本立意就是“现实”。到了最后这一条,必须谈谈“理想”。一支没有理想的队伍走不远,一名没有理想的大哥也不配被追随。
作为团队的大哥,一定要记住:当前的选择都是权宜之计,为了应对未来的风雨,眼下就应该开始着手准备。他必须是一个不安分的人,原则1的“不折腾”是针对于团队而言,即不要折腾团队。但他必须自己折腾自己,把大部分坑自己都踩过了,再去考虑团队内部是否推广的问题。
说得通俗点:让团队做眼前的事,作为大哥,他需要做好未来的安排。不论这个事情是他亲自做,还是别人做,都必须有人做。说着说着好像有点像“预研部”了,;)
案例:我是如何为团队做技术储备的?
其实,作为互联网创业的后进,为未来做技术储备和选型其实并没有什么困难的。因为只要按着前人走过的道路走,然后结合自身的特点就好了。你会发现,大家走的路其实都差不多。
通过查阅和了解成功互联网公司的架构演进,可以很容易总结出架构发展的几个阶段,而且你会发现大家的架构也都差不多,只是在实现方式上不同而已。问题的关键在于确定合适的引入时机。它由几个条件决定:
- 首先,最重要的就是业务的发展水平。
- 其次,就是团队是否为这种演进做好了技术准备。
- 最后,确定目标之后的行动步骤。
第一点靠系统监测的各项指标可以很容易的掌握;第二点就在于提前的技术布局和相关的技术培训;至于最后一点,就是所谓的项目实做了,并不困难。
写在最后
这篇文章缘起于最近的一次回杭之旅:
- 与原杭州公司同事聚会时,提到新旧公司的差异。原话是:“原来还没有觉得咱们公司技术挺牛的,现在到了新公司,感觉差别一下体现出来了。”
- 参加了久违的EGO小组交流会,会上就某个话题展开,进行了短暂的创业公司的工程实践讨论。
其实,我想说的是:以上原则都是一支正规队伍的基本做事原则,如果连这些都做不到,那真是无话可说了。换句话讲,不是我们太强,而是对方太弱。
网友评论