一、日常问题
1)协作团队资源不足
这次公司有个五周年的庆典活动,但正好碰到两个APP的版本发布,以及三个测试老员工离职,只进来了两个新成员,其中一个恰好要休陪产假,那么测试组资源异常紧张。
虽然我们提前了整整一周提测,但一直到周五还有很多点没测到。测试组甚至想到了阶段测试,因为多个活动的上线时间不同,所以可以先测最先上线的活动,后面的再往后推,延迟测试,这是他们组的一个对策。
而我们前端组,可以做的就是先按照他们的测试用例,自行跑一遍,提前帮他们把一些明显的BUG修复掉。虽然不能很深的测试,但至少可以替他们节省不少时间。
有时候就是一些很简单的问题会拖慢整体节奏,例如数据缺失、页面白屏、接口不通等。
打破常规,在测试环境的时候就将页面给产品体验,而不是等到预发才确认。
因为她可能掌握着一些我们不知道的信息,例如我们都以为页面只会在活动开始的时候才会开放访问,其实不然,运营会提前一天造势,所以的话,有些操作需要加时间判断,这是之前未考虑到的点,得修改代码。
这样的话,既拖慢了上线时间,也有可能造成潜在的BUG出现。虽然做了很多保障,但是周五晚上还是加了会儿班。
2)低代码
低代码在行业里比较流行观点是更加易用、降低开发成本的搭建系统。其实就是面向特定场景做抽象、沉淀出最佳实践,再通过产品封装来加速整个制作过程。
我这边实现低代码的第一步,是将常用的活动功能提取出来,减少代码的体量,增加代码的稳定性。
例如公司常规的打榜活动,活动形式和玩法都比较固定,于是组织团队三个成员分别将活动的三端抽象化。
我负责榜单的数据源,开发了一套针对该类型活动的定时任务,在后台可视化操作,可事实更新参数。
另外两名成员,一个是将前端页面中通用的部分封装成组件,包括表单、菜单切换、埋点、分享等。
另一个是将请求接口中的逻辑封装成几个方法,未来只要传几个参数就能获取到对应的数据,并且将一个可配的参数存储在通用配置中,而不是硬编码在代码中。
这套组合拳打出来之后,可大大缩短活动的开发周期(目标是一天),也能解放测试,因为系统稳定后,就可以直接上线了,运营人员也不用半夜找我们修改BUG了。
当然还有第二步,那就是将前端页面也做成可视化的,拖拖组件就能完成搭建。
3)规范开发流程
公司最近上线了一个新礼物,但在上线后出现了很多问题,例如新礼物的收益未计算在榜单中、新礼物出现在错误的类别中等等。
技术团队内部讨论后,由技术部leader牵头,为了避免重蹈覆辙,重新制订了一套保障研发顺利进行的流程。
而在这个流程中会新增一个临时 PM(项目经理)的角色,其职责和我之前提到的协调人差不多,这个人在项目开发过程中起着非常关键的作用。
这套流程分成六个部分:需求评审、技术评审、用例评审、测试验收、提审上线和复盘总结。对于我们前端来说,提审上线这一步是不需要的。
每一部分都会有几个清单,当完成时就把勾打上,当不存在时,就直接删除,开发成员只要查看这份清单就能洞悉目前的开发进度。
需求评审是为了确保需求清晰无疑问,UI设计及时交付,埋点准确无误。
技术评审是为了确保相关技术人员都参与到了技术方案的讨论中,避免出现细节遗漏。
用例评审是为了确保测试用例和冒烟用例都已传达到了相关技术人员,明确本次测试方案。
测试验收是为了确保测试人员已在测试环境、预发环境、生产环境验收,以及业务部门也已验收。
提审上线是为了确保客户端已发布应用市场和App Store。
复盘总结是为了解决掉研发过程中暴露出的问题,输出相应的解决方案,避免再次踩坑以及提前预防此类问题或相关问题的发生。
4)结点不一致
最近遇到个比较离谱的事情,大家做项目的时候,居然对上线时间都有偏差。知道是那一天,但有的认为是0点,有的认为是10点,有的认为是20点。
之所以会有偏差,是因为产品文档上写的上线时间是0点,而与这个项目同时进行的还有另一个项目,上线时间是10点(也就是说,两个项目混淆了),认为晚上20点上线,其依据的是效果图中的活动时间。最终和产品协商后发现是20点上线,产品这个锅得背一下,需求文档没有及时更新,但大家以后真的得好好对一对上线时间。
这是一个比较严重的信息不同步,直接导致了大家修BUG的速度有快有慢。测试在抛出BUG后,就要等待相关人员修复,一个多端联调的BUG就会花费比较多的时间,进度缓慢,很容易出现不必要的加班。
之前的流程中曾选出一个临时PM,而这个人是有责任来协助测试人员完成测试任务的,尤其是临近上线的时间。最简单直接的方式就是每隔一段时间询问当前进度,了解卡在何处,想办法帮助推进,协调资源。不要白天悠闲的修修补补,到了晚上突然冒出这个那个的问题,产品和运营都没时间给他们验收,匆匆忙忙的上线,后患无穷。
5)菜单梳理
经常会有人来问我管理后台的XX功能有没有或怎么用,出现了XX问题,该怎么解决。
其实很多时候我也不太清楚,自己也是中途接手。最清楚的人莫过于每天都在使用的业务人员,所以首先得知道哪些人在用哪些功能。
在和产品沟通的时候了解到,她们之前特地整理过一份管理后台使用人的表格,只是内容还未填写。
表格的横坐标是小组,纵坐标是菜单,每个单元格都有每日、每周、每月和偶尔使用的选项。
后面拉了个群,将相关负责人邀请进来,让他们把各自负责的部分填写了一下。以后找功能就能快速定位到某个小组了。
测试组对管理后台也是比较了解的一个小组,因为他们也需要经常操作各类菜单。在和他们沟通时,他们提供了一张管理后台功能的思维导图。
这是之前他们专门花了几周时间安排一个人力做的整理,覆盖了那期间的所有功能。由于之前管理后台是没有产品支持的,所以也就没有产品文档。
有了这张思维图后,对于我们来说,是一个非常好的参考。
无论是使用人表格还是思维导图,都有一个比较麻烦的点,那就是需要有专人来维护。经过几个月的发展,管理后台又新增了一大批功能,这些都还未整理进来。
后期需要讨论下由哪个组来维护这些文档。
6)边角项目
边角项目是指那些隐藏在角落里,让人忽略的项目,随着人员的流动,这些项目往往就会被埋藏起来,没人知道还有这么一个项目存在。
一旦碰到这类项目,就需要花大量时间寻找源码和阅读逻辑,有时候还得重新配置发布环境,往往需要联合运维来查找这类项目。
这类项目神秘莫测,往往无法主动将它们揪出来,因为没有任何文档遗留,或者在众多文档中轻描淡写的记录了一句话,很容易让人看走眼。
最近碰到两个这样的项目,一个是运营说要更新官网主页,一看到域名,就知道之前没有维护过,找运维才定位到指向的项目。
另一个是小程序中出现了一个BUG,经过排查发现调用了一个接口,但这个接口不在平时维护的项目中,翻阅文档,才知道原来这类接口存在于一个独立的项目中。
这两个项目有个共同点就是都已经断更,前者是之前就很少维护,后者是已将大部分接口迁移到另一处。
目前唯一的手段就是补充这两个项目的文档,完善信息,下次再遇到就能胸有成竹了。
二、工作优化
1)代码腐烂
这是我最近听到的一个新词语,所谓代码腐烂,简单地说是指代码在可维护性,灵活性,可移植性,可重用性,可测试性,可理解性等质量方面变得越来越差。
代码腐烂不是一搓而就的,都会经历一个循序渐进的过程。联想到我当前公司的项目,它们也正在腐烂中,而造成腐烂的原因包括维护他人遗留下的代码,技术栈长期未更新等。
在缺少代码规范、注释,并且无法与之前的维护人员有效沟通时,修改当前代码难免会不理解当时的设计思路和逻辑结构,按自己的想法去修改,可能会留下不稳定因素,而给自己埋坑。
减缓该腐烂的方法就是多加注释,多为核心业务编撰各类文档,制订代码规范统一代码风格。多多沉淀,稳定代码,少做少错,例如抽象后台业务组件,定时任务参数化,通用接口等。
老旧的技术栈会限制使用新的库、新的开发思想、甚至限制团队成员的技术拓展,例如公司还有一个项目在使用jQuery,Node项目还基于8.7的版本,后台管理系统基于Umi 1.0 并且是个巨石应用。
减缓该腐烂的方法有多种应对策略,目前正在将jQuery技术栈迁移到Vue;Node项目正在迁移到基于14版本的新项目中;对后台管理系统进行剥离,引入微前端整合新旧两套系统。
个人感觉代码腐烂是一种自然趋势,我们所能做的就是减缓腐烂的速度。
2)返回上一页
在管理后台中身份过期后就要重新登录,目前只会登录到主页,并不返回上一页,在体验上大打折扣。
我们的账号会开放所有菜单,每次在系统开发阶段过一天刷新页面就要重登陆,然后再找一下菜单,这一找就得花个几十秒甚至几分钟,非常浪费时间。
于是决定加此功能,首先想到的是在Server端读取上一页地址。
每次页面切换,都会请求一个身份接口,于是在接口中读取 KOA 封装的属性:ctx.request.headers['referer'],但事与愿违,得到的却是 undefined。
查看 HTTP 请求中的首部,发现有一个 Referrer Policy: no-referrer,也就是禁用了 referrer。搜索前端页面,发现模板中的 meta 元素有一段声明:
<meta name="referrer" content="no-referrer"/>
经过与同事沟通,发现他当时为了解决一个BUG才加的这段。在团队协作开发时,切记不可贸然修改源码,很有可能影响原有逻辑。
如此一来就不可在服务端请求,但即使我取消了这段声明,在Server端返回上一页,改造成本也是巨大的,只得放弃该方案。
另一个方案就是在前端页面中增加读取上一页的逻辑,马上想到的是 document.referrer,但发现每次读取都是空字符串,很是不解。
后面再想一下,才发现后台管理系统是一个单页应用,所以跳转地址并不会刷新浏览器,也就无法通过 document.referrer 读取上一页了。
但既然是单页应用,那么就会有浏览器的历史记录,我们的框架使用的是 react-router-redux,一翻文档果然有返回上一页的方法:goBack()。
不过又出现了新的问题,就是如果直接在浏览器中输入登录的地址,那么就没有上一页,默认得跳转到主页,得判断出这种情况。
在该库中没有什么发现,后面再深入到HTML5的History对象,发现它有一个 state 属性,记录了历史堆栈顶部的状态值,若没有就是null,这样就能判断了。
在实际使用中发现重登陆后,还是会跳转到主页,经过排查发现在回到登录界面时并不是路由切换,而是地址跳转,等于说是重新进入了一个页面。
此时页面并不存在上一页,所以默认就会切换到主页。
后面是在监听全局路由切换的事件中(使用的是dva.js),通过sessionStorage缓存当前页面的路径,在登录的时候切换至缓存中的路径。
subscriptions: { setup({ dispatch, history }) { history.listen((location) => { if (location.pathname !== '/login') { sessionStorage.setItem('last_pathname', location.pathname); //缓存上一页路径 } }); }, },
一个看上去蛮简单的功能,但其实真正做起来还是需要花点精力和脑力的,并且还要了解一些原理。
3)静态页面配置
静态页面是指那些只要几张静态图片的页面,没有任何交互和跳转,例如宣传页、各类政策等。
这类页面虽然重新开发成本并不高,但是将前前后后的时间统计起来(包括开发、发布、验收等步骤),其实也不少,半小时最起码。
并且做好后,在验收阶段很有可能对图片修修改改,那么就需要重新发布。最麻烦的是在休息时间要求修改,那么很难第一时间做出响应。
经过综合考虑,还是在后台做个功能,让运营或产品可以自行编辑和发布这类页面,让他们不用那么被动,大致效果如下图所示。
就是一个标题以及动态添加图片地址,当然也可以做出动态上传图片。
这是一种简单的楼层搭建方式,如果有人力有资源的话,可以做一套可视化搭建系统,将各类运营活动集中到该系统中处理。
4)代码发布提速
后台管理系统分为前端页面和后端服务两个项目,后端服务代码发布的时间很稳定,但是前端页面的发布时间就很冗长。
在刚接手这个项目时,发布时间在10分钟左右。当时就和运维商量,出个解决方案来提速。
运维找到阿里云的技术支持,但是也没有一个好的解决方案,就这样不了了之了。
经过几个月的时间后,我上线了前端监控系统。这套系统需要监控项目的source map文件。于是在构建后台管理系统的脚本时,多了一步生成该文件。
由于管理系统的脚本已经非常巨大,所以构建的过程又被拉长了,代码发布的时间也被加长。有时候甚至要20分钟,可能还无法正确发布。
基于umi升级的这次契机,我关闭了source map文件的生成(在实际使用中,也很少用到该功能),发布时间一下子稳定在了8分钟左右。
不过,这个时间仍然无法符合我的预期,再去和运维商量。他的意思可以打一个镜像,不用每次都下载npm中的依赖包。
这个提议非常好,马上就让他帮忙弄了一下,经过了几次调试,终于发布成功了,目前稳定在4分钟内。
在实际使用中,却出现了非常严重的问题,运维将源代码也打包到了镜像中,也就是说,我更新的代码不能发布,那这样的话,这个优化就没有意义,只能回退到原先的样子。
5)活动复盘
最近上线了两个差不多的活动,在实际运营中,共出现了三个问题。虽然都不是致命的BUG,但也暴露出了不少问题。
这次的三个问题都是时间导致的,可以看出组内的成员对比较基础的时间处理还比较模糊。
后面就抽空带大家一起重新学习了JavaScript与时间相关的基础概念,查缺补漏。
并且再次强调了单元测试的重要性,因为这次的几个BUG,测试不一定能测出来。因为要与需求保持一致的话,就得修改服务器时间,与活动的截止日期保持一致,才能测出来。
但如果自己做了单元测试,那么就可以通过传入不同的时间参数,得到不一致的结果,从而就能将问题扼杀在上线前。
当然,这次测试人员有些地方也没到位,未来的话,是希望测试的时候,有些方面要与需求保持高度一致。
以后每次活动之后都可以做点复盘,保持好的方面,改正坏的方面。如果能在下次的活动中避免出现相同的问题,不再重蹈覆辙,那也是一种收获。