项目实战(2): Beta案例

时间:2019-08-23
本文章向大家介绍项目实战(2): Beta案例,主要包括项目实战(2): Beta案例使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

上一篇:项目实战(1): Alpha案例

有很长一段时间没有写博客了,主要时间都在忙着项目的事情。现在进入尾声了,做一个小记录。

0x01 项目立项

这是一个合作性的项目。双方的合作基础是双方各自的需求。我是在乙方这边。

甲方的痛点

  1. 现有系统可以运行,但是缺乏系统设计,在一些关键部分有系统性的缺失,导致系统只能做客户端的微小功能升级,无法满足后续的运营需求。
  2. 开发人员青黄不接,服务端开发和客户端开发不在一个地方,出现问题的时候无法明确责任关系。

乙方的意愿

  1. 跟甲方的上头有之前的合作关系,所以有做这个项目的合作基础。
  2. 可以让甲方的项目使用我们的Severless框架,case by case地推动公司现有PaaS开发服务。
  3. 可以尝试建立开发人员脱管模式的合作。

在这样一个简单的合作基础上,项目就开始了。

0x02 前期需求分析

最开始的时候是比较模糊的。我们去甲方公司谈了几次项目需求。软件系统是一个多端的软件,包括下面这些:

  • PC客户端软件(顺便吐槽下,这年头已经没有什么新的ToC的PC客户端软件了,在这个例子里面,这是一个全屏触摸屏操作的软件,放在商场里给人扫码支付用的软件。这年头360已经流氓到PC客户端软件采用白名单机制了,但是普通PC软件很难过360的白名单机制,事实上宣判PC端客户端软件的死刑,不过走Windows Store的机制不知道情况怎样)。
  • 多设备软件的远程控制端。软件在触摸屏上可以点击设置,做一些软件的操作,这些操作有些是运维行为。再加上软件本身需要有一些守护行为,例如某些依赖的组件或环境崩溃时自动拉起等。 需求分析的时候把这块独立出来,为多个设备的客户端做一个网页远程操作端。相对应的,客户端本身被分离成两个部分,纯客户端部分和本机服务部分。
  • 手机微信扫码支付的部分。这个部分,旧的系统只建立起了微信扫码后获得的OpenID来做用户唯一标示,账户这部分几乎是空白,也导致了旧系统很难做用户的功能升级。
  • 后台系统(内容管理)。前一阵子有一句金句:“后台系统就是数据库的前端。”这个部分基本上要多复杂有多复杂,什么都可以往里面塞。

一开始的需求分析部分,现在检讨,在后台系统有太多不确定,一开始重点都放在了对客户端的需求分析部分,到后面一直做下去,后台部分对方加了太多的功能。由于项目的合作基础背书,一开始并没有对这部分做严格的功能需求边界界定,后面加入了太多的不在计划内的功能。开发时间的估计上,也被这部分严重增加了。这里我只能吐槽我老板做估计太不靠谱,该谈的边界不谈清楚。我觉的和任何生意一样,无论是多么熟的人,只要是合作,边界就应该是要界定清楚的。否则你会入不敷出。

无论怎样,我就这样被上车了,本次项目做乙方的项目经理,主要负责项目的整个开发构架、项目开发周期的推进,以及包括帮助对方招聘合适的前端开发人员,并让他们在项目中实战。

0x03 项目构架和人员安排

整个项目的构架大致是这样的,不是很复杂的一个构架:

这个场景很适合用巴克云的Serverless场景,主要便利如下:

  1. 多个客户端只要关注逻辑开发,与后端的交互全通过bucky的核心库发起对后端的rpc或者触发事件。
  2. 后端部分可以自由的分模块写,模块与模块之间也能方便的互相调用,然后用bucky提供的工具链一键编译部署即可。

其中第2部分大大简化了后端的开发难度,项目开发中帮助甲方招聘的前端开发人员,一周内很自然的上手,经过一段时间磨合后前后端都能参与开发,到后面基本上就是一个模块的前后端的分配给一个人即可。而在此之前,两位前端在以前的开发环境下只能做纯前端开发。

不是说纯前端开发不好,有时候是非常必要的,例如PC客户端部分由于涉及复杂的多进程管理和第3方软件的控制逻辑,就需要PC客户端开发专注在那部分逻辑。而涉及到和后端交互的部分,就需要有经验的开发人员(当然是我,泪崩)封装好一个底层组件,让上层只要做控制和事件处理即可。

人员安排方面,一开始的时候比较简单就分了下去,但是中间还是遇到了一些问题:

  1. 客户端开发1个,事实上后面证明这个部分过分乐观了,客户端部分包含复杂的控制逻辑和错误处理。里面需要有良好的状态机封装,但是负责客户开发的程序员在交互开发方面还比较优秀,但是对状态机的封装还经验不是太多。另一个方面是Windows开发部分,进程的调度部分的经验不足。但是我们及时通过焦点问题诊断,一方面及时把这部分分离出来,作为独立的组件或进程,交由更有经验的开发人员封装好;另一方面,在代码里面做好分层,底层状态机部分与上层隔离,同时在开发中对上层的状态机做code-review,逐步把不对的部分做对,客户端开发人员也逐渐理解到了这些部分,后面就比较顺利。状态机这部分后面会单独说,总的来说,开发人员也必须在实战中才能获得对这部分的理解和进步。
  2. 本机服务开发1个。这部分相对比较独立,负责客户端的各种进程和环境的守护,这部分就交给了资深的工程师负责。基本上就是要把状态做对,并正确的做进程守护,以及写各种相对复杂的windows开发,提供各种难搞的工具封装。这里面涉及到的一个问题是,要做好决定哪些是不能做的,毕竟做守护进程,很容易不该守护的时候守护,所以要做正确的事,不要做不该做的事。
  3. 店铺管理,这部分事实上也是本机服务的延伸,所以也交给本机服务的开发人员一并负责。
  4. 后端开发,这部分涉及到后端数据库的设计部分,以及各种后端模块的分拆和接口设计。大部分时候是我负责的。有些部分直接交给对应端的开发一条龙开发。其中账户部分和微信支付部分,交给我们最资深工程师开发,这部分基本上没什么大问题,主要是保证稳定、可靠。
  5. 内容管理系统,这部分一开始是我们的一个前端开发,中间一前一后帮助甲方公司招聘到了两位前端来参与开发。一开始我们的前端就主要负责这块,可是泪崩的是开发了一个时间节点后,我们的前端同学因为家庭的原因选择了去日本闯荡了,又变成我直接带两位前端开发了。
  6. 手机支付端,这部分中间人员是不足的,我直接上手撸了一个简洁的纯H5单页面组件渲染和调度组件,然后用在开发中,效果还不错。我个人的体会,做前端开发,你还是需要去理解编程本身可以做什么,而不是只会用框架,至少你应该有机会自己写过一次简单的渲染和调度逻辑,这样你再去看框架的时候是很自然的,原理才是重点。其他部分,无论是原声H5的部分还是其他UI框架部分的,都是查手册熟悉的过程,那些不是最重要的点。另外一个地方就是你需要去理解交互背后的数据模型,理解数据模型才能理解这些交互的目的。

0x04 三个阶段的开发

项目实际开发,每周2都会和甲方的产品经理和项目经理碰头周会对进度。第1阶段实际上连续好几周我们只能处在一边对整体需求,一边对几个关键部分的开发需求讨论中。

这个阶段不确定性是非常大的,客户端只给出了一个很粗糙的原型设计,事实证明一开始粗糙的原型设计包含着对方也没有明确界定的功能单元,这些到最后才明确的功能单元往往会导致状态的组合爆炸,最后要多花很多时间才能把它做对。

另一方面是,对方对后台的需求真的是无止境的,资源配置和管理的需求、运维的需求、数据分析的需求、权限的需求、审核的需求、甚至还想加OA的需求。然后这些需求之间的依赖关系又理解的很差劲,单独这一个系统都是可以独立列一个项目的。要不是老板说这个项目的特殊性,我早就不干了。这导致了我后面一直带着某种不爽的情绪对接下去,再来一次绝对不是这样就谈了需求。

对于如何在一开始把不确定性排除,我后面的看法是,一定要一开始有完整的原型设计图。这个项目对方是挤牙膏式的,每周产品经理给一部分稳定和原形设计,而且非常粗糙的原型设计。说实话,也难怪我们说大部分产品经理都是不靠谱的,有时候他们对于一个模块下去,状态的组合爆炸是没有丝毫理解的,只能说为0。所以说画原型设计,还是请认真点画,逻辑链条要完整,一开始就展示完整的功能逻辑是重要的,一边造飞机,一边做飞机设计图的事就是不靠谱,而且很危险。

第一阶段,我们重点在账号系统、微信支付部分、以及各个端的初步框架搭建和模块接口的开发。这个阶段只关注核心能力,每个部分只要有能demo性质的核心能力展示即可。这个阶段没有用任何项目管理软件,一直到一个时间节点,我们把每个部分的核心能力建立起来,还是比较准时的做了demo演示。

但是!由于demo演示比较成功,对方领导开始好大喜功,设定了下一个时间点的开发目标就不靠谱起来。我的失误是,没能在开会的当时及时识别出来这个不靠谱。这里的坑是,我理解的目标和他们领导希望的目标实际上不是一个目标,我们在demo阶段只关注的是每个功能的核心能力。就是一个项目的mvp的部分。也就是下图的阴影部分:

当领导看到了阴影的部分,他们希望同样的时间,你把非阴影的部分都补全,这种坑的印象太深刻了,任何时候你心理都要有这个图,否则你会被坑死的(求我的心里阴影面积。。。)

我在做的时候感觉不对劲,快结束两周的时候,我觉的这必须做风险控制了,于是我向两分的领导提出了开项目风险评估会议,对功能集做边界控制。实际上整个过程,每次周会我都在做功能的拒绝工作,在随时都会冒出不确定需求的情况下,我觉的当时脑子里一直在回应这句话:“在一个sprint周期内,拒绝不在周期内的任务”,好在我们有软件工程的原理做基础,你就不会怀疑自己做的是否不对。经过评估会议后,终于压住了几个明显在周期内风险比较大的模块。

这个时间点,我自己的生活也比较动荡,所以也没有去用项目管理软件,另外由于开发人员有我们的也有他们的,内部的项目管理软件也不是很合适。所以我就临时自己用Microsoft TODO软件做简单的功能点列表,每完成一个就标记一个,有时候这其实也很有效,你就是要看着TODO LIST一个一个地被消灭,直到完成。

即使是这样,我们到了时间节点的时候,提交的版本肯定是各种问题。其中最大的问题来自于客户端,就是我前面提到的客户端的三类问题没有很好的被解决:

  1. 子进程的控制逻辑。
  2. 第3方程序的控制逻辑和错误处理。
  3. 一个关键功能的设计是有问题的,变成一个阻塞问题。

这里面其实有两种问题:

  1. 测试。时间节点只够我们完成功能的“开发”。但是实际上开发中你是没办法绕过“测试”环节,所以这两周实际上就变成了测试时间。这部分我们老板在时间估计部分又完全没有考虑这部分时间。下次谁估计时间的时候,你就一定要问他:“你留了多少测试时间在里面?”如果没有,他一定是个认为飞机是焊接完直接飞上天然后坠地的那种人,珍惜生命,原理不靠谱。
  2. 集成。在一个多端的系统中,开发的时候,每个端单独开发。但是在一个时间点,你需要把多个端集成在一起测试。例如:我需要让后端和内容管理系统做集成,经过测试,大量BUG爆发;我需要让后端系统和本机服务做集成,经过测试,大量BUG爆发;我需要让后端系统和店铺管理系统做集成,经过测试,大量BUG爆发;我需要让多端和客户端做集成,经过测试,大量BUG爆发。这就是典型的小强地狱阶段。集成不只是一个多端联调的过程,更重要的是,集成是有侧重的,当面向某个子模块集成的时候,测试和开发人员资源都要往当前被集成的那个端跑。我就发现我要去跟每个要被集成的端做大量的分析和诊断,这让我对整个系统非常熟悉,我对整体的理解和每个部分核心问题的理解比那些模块自己的开发者还多。我们说持续集成,另一个含义应该就是在多个周期中持续对每个模块做集成。

所以第2个阶段,就重点是相对完整的功能开发。以及至少要经历一个小强地狱阶段,测试一开始,我就马上去teambision上建了个账号,利用它可以在10人以下免费的策略,把我们刚好10个人所有的人都拉进去,用teambision的缺陷管理来组织BUG的提交和修复。这个过程就比较高效,通过这次使用,我也体会到了看板模式的优缺点。

简单说,它可以做基本的分类:

  1. 未处理的
  2. 解决中
  3. 已解决
  4. 重复打开
  5. 已拒绝
  6. 已关闭

但是我们实际的BUG修复,会有这种需求:

  • 未处理的,要被分类,所以我用它新建看板列表的方式新建了每个端的列表,这样就可以及时把未处理的分类到对应的列表里,相关的开发人员也可以只看自己的那列即可:
    • 内容管理系统
    • 店铺和客户端
    • 手机支付
  • 已解决的,是不能直接标记为已解决的,因为很多时候开发人员修复了BUG,但是软件你还没有部署,或者还没有大包,所以我就新建了分类:
    • 某一天修复的:例如“2019-07-24已解决“。这样等软件新打包或发布后,只要告诉测试人员,这个版本可以回归这个列表下的即可,测试回归后再标记为已关闭。
    • 标记为“已解决待发布“,这样不会出现开发者说解决了呀,测试说没有的情况。
  • 这个缺陷管理软件可以自动生成一些燃尽图,但是它不能自动地每周生成对应的燃尽图,我觉的这里是可以做的更自动化一些的。
  • 我不知道为什么看版类型的issue管理,都不给每个条目一个编号,实际上编号是重要的,我们就可以在开发和测试之间,甚至提交日志里说是哪个编号的issue就好了。
  • 看版类issue管理,对自动归类同类型或重复BUG的能力很差。不同的测试人员常常会提重复的BUG。开发人员表示很愤怒。

第2阶段的BUG是不可能一下清空的,差不多每个部分是个位数的时候,我们就进入下一个阶段的开发了。也就是所谓的Beta阶段。这个阶段,我就要求规范化,必须先把所有要做的功能具体的列出来并发Email。然后我们这边评估后做裁剪再顾及开发时间和人员安排,再回Email确认。

总的来说,这个阶段是在我的预期和控制内。但是不知道甲方是怎么回事,中间临时又搞出一个中间时间节点。而且那产品经理还时不时来问进度,我是很火大的,因为那些进度在teambition上都列着,只是因为他们领导总是问他们进度,他们就频繁来骚扰。人们经常认为事情是不需要过程的,能一下子就搞定的,这是不现实的,软件开发是要遵循规律的。经典的说法又好、又快、又便宜,是不可能的。如果是,那一定是有人压榨我们,不是你的老板就是你的客户。

这个阶段比较有意思的是,对于那些要做的功能,慢慢梳理出了合适的顺序。例如你要做退款、就要有审核、要有审核、就要先有权限控制。所以我会给后台开发做合适的开发顺序分解。

还有就是,那些初级开发人员可能会觉的审批是一个有点麻烦的任务,我会给他们分解下说,审批实际上还真是一个CRUD的过:

  1. 提交审批申请:Create
  2. 看到审批状态:Read
  3. 审批:Update
  4. 拒绝审批:Delete(Soft)

还一个例子是,活动部分,有优惠券,有广告,看上去比较复杂。我会给他们分解下说:

  1. 广告的配置是独立的,就是CRUD。
  2. 优惠券的配置也是独立的,也就是CRUD。
  3. 活动本身也是一个配置。只是一个活动可以去绑定一个优惠券,也会去绑定一个广告,给广告追加图片等。
  4. 通过这样的分解,每个部分都是充分简单的。

再一个例子是,数据库的设计上,不断讲解1:N,M:N的关系,让开发人员理解清楚数据模型的设计。

类似这样的过程,我觉的我对问题分解的能力获得了一次实战中的进步。以前我也觉的任务分解应该用WBS,但是实际上就是你必须去给初级人员讲清楚任务如何理解、如何分解,使得他们对任务不产生恐惧感的过程中,才算是完成对WBS的真正理解和运用。这个过程本身也是一个把不确定性排斥,增加确定性的过程。

最后说下我对状态机的理解。我们的后端开发,大部分时候每个PRC都看做是一个独立的调用过程,RPC和RPC之间是无状态的,所有的状态都落地到数据库去。实际上这里隐含的状态机是,只有对应模块的创建和更新接口才能更改状态,创建和更新模块里的where条件,就是对应状态机的状态能否转换的条件。而其他模块只能读取状态,这就保证了状态机的安全。

而纯客户端代码里的状态机,状态是在内存里的,也是要有严格的状态机逻辑。这个地方一般就要做到:

  1. 有明确的状态机枚举,例如:init、start、pause、…
  2. 状态一定只能在内部的唯一入口改变,例如 enterState(state)方法。并且这个方法内部要对previousState做判断,保证状态转移的正确限制。这个地方和数据库的where条件一样的作用,你必须限制严格的条件,满足条件的才进入状态并触发stateChanged事件。
  3. 只有进入状态成功,才能修改对应的数据。

这里只是大概描述下,我觉的一个稍微有点经验的开发者,还是应该要有对状态机的正确认识才对。程序员大概都知道“封装”的概念,但是在开发中常常写出:“在没有状态保护的情况下,在外部直接修改内部的数据“。如果你有,说明你对编程的理解确实需要提高。

当然,中间我还基于数据库做了一个多机器的扫码支付机器锁的功能。以及一个多机器状态同步的功能。者两个部分以后再单独分析了,只是实现了功能是不够的,还是要找时间从理论上分析下。

第3阶段,当然开发完成,进入一波小强地狱,然后收尾,循序渐进。做这样一个项目,没有什么惊喜,只是过程中自己体会到了一些道理,有时也会想起我在学校的编程启蒙老师以前跟我讲过大部分时候跟人的工作都是argue的过程。虽然我跟他在世界观上分道扬镳了,但是做项目累的时候,还是很怀念过去一起做项目的美好时光的。

--end--

原文地址:https://www.cnblogs.com/math/p/developcase-beta.html