前面的话
从6月到8月,feed着手timeline的优化和新需求开发。从开始的轻松从容,到后来的逐渐失控。实际上,一个仿造的“人月神话”悄悄来到了我的身边。其中有很多值得反思和总结的地方。希望趁现在处于羞耻,自责和焦虑中,思考和总结点东西,一方面希望能够总结出一些自己受用的一些规则和教训,对以后成长更有帮助。另一方面,希望能借此透过现象看本质,穿越流于表面的情绪看到问题的本质,真正的获得成长。
需求之坑
在做feed之前,我也曾经被需求弄的很头疼,但是当时自己并没有很重视,而是单纯的归因到团队里去。在华为正式工作的时候,因为在预研部门,项目流程不是很规范,直接leader是项目管理和人员管理的,需求是由另一个领导直接提的。
需求不是架构,需求不是设计也不是用户界面,需求是需要 —— 《程序员修炼之道》
在华为的时候,我们得到的并不是真正的需求,只是用户(leader)的模糊的需要。这种需要没有形成需求文档,产品设计文档,没有ui去描绘用户界面。还是初入职场的菜鸟的我那时候也不懂得《程序员修炼之道》里面的真知灼见,单纯的归因为团队的不规范,却又说不出具体怎么的不规范,归因为自己的技术水平但事实上,导致项目失败的原因,技术水平只占了不到1%。
来到shopee,leader是在微信和产品经理斗智斗勇多年的老司机,他用他的经验告诉我们,开发要站在用户的角度思考问题,要评估需求的合理性.另一方面,这边的产品经理也显得更加正规靠谱,毕竟是阿里头条挖过来的。
与用户一同工作,以像用户一样思考 —— 《程序员修炼之道》
正是这些,导致我再一次忽略了对需求的思考。也许我用leader那拾人牙慧的学习到了一点需求的经验。但是并没有形成自己的一套方法。
先抛出我作为一个开发者对需求评估的工作流总结:
不要搜集需求,要挖掘需求
《程序员修炼之道》里给了一个典型的例子:”只有员工的上级和人事部们可以查看员工的档案”是需求吗。转换一下:只有获得授权的用户才可以访问员工档案。两种陈述对于实现来说是截然不同的。
这一点通常主要是产品的工作,但是开发从产品和用户角度去思考需求产生的原因,往往更能把控实现这件事情的方式。典型的例子是对于这一次开放用户白名单给非kol的商家的需求,PM提出来之后我马上就思考现有的实现细节,没有先分析需求提出来的原因,或者说思考的不够认真,只是流于表面的认为这个只是为了紧急支持local的99促销活动。如果我再进一步的思考,我应该去思考为什么现有的系统不能做,怎么做更佳合理。最终导致自己加班加点的去做需求。
需求文档的坑
同上,这个也主要是PM的工作,但是需求文档是PM和开发的接口文档,对于开发来说,分析需求文档,建立用例图,然后通过沟通和PM澄清需求,是开发前期最重要的一个阶段。
在我们的系统中,需求文档主要有两个问题:
- 需求文档变更,我们经常抱怨需求文档变化,一方面是需求下来的时候可能比较紧急,文档确实不够详细,另一方面,这是需求文档本来的”原罪”,我们只是没有认识到这一点而已。
制作需求文档的一大危险是太过具体,好的需求文档会保持抽象,需求文档能准确反映商业需求 — 《程序员修炼之道》
在multitabs的需求中,我承认自己对需求文档不够重视,没有仔细斟酌里面的描述,缺少在写代码前和PM的交流,澄清需求,为了逃避交流自己做了太多假设。交流产生的结果也没有准确写入到PRD或者自己的需求规约汇中。这是自己给自己埋下的第一个坑。
###
进度管理
人月神话在”系统测试”一节给出了一个软件任务进度安排的经验法则:
1/3 计划
1/6 编码
1/4 构建测试和早期系统测试
1/4 系统测试,所有构件完成
在我看来,这些比例也并非一成不变的,但是更多的东西我没有足够的重视,或者没有足够的经验去思考出自己的一套需求开发进度安排和任务工作量估算的方式。经过一年多的踩坑,我终于认识到,进度管理真的不仅仅是leader的事情,也许我们只需要管理好一部分进度,但是进度管理的基本方法论是不变的。
计划
计划这一阶段应该在需求评审会的时候,明确好以下的一些东西。
- 任务
- 责任人
- 进度
- 接口定义
设计和编码的分离
首先一点我没有清晰的认识的是,计划和编码是具有清晰明确的边界的。而且计划的时间一定比编码长。在feed项目之初或者至今,我都没有很好的平衡这两点。系统时序图对于思考编码的实现,业务流程是很好的工具,可以当作设计阶段的一个很好的形式化工具,类似于vscode之于编码,系统时序图就是设计阶段的工作。
设计工作量永远大于编码,除非是一个需求很清晰,实现很清晰,代码量不足50行的需求,否则我都应该在编码之前,在草稿纸上,画出一个简单的设计。更加复杂的需求,就要借助startuml工具(puml)来完成了。
外部依赖管理
一个0.5天工作量的需求,往往具有的特点是:
- 不存在外部依赖
- 代码修改量少于50行
存在外部依赖的时候,即使条件2满足了,也不能乐观的认为工作量只有0.5天完事,《人月神话》里,对于职业的苦恼,有一点正是说的——
“苦恼来自由他人设定目标,供给资源和提供信息”
推荐团队是我见过的最恶劣的合作团队,不仅仅无限延期对接的接口,给出的接口竟然能不按照穿进去的分页参数去返回结果。这也让我认识到,外部依赖永远都是不可靠的。
不仅仅是团队,内部的依赖往往也不可靠,比如你永远不清楚,一个别人定义的delexxx方法,究竟在实现里面会不会带有副作用。
在有外部依赖的情况下,工作量都需要按照1天起估算,主要是因为,对于外部依赖,需要有充足的系统测试时间。另外,当一个需求实现的工作量时间大于两天,往往需要再细分到更小的粒度,不然很容易导致失控,或者在遇到困难的时候,没办法让别人更好的参与进来一起解决。
设计之坑
初级设计之坑
用华为的等级来看,能不能掌握避开初级设计之坑的方法,是13级和14级的区别。13级基本不需要设计,按照既定的规范来做就好,14级开始要做初级设计,接口文档,系统设计之类的。不再埋头编码,是一个准备入行的菜鸟和已入行的弱鸡的区别。
设计阶段,有两个坑:
- 不知道抓重点
- 不知道使用什么工具/流程图表达
第1点在去年的时候我也没有清晰的认识,但是今年看完《DDIA》,结合一些实践上的思考,得出一些自己的经验规律。
比如对于接口,或者系统设计,我们首先要明确好负载,负载可能是一个高并发场景下的QPS这个指标,也可能是feed关注关系的读写扩散导致的读写放大。之后要明确好性能,性能主要是响应时间等一些我们期望达到的目标。抓重点首先要简化需求模型,脑海里有一个MVP(最小可行性)模型,方便我们对症下药。
不知道使用什么工具,一方面可能是我们对于软件开发的众多UML工具没有一个系统的了解。但是在学习完《软件方法》课程之后,其实就不太应该了。我觉得,最应该熟悉的是:
用例图
系统时序图
其他的都是用的时候再去思考哪种合适就好,永远都不要做工具的奴隶,拿起锤子,看到什么都是钉子。
高级设计之坑
在华为我见过最厉害的14级的设计,也很少去很好的思考以下的一些问题:
责任是否得到了良好的定义
协作是否得到了良好的定义
耦合是否得以最小化
接口定义和各项约束是否可接受
这些都涉及一定的经验和一定的技术直觉。经验有得到需要的是3年/5年,对于善于思考的人,往往更短。
实践是最好的老师,但智者还能从其他的地方有所收获 — 《穷查理年鉴》
我们可以在自己的设计和别人的设计中不断思考反思上面的4点是如何迭代实现的。在学习开源框架中学习如何抽象对象和结构,在业务开发中,更佳灵活的根据各种需求来进行设计,把阅读开源代码学习到设计灵活应用起来,这样才能真正转化为自己的东西。
技术直觉需要源源不断的学习,保持好奇心,保持兴趣。
比如通过DDIA对数据系统的高屋建瓴般的总结,从而对常用的中间件建立一定的技术直觉。
当然,好奇心和兴趣往往因为压力打压变小,这种时候就该反思自己最近一段时间的状态了。而不是把这种状态视为理所当然。不要逃避问题,否则只能遭致更大的问题。
总结和勉励
有时候,心里总会有这样的一个声音反复问自己:”为什么要总结这些东西,再怎么总结,以自己的经验,都是做不到比书本更完美的”。我想,有了两年的工作经验之后的今年,我终于找到了原因:
不把信息当知识,不把收藏当学习,不把阅读当思考,不把存储当掌握
当我们生搬硬套教科书的知识/别人的经验,那是永远都没有真正去掌握并转化为自己的能力的。
- 比如网络5层协议没有生搬硬套OSI7层网络模型
- 比如东施效颦
编码工作是理性的,枯燥和创造性并存,让其成为近百年来改变世界最明显的工作的原因,正是千百年来无数数学家思考的结晶。很多东西和生活也是相通的,比如生活中怎么管理好大大小小的事情,和项目管理也没啥区别。
愿我能继续拥有感性的精神世界,理性的生活方式。继续矫情下去,但是也能理性的去掌控好自己的生活。