- 前端架构:从入门到微前端
- 黄峰达
- 4791字
- 2020-08-27 20:42:11
2.3 业务回补期:应对第一次Deadline
当团队成员能正常地开发业务逻辑时,我们的关注点就变成了:应对第一次Deadline。在这个阶段里,业务开发虽然已经进入正轨,但是可能存在一定的进度落后。于是在优先级上变成了业务第一、技术第二。
这是一个价值证明的阶段,也是调配落后的进度与先进生产力的时期。毕竟欠下的债(业务)总是要还的。如果在上一个阶段中,我们花费了大量的时间在概念证明上,那么必须在这个阶段偿还这些时间。
在项目开发的过程中,人员能力不足也是大部分项目都会遇到的问题。就好像带兵打仗,老兵并不会一直待着,总有走的时候。而随着团队的规模不断扩大,会不断添加新的成员。若是这些新成员的能力不提升,或者提升比较慢,就会影响项目的进度。
此外,由于内部技术的问题已经解决了,内部的业务已经步入正轨,我们开始关注于第三方系统集成,并着手准备应用的测试和第一次上线。
2.3.1 追补业务
当技术不再是问题时,关注点便在业务上。虽然技术是业务价值的实现方式,但是业务才是赚钱的直接证明。如果业务无法存活下去,那么技术就无法证明其价值。
如果因为先前的概念验证导致一定的进度落后,那么在适当的时候,我们还会临时性地后置部分的技术需求,以用于按时完成业务。比如在必要的时候,单元测试、UI测试都可以适当地减少,直到业务平衡之后,再回来填补测试。每当这个时候,总会有人为此感到困惑和不理解。
先进的架构,并不一定会为业务带来价值;先进的技术,也并不一定会为业务带来价值。这就是为什么每当我们采用新的架构和技术时,总需要通过一系列的会议来讨论新的架构是否能够带来更多的价值。新的架构和技术带来的往往是一些架构上的可能性,它节省的往往是开发时间。而实施这些新的架构,也会花费一定的开发时间,因此需要适当地计算收益,以实现业务的最大价值。如此一来,利益相关者才会考虑架构的价值。在大多数时候,业务人员考虑的是业务价值,进度是他们考虑的第一因素。
2.3.2 测试:实践测试策略
在编写业务代码的过程中,还要不断面临测试上的压力。
在敏捷项目里,测试人员真正开始测试,是在项目进行一段时间后才开始的。一方面,前后端之间的联调可能没有完全准备好,无法进行完整的测试。另一方面,可测试的业务内容相对比较少,部分功能可能无法完整地串联起来。随后,便一直在项目中进行日常的功能测试。在上线前,才会进行一次相关的、完整的回归测试。
对于瀑布型项目而言,一个项目的测试和其他项目的测试并没有太大区别。只是在新的项目中,往往也需要大量地准备、熟悉项目、编写测试案例等,才能进入测试的流程。因此,测试人员往往在上线前的几周里才开始进行大规模的测试。
日常的测试,除了带来更稳定的功能,还给开发人员带来bug,这些bug会进一步地影响项目的进度。随着上线时间的逼近,bug数量在不断增加,甚至可能会出现一些混乱的场面——测试人员在不断地提bug,而开发人员需要不断地完善新业务,导致出现一些矛盾。
对于一个前后端分离的项目,在平时的开发里已经进行了大量的联调,基本可以应对上线。只是我们在设计架构时考虑的一些情况,可能会在这个阶段里出现;一些尚未考虑的情况,可能也会在这个阶段里出现。诸如:
◎ 没有进行集成第三方测试,无法验证业务的完整性。
◎ 没有准备好一个稳定的测试环境,以提供给测试人员进行测试。
◎ 没有接近真实的数据,以验证一些极端条件是否会出错。
……
每出现一个导致测试不完整的情况,都相当于一个风险问题。
此外,在这个时期和上个时期里,开发人员编写的自动化测试(单元测试、UI测试等)的覆盖率比较低——大量的时间被花费在相关业务功能的实现上。尽管如此,我们还需要尝试在这个时期里,定下一个覆盖率的基值,比如30%,先从0开始,然后在下一个阶段里进入更高的数值——就当前而言,它不能变得更差了。这样在后期,我们才有机会进一步提升代码的质量。
这一系列的混乱会随着项目的进行被不断地改进。
2.3.3 上线准备
在追补业务的过程中,我们在另外一方面着手准备了应用的上线事宜。当第三方依赖已经准备好时,便可以着手准备与上线相关的事宜。小公司要购买相应的服务器,大公司要申请相应的资源、审批流程,等等。
如果项目依赖于第三方服务和平台,并且他们的上线周期与我们的上线时间接近。那么,这个时候与他们联合进行调试就是一种挑战。特别是上线日期临近时,如果遇上Bug,那么就需要反反复复地修改和测试。
与此同时,需要根据部署架构练习相关的技术实践。若是计划使用服务端渲染,那么我们需要准备好与Node.js相关的线上调试环境,并让团队拥有基本的调错(debug)能力。若是计划使用Docker,那么也需要不断尝试练习与DevOps相关的技能——哪怕是公司内部拥有相关的DevOps,开发人员也需要拥有基本的能力,才能应对线上的问题。
总之,我们需要在上线前准备好所有相关的内容。
2.3.4 第一次部署:验证部署架构
无论怎样,第一次部署都会比较痛苦。哪怕在我们有了其他项目经验之后,一旦一段时间内没有经历过新应用的部署,就有可能出现问题——通常是一些配置问题,比如某个软件升级,导致之前的配置出错。哪怕使用Docker这样的工具,也可能出现一些意想不到的情况。应对这些情况的最好方式是,如果能提前尝试使用上线流程,那么就提前走上线流程。
对于前端项目来说,部署并不是一个痛苦的事情。大部分应用只是单纯的静态文件,可以直接打包交给后端人员上线,也可以结合Docker进行自动化部署。若是带有服务端渲染的前端应用,部署会稍微麻烦一些,还需要配套对应的进程管理、服务监控等一系列的工具。
不管怎样,在第一次上线之后,我们实现了从0到1的阶段。有了这一次的经验,往后基本不会出现太多的问题——但是仍有可能出现问题。
2.3.5 提升团队能力
受团队能力影响,越是进度困难的时候,越需要提升团队的能力。它可以避免我们陷入一个误区,即我们因为能力不足而加班,却没有时间提升能力,又进一步导致加班。一旦团队里出现这样的问题,我们就不得不正视这个问题。尽管能力可以通过个人的练习得来,但是通过参与项目的方式来提升能力,则是一种更高速、有效的方式。
提升团队能力的方式有很多,但是受限于业务进度,我们需要选择一种合适的方式,在时间有限的情况下发挥出更好的效果。在项目实施的过程中,相关能力的提升方式如图2-2所示。
图2-2
日常培训的过程如下:
(1)通过进入日常开发之前的培训、阅读文档等一系列的方式,来帮助他们培养基本的能力。
(2)进入开发后,则通过代码检视、代码规范及原则等一系列的方式,来帮助他们写出符合需求的代码。
(3)在项目开发过程中,我们可能会通过结对编程的方式,来帮助他们更好地成长。
如图2-2所示,在这个阶段里,我们提升能力的目标是,让每个人在完成功能的同时,还要保证质量。
1.技术分享(Sessions)
能力提升有多种方式,其中使用得最多的招式便是技术分享。继续按照是和否的分法,我们依旧可以将其分为两类:
◎ 项目相关的技术分享。它所围绕的是项目所使用到的技术。
◎ 非项目相关的技术分享。做一些项目相关的技术栈,或者完全以项目为主的技术分享。
对于非项目相关的技术分享来说,主要目的在于,知道有这样一件事,以及它能做些什么。对于绝大部分的人来说,仅仅是听半小时、一小时的分享,是不可能掌握相关的技能的。整个分享结束,掌握得最好的人,便是那个做技术分享的人。因此,就结果而言,做分享的人是最能学到东西的。我们也往往会将相关的分享,交给团队的新人来做。
当我们做一个技术分享的时候,必然需要准备一系列的资料,还要反复加工相关的东西,这样才能向其他人介绍相关的技术。如果团队中有技术经验丰富的人,就能指出讲述过程中的一些错误。做分享也能加深双方的印象。此外,技术分享还能帮助新人练习一系列非技术相关的技能,诸如表达、资料搜集,等等。
如果想在项目内制定分享的机制,需要人人都进行技术分享,那么就要有相应的鼓励政策。此外,需要注意时间和地点的选择。若是分享可以在上班时间完成,就应该在上班时间完成。否则,团队中的大部分人会觉得这是一种累赘,觉得分享是一个不好的事情。
通常开启技术分享的人是项目的技术负责人。在项目启动阶段,介绍一系列与项目相关的内容和知识。对于这种类型的分享,一般在时间长度上控制在30~60分钟之间。除了介绍理论,还需要配合实践示例,以加深大家的印象。
2.工作坊(Workshop)
对于听的人而言,听别人讲与技术相关的内容,哪怕再有兴趣,一段时间后,我们也会忘得一干二净——这大抵是人的本能吧。平时工作中用不到的内容,我们早晚会忘记的。如果觉得一个技术有用,需要用更有效的方式来学习和练习技术,例如工作坊(Workshop)。
工作坊是一个以练习为主,以理论为辅的掌握新技术的方式。它在介绍新技术的过程中,会设计与之配套的大量练习。参加工作坊的人,都需要参与到这些练习中,以掌握相关的技能。由于这些练习是现场进行,它能让参与者相互进行沟通和交流。在练习过程中,若是遇到一些问题,也能互相帮助,快速解决遇到的问题。正因为如此,与私下的个人练习相比,它能更快速地掌握相关的技能。
与工作坊相似的,还有一个名为Bootcamp的练习事件。它适用于复杂的、抽象的技术,如面向对象和设计模式。工作坊着重于让参与的人掌握一门技术;而Bootcamp则只能帮我们技术入门。
3.面向新人的结对编程
结对编程,是现代软件工程一直在寻找的一种有效的知识传递方式。结对编程存在多种模式:
(1)Navigator-Driver(领航员-驾驶员式)。Navigator关注如何实现功能,Driver则负责实现。并且由Navigator告诉Driver如何实现相关的代码。
(2)Ping-Pong模式。常见于TDD开发模式,由A编写某个功能,B实现测试,随后调反过来,由B编写功能,由A实现测试。
(3)键鼠模式。即编程时,由一方掌握鼠标,一方掌握键盘。这种模式的主要目的是,帮助新人快速熟悉使用编辑器的快捷键。
对于新人而言,我们往往会采用Navigator-Driver的模式来进行结对编程。过程中,只提供相应的思路,由项目中的新人来实现相应的业务。而作为一个经验丰富的程序员,我们除了指导他/她更好地使用工具,诸如如何更好地使用IDE和Git命令等。我们还需要观察新人在过程中犯的错误,有些错误,我们可以直接指出来,并帮助其改正;有些错误,则是等他犯了之后,帮助其解决问题,以积累经验——有些错误若是不犯,可能并不会意识到有错误。
4.对内输出和对外输出
输出是最好的输入方式。在输出的过程中,需要重新梳理知识体系,也因此输出变成了一个输入的过程。这种重新输入的输出,可以分为对内输出和对外输出。
对内输出。我们前面提到的技术分享、工作坊、结对编程等,都是一些对内输出的形式,它可以加快新技术在团队和组织内部的实施。
对外输出。这部分内容便是我们在日常的技术社区里经常看到的各式各样的技术团队的输出方式。在国内,越来越多的公司和企业,都在进行对外输出和分享,比如撰写某项技术在公司的实践、某些新框架的试用,等等。对外输出的目的有两个:
(1)练习技术上的技能,提升相应的软技能。
(2)扩大团队的影响力,以便未来招聘到更多人才。
输出方式多种多样,有翻译、写作、开源项目、技术分享等。我们既可以翻译技术文章,也可以翻译技术书籍,还可以撰写团队相关的技术文章、技术书籍。诸如360奇舞团的相关开发框架和技术周刊,饿了么团队开源的前端组件库,广发证券团队翻译的Angular相关书籍等,这些都是很好的对外输出示例。
5.其他
此外,一旦内部没有资深的人可以对我们进行培训的时候,我们便需要考虑使用外部力量来提升我们,即外部培训。由于笔者并没有遇到内部无法消化的问题,对于外部培训的了解并没有那么深刻。从笔者的角度来看,如果只是为了学习新技术,那么可以尝试在团队中一起学习和练习。在学习和练习的过程中寻找专业的人士、搜索相关的资料,以更细致地掌握相关的内容。
不得不提及的一点是,以上几种方式,都是笔者在ThoughtWorks经历的一些提升方式。在不同的公司里,也会有各自不同的提升方式,总体上存在一定的差异。但是,大体上并不会有太大的偏差,只是有的公司不一定有这么全面的培训体系。