软件工程基本常识

那些《人月神话》和《快速软件开发》中教会我们的事情,我们永远不会记住,也不会吸取教训。

现实情况

认可现实是对软件工程的前辈最好的尊敬

老板认为多一个人就要多一份活,主管认为每一个人都不能闲着,下属在划水混日子,推进产品的人却在得罪人

无效沟通导致团队低效产出

高效的团队与低效的团队之间,成本可以相差10倍,效率可以相差100倍

软件团队的负责人往往不知道问题存在于哪里,团队成员很难站在团队负责人的视角提出问题

老板选择信得过的人去负责团队,团队负责人却不知道选择能力最强的下属去解决问题

有错都是程序员的错,程序员还不被允许脱离产品经理,产品经理却不懂业务需求

这个问题很简单,具体实现我不管,明天上线

这样实现最简单,你的问题我不管,明天上线

首先实现要简单,我的问题你别管,明天上线

上线怎么会出错?程序员不测一测?光靠测试怎么行?

另一种情况会是这样:

研发类的项目在弄明白需求之前就要求先开始,如果架构设计出现问题,没有人愿意承认架构有问题

维护类的项目在弄明白业务之前就要求先开始,如果业务需求出现问题,没有人愿意接受业务的重要性

所有的大版本最后都会切分成小版本,切分的原因不是软件开发团队水平差,更多的原因是不知道业务需求

团队较弱业务分析能力最终必然导致开发团队使用敏捷模式开发半成品软件帮助业务团队梳理需求

敏捷模式下的半成品软件必然被业务团队视为最终软件再次鄙视开发团队的敏捷模式

不使用敏捷模式又导致需求不明确的前提下一直无法进入开发,产品设想的讨论无法落地

最后不得不换一家外包公司,然后发现产品开发过程更烂

这时才接受考虑大版本迭代,小版本敏捷,然后整个团队已经浪费超过一年

常规的软件流程

软件需求调研无法获取真实需求

产品设计部门专注设计,脱离业务

开发部门闷头做产品的设计,导致产品脱离业务需求

需求分析人员误以为自己获取的需求是真实的产品需求,进而再次修改产品设计

以上情况是80%以上的软件团队面临的困境

无论是否处于这种困境状态,软件团队必然会经历如下的软件过程:

产品人员调研业务逻辑,形成业务需求

产品人员通过业务需求,完成产品设计,其中可能包括原型设计,视觉设计,交互设计,产品说明方案、文案

技术开发团队参与产品设计过程,或者产品开发团队直接按照产品设计稿进行开发

技术开发团队面临各种技术问题或者产品问题,产品发布延期

测试团队介入,进行常规测试

运维人员介入,完成部署与实施

产品人员进行功能验证,推广给用户或者业务人员(运营人员)

产品确定发布

能顺畅走完这个流程的团队,并且没有隐藏失败可能的团队,是优秀的软件团队

敏捷不能解决人的问题

常规的软件工程不能解决问题的时候,会搬出敏捷模式来救场

敏捷模式是业务不清楚时候的底线方案

敏捷模式有大量的无法解决的问题,不能银弹

敏捷模式不能解决团队成员水平差的问题

敏捷模式不能解决业务不明确的问题

敏捷模式不能为业务人员带来直接可用的产品

敏捷模式不适合低容错的项目

敏捷模式不适合事务模式下的业务系统

敏捷模式不能解决产品设计的缺陷

敏捷模式不能解决代码质量的问题

敏捷模式不能解决业务、产品、老板的不协作,这里的本质还是因为敏捷模式的目标是尽早产出半成品帮助大家有可用的软件,但大家更希望拿到手的是完美的成品

最后总结:敏捷模式不是银弹,能用好的团队不多,不过无论是否使用敏捷模式,迭代开发是值得推广的模型

有效人才

如果传统软件模型不靠谱,敏捷模式不靠谱,那么可以使用有效人才战略

有效人才战略中,需要组建手术刀团队

一台手术需要多人协作,核心是主任医师,主治医师也只能打下手

我亲眼见过一个程序员带着两个助手用PHP语言在3个月内完成了一个产品,比竞争对手的十二个人团队完成的竞品还要优秀

有效人才又称为手术刀团队,也称为主程团队

最高效的程序员效率可能是普通程序员的50-100倍

上一条数据的计算不单指开发速度,更包括维护以及技术方向、产品方向的综合成本

主程模式很贵,非常贵,可是值得

在复杂项目中,我还不能做一个合格的主程,我希望能够做到中等复杂的项目中,可以担任手术刀团队的主程

不要相信业务人员

业务人员一定认为自己知道自己需要什么

业务人员知道自己的业务需求,不一定知道自己的产品需求

产品存在的意义有多种,并不一定是满足业务人员的全部需求

产品存在的意义包括对业务的边缘限制,也包括对业务能力的放大

优秀的产品可以把业务能力放大10倍,更优秀的产品可以把业务能力放大100倍

这种对业务能力的极限放大,往往会导致10%-20%的业务需求不被满足,可是业务能力的放大过程需要时间

因此有可能在产生效果之前,产品已经被业务人员否定了

因此,有三个重要原则

原则一:不要相信业务人员提出的需求,因为他们是业务主导方,因幸存者偏差,他们提出的需求往往导致产品失去了放大的能力

原则二:满足80%的客户,得罪20%的业务,获取200%的规模效应,这就是成功的产品

原则三:产品成功之前,有可能被裁掉,做好心理准备即可

以此,感谢软件业前辈的忠告:把自己能力范围内的事做到最好,然后等着被开除。如果没有被开除,那我就是做了正确的事情——为所有人。如果被开除了,那选错了老板。总之,两方面,我都是赢。

运营、产品、研发

本来没有产品,后来分工越来越明确,就有了产品

运营一直都有,有的时候叫销售,有的时候叫市场,有的时候叫客服,有的时候叫COO

也有的时候,叫CEO

产品经理的范畴很广,所以谁都能自称产品经理,可是好的产品经理几乎见不到

所以运营与开发之间的距离可近可远

产品强,运营与开发的距离远,分工明确

产品弱,运营与开发的距离近,分工不明确

大多数团队分不清这些职责

最差情况是取消产品经理,由好的程序员接手产品管理

或者产品经理偏运营,开发偏一部分产品,这种情况下需要开发团队有分工,有人负责沟通和设计,有人专注技术

我们讽刺自以为是的产品经理,常常说:这个产品经理已经优秀到极致,与乔布斯的层次之间只差一个逝世

没有恶意,可是产品经理对自身位置的定义,决定于运营与开发的配合度

从不期待有优秀的产品经理,只期待产品经理能够把业务梳理好

配合产品经理一起分析并梳理业务是好的开发人员的责任,但不是义务

产品经理梳理多条业务线的业务模型是天职

如果产品经理好说话也有上进心,那么好的程序员可以大胆提出自己的产品设计理念

其实这些理念大多也没有人在意,因为大家都会说程序员不懂产品,不懂用户,不懂业务

可是真正优秀的程序员能够帮助产品经理完成业务梳理以及用户增长,大家把这个叫做:黑客增长

所以,弄清楚产品经理甚至产品团队的自身定位,可以方便开发团队给自身的工作职责定出边界。

最终还是要满足业务需要,但不是满足所有的运营人员。

除非老板特别优秀,否则不要对老板负责,要对软件产品负责,并说服老板为什么要这么做。

大多数的产品都是过度设计

在产品上线之前,没有人知道用户需要什么

产品上线之后,依然没有人知道用户需要什么

用户要的功能很简单,所有人都会把用户想复杂了

所以可以假设任何功能都是一个文章,一共六条属性:id,title,summary,content,datetime,jsonb

在这个基础上,先上线再说

这样的设计太简陋,这不叫简单

程序员不懂产品设计,可是好的程序设计方案可以训练程序员分清简单和简陋

用户需要的是简单的产品,不是过度设计的产品,也不是简陋的产品

过度设计的产品是浪费公司的钱和机会,很多团队却把过度设计当成KPI

尝试说服团队不要过度设计,如果实在说服不了,那么,领导说怎么干就怎么干,然后等着被开除

测试人员测不出问题

程序员写的程序有Bug

测试环境会测试出一些Bug

但是测试人员测不出问题

最容易测出来的Bug是页面打不开,或者不能正确显示数据,程序员能自己解决80%的此类问题

剩余的20%的问题,测试人员只能测出5%左右

如果程序员测不出80%的问题,那是程序员的责任,如果测试人员测不出5%的问题,是测试人员的责任

其他问题一定会在生产环境下出问题,因为没有办法让生产环境与测试环境一至

所以要使用一套方便线上解决问题的方案,包括但不限于日志、数据库镜像、代码库分支、快速部署与回滚

所以测不出问题,不怪测试人员

其实也不是,还是测试人员水平不够,可是,哪个团队愿意花钱请优秀的测试人员?

我知道一家,开发操作系统的微软。

没了

Bug是修不完的

为什么一直在修Bug?

因为大家都分不清哪些是Bug。

开发的多功能文本编辑器,需要我来开发一个远程图片自动下载的功能,我处理了所有可能的格式

包括但不限于文件格式,img标签,data-src懒加载,cdn限流,refer限制

可是报了一个Bug,说我处理的功能没有实现图片压缩

我是严格按照需求文档在编写功能,需求文档没有写需要处理refer限制,我也做了

最终产品依然认为是我的责任,因为我没有把图片压缩

心态放平,Bug是修不完的

分不清一个问题是不是Bug,是常态,能分清一个问题是需求还是Bug的团队,是有前途的

本地沟通与远程工作

产品经理喜欢站在程序员身边讲需求

那是因为他们没有想清楚自己的业务闭环,没有完成产品设计

同时缺乏产品表达能力

一个产品经理设计的产品,程序员听不懂他的产品要做什么

用户,会懂吗?

大家在一个办公室里工作,本质上是为了更好地交流与协作

不是为了满足产品经理的需要而在一个办公室

这是另一个话题:为什么这么多的团队中,很多人需要迁就其中的一两个人呢,这个不在现在讨论

有的团队适合远程工作,有的团队适合本地化工作

产品经理方便随时提需求,不是决定远程还是本地的重点

管理工具能够提高效率

Jira是一个好用的工具,无论是哪一种类型的项目,Jira都很好。

Mantis也是一个好用的工具,很好用,能够提高效率。

不推荐花哨的管理工具,因为越贴心的工具越有限制。

效率的本质是:提出问题,追踪问题,反馈问题,总结问题。

Jira和Mantis都需要配一个wiki。

好像应该试试Trac和Redmine。

编程工具不能够在长效项目中提高效率

我写过PHP,能写,不太熟,写简单的WEB项目挺快

可是我用mojolicious的效率远远高于PHP

他们不能以PHP开发WEB的效率更高作为标准用在我的经验中,因为同样是三个月的周期,用mojolicious的速度不亚于PHP

我写过Java,从完全不懂Spring到上手编写类似于SpringBoot的原型产品,不超过2个月,那会还没有SpringBoot,我们自己把tomcat集成到Maven中

有人问我为什么非要把tomcat集成到Maven中,我说单一可以启动的服务远好于中间件部署模型

后来就有了SpringBoot,比我做得好,不过思路差不多

如果不是做三个月的PHP,也不是写三个月的mojolicious

是写三年的产品,无论是PHP,还是 mojolicious 还是SpringBoot,早晚面临着:

自己实现OAuth,自己实现JWT,自己实现Cache,自己实现Queue,自己实现Session复制或者Token分发,自己实现RPC,自己实现Search

有的语言轮子多一些,有的语言轮子少一些,学会轮子或者判断轮子能不能用,或者正确使用各种轮子

最后花的时间差不多

开发速度上C++可能会慢一点,不过C++14或者C++17也不会太慢,前提是熟悉C++11

所以项目当前是什么技术,如果还能招到人,或者能培养,就继续用下去,任何以为换一种技术就能够提高开发效率的思维都太极端

加点私货:用Perl插好的,做大以后用Java或者C++重写一部分组件,很方便

产品思维决定产品形态

产品思维有很多种

需要提前了解团队专注的产品,是哪一种思维

本质上有两种思维

第一种是数据约束思维,又称为信息系统思维,或者叫数据事务思维

另一种是数据发散思维,又称为信息传播思维,或者叫互联网的思维

如果是第一种,那么数据库约束与事务要做成核心,消息系统要稳健

如果是第二种,那么用空间换时间,不准确的数据只要不涉及钱,就可以接受

本质上,第一种要存钱的时候要使用BigDecimal,第二种可以转化成分进行存储

前者少用敏捷,后者多用敏捷,前者多找领导签字确认,后者大胆开发,流量为王

不管是前者,还是后者,多用PostgreSQL,少用MySQL/MongoDB,真的

常见问题

软件开发中的一切问题,都是常见问题

所有常见问题的解决方案都要根据业务和人的情况来抉择

我的抉择能力较差,我选择做好我应该做的,其他方面靠磨合,磨合不好就没办法了

但是一个顶配的程序员放在一个低配的团队中,我却知道如何调配

因为顶配的程序员去做那些让其他人效率变高的事情,效果好于用这个程序员去做普通的开发

我还不是顶配,我缺乏更高的层次与视野,我努力。