• 带团队后的日常(一)
  • 带团队后的日常(二)
  • 带团队后的日常(三)

    一、日常工作

    1)开会

      由于公司规模并不大,因此一有事情就会拉个会议,例如需要大会、技术评审、汇报周会、突发会议等。一周中大概有20%~30%的时间会花在大大小小的会议上。
      公司会议难免会出现接锅的情况,虽然自己不想做锅靖,但是有些边界定义比较模糊的锅(既可以给后端,也可以给前端),在时间允许的时候,都会自己接下,因为服务端资源很有限,日常杂活太多,大家打工人都不容易。
      虽然比较费时,但会让自己有更多的参与感。公司办公都是用mac pro最新款,携带也比较方便,开会的时候带个笔记本,也可以在会议中处理一些工作的事情。
      在团队成员来齐后,每周五的10点,自己还会组织一个团队短会,一般控制在30分钟内。不是工作汇报,而是:
  1. 回顾一下本周遇到的难点或费时的事情,若还未解决,可在会议上当场讨论思路。避免下次碰到又要花费太多精力。
  2. 发表一下自己这周遇到的困惑,无论是技术还是公司,都可以随意发表。互相了解一下团队成员的想法。
  3. 我也会传达一些公司信息,例如本周或下周的重点任务、公司的新政策等,及时与团队成员同步。
  4. 若有时间还会做个简短的 Code Review,或者做技术分享,无论是当前前沿技术,或者是经典案例,都行。

    2)任务分配

      目前公司两条产品线,加上我是3个人,他们各自负责一条线。若一些需求没时间做的时候,我也会帮忙写。
      并且与组内成员要保持任务信息的同步,大家都得清楚现在做什么,未来还有哪些活需要处理。
      新同学刚来没多久,还在适应期,给他的任务都不是紧急的。当抽不出人手时,也会让他搞,不过我和另一个同学也会协助他。
      当有紧急需求时,我会将优先级不高的任务延后,并安排给合适的人处理。
      自己除了开会之外,也要写代码,一些难弄麻烦费时的功能都留给了自己,例如那些跨团队的、或是测试环境不容易部署的功能。
      每天也会关注一下组员的进度,遇到问题可以帮忙出解决方案或应对策略,以免卡在一个地方,既影响心情,也影响开发进度。

    3)错误调试

      我们Web小组不仅维护着一个庞大的后台管理系统(前后台都做),还参与过许多后端服务(例如定时任务、金额结算)、H5活动页面、微信公众号、小程序等。
      因此,很多时候线上出问题,都会与我们组有关。经常是某个人找到我,向我反馈问题,严重的话我就得停下手中工作,立刻去拍错。
      我花了很多时间去做各种错误调试,并且经常会出现跨团队的场景,而我排错的过程一般是几步:

  5. 页面样式出错,那毫无疑问是我们组的问题,除非那人看错了,将客户端的页面报到了我们这边。

  6. 若是调用的接口问题(所有的前端接口都会通过Node服务做一层中转),那么会将接口路径拿到VS Code中做一次项目搜索,查看代码逻辑。
  7. 若内部核心逻辑是调用服务端内部接口,那么就需要将问题反馈给他们,再做联调和定位是谁的问题。
  8. 若接口中的逻辑没有调用内部接口,都是直接操作数据库的,那么就要查找数据库写入的逻辑。若没有,那么就去找谁在维护这张表。

  之前就遇到过一个问题,说是后台的一张重要的统计报表没数据了。查了半天,发现是一个定时任务在做写入,而在这个定时任务中又会涉及MongoDB的写入、客户端的上报、第三方平台和服务端的读取。在一一排除后,最终发现是服务端在写入其中一个数据源时,日期写的不对(由于时区的问题)。断断续续花了4天的时间,期间与运维、客户端、服务器、测试还有第三方平台的技术人员先后做过沟通,这种排错很费成本。
  后面又遇到一个问题,也是与后台有关,说是一张统计表看不到了。这次也是先查写入的代码,发现没有,马上与服务端联系,他们那边也没有。于是就找到测试组,因为他们组目前是公司内最了解整个管理系统的人,果然找对了人,他就说是AI算法组在维护的。找到他们之后,才查出是他们的一个定时任务挂了,怪不得没有数据。之后在周会上,我就提出让他们统计出自己维护的数据库表,并且是那些与我们组相关的数据库中的表。

4)完善文档

  文档有两大关键的意义:

  • 第一个是帮助梳理思路,消除个体对于事物的不确定性。
  • 第二个是传递信息,消除团队中对于事物的不确定性。

  先前的 WIKI 已有部分文档,但内容非常分散,不成体系,我花了点时间重新梳理,并整理到合适的位置。
  书写之前没有的文档,尤其是现在比较重要的业务或功能,完善业务流程,甚至将相关的 SQL 查询语句都整理了出来,方便调试。
  邀请其他组的成员帮忙书写相关的文档,例如让客户端组完善 JSBridge 文档,而测试组是目前掌握最多业务细节的人,让他们帮忙写些发生突发情况或意外故障的处理过程。

二、工作优化

  日常的工作除了做业务需求(俗称写BUG)之外,其实就是发现问题,再解决问题,有时间的话,找出合理的优化手段,避免重复踩坑。

1)MongoDB可视化界面

  若要查询MySQL,可以借助DMS可视化界面。但要查询MongoDB,那么只能先连上跳板机,然后再通过跳板机进入MongoDB服务器,这一来一回经常要耗上点时间。
  因此,后面就着手自己写了一个简易的可视化界面,只提供查询功能。Node代码中的ORM系统采用的是Mongoose库,那么就从其find()方法着手。
  界面中需要传入一个Model名称,多行文本中只要传入 where 条件即可,语法参考的是 db.collection.find(),下图灰色使用了

  1. 标签,为了能在页面中显示空行和换行。
      1.带团队后的日常 - 图1
      在后台管理系统中,原先有个查询redis的界面,但只查了一个库,数据类型也只列了4种,后面将库修改为可配,并且新增了一个数据类型。
      从而就能避免通过跳板机来读取redis中的缓存,可直接在页面中查询。
      脚本文件的执行,原先除了上传代码之外,还得进入服务器中,手动输入命令执行。
      这么操作略微繁琐,自己做了点加工,做成半自动,代码还是要发,不过在后台管理系统中有个按钮,点击后就能执行指定的脚本,下面是执行接口,调用了 fork() 方法。

  2. router.get('/scripts/exec', async (ctx) => {
  3.     const path = require('path');
  4.     const { fork } = require('child_process');
  5.     const exactPath = path.resolve(__dirname, 'scripts/index.js');
  6.     fork(exactPath);
  7.     ctx.body = { code: 0 };
  8. });
  9.  
  10. 2)微信公众号配置封装

      调用微信公众号的JS-SDK之前,都是需要先引入配置文件的。先前的做法是先在前端脚请求一个接口,响应得到timestampnoncestrsignature等参数。
      然后调用wx.config()进行配置,最后在wx.ready()调用微信的onMenuShareTimeline()、onMenuShareAppMessage()等方法。

  11. const wx = require("weixin-js-sdk");
  12.     const wxUrl = encodeURIComponent(location.href.split("#")[0]);
  13.     getWeixin(wxUrl).then((e) => {
  14.       wx.config({
  15.         // debug: true,
  16.         appId: "wx....",           // 必填,公众号的唯一标识
  17.         timestamp: e.timestamp,       // 必填,生成签名的时间戳
  18.         nonceStr: e.noncestr,        // 必填,生成签名的随机串
  19.         signature: e.signature,       // 必填,签名
  20.         jsApiList: [
  21.           "onMenuShareTimeline",
  22.           "onMenuShareAppMessage",
  23.         ], 
  24.       });
  25.     });
  26.     wx.ready(function () {
  27.       wx.onMenuShareTimeline({
  28.         title: "",
  29.         desc: "",
  30.         link: "",
  31.         imgUrl: "",
  32.         success: function () {},
  33.       });
  34.       wx.onMenuShareAppMessage({
  35.         title: "",
  36.         desc: "",
  37.         link: "",
  38.         imgUrl: "",
  39.         success: function () {},
  40.       });
  41.     });
  42.  
  43.   一旦需要用到微信JS-SDK就要调用这么一坨,但其实这些可以都放到服务端去执行。
      后面我将上述配置封装到后端的一个router方法中,路由成一个JS文件(例如bridge.js),前端只要调用它,然后传递一些参数做一些简单的变量声明即可,完全不需要配置appidsignature等参数。

  44. 3)后台管理系统界面优化

      后台管理系统都会包含左边的菜单栏,刚接手的时候,每次页面刷新,菜单栏默认就会闭合,不会展开当前URL路径所处的菜单。
      在调试的时候,改一下脚本就会自动刷新窗口,一刷新菜单就会闭合,导致我要换旁边的菜单时,又要一步步的点击。
      于是就着手开始优化,在查看代码时发现,菜单数据被抽象成了多叉树结构,而选中某个页面的菜单,其实就是用深度优先算法来匹配指定路径,下面用代码简单的实现了这个功能。

  45. //深度优先 搜索当前菜单
  46.   let defaultSelectedKeys = [],   //默认选中的菜单
  47.     defaultOpenKeys = [],         //默认需要展开的菜单路径
  48.     isFind = false;
  49.   const dfs = (node, keys) => {
  50.     keys.push(node.id);
  51.     if(node.routers == props.path) {
  52.       isFind = true;
  53.       defaultSelectedKeys.push(node.id);  
  54.       defaultOpenKeys = keys;
  55.       return;
  56.     }
  57.     node.children && node.children.forEach(value => {
  58.       if(isFind)
  59.         return;
  60.       dfs(value, [...keys]);
  61.     });
  62.   };
  63.   dfs(menuTree[0], []);
  64.  
  65.   其实算法离我们平时的业务并不远,只要用心发现就能挖掘出各类算法。

  66. 4)发布系统问题

      公司买了第三方平台的一套发布系统服务,每次发布时,都会比较耗时,卡在某一步,少则78分钟,多则10几、20多分钟。
      向运维也反馈过很多次,但每次都没有找到针对性的解决办法。
      最后无奈,只得和运维商量,在测试环境,自己写个文件传输工具,直接把build后的代码传到指定目录,跳过发布系统。
      毕竟测试环境要经常发代码,老这么延迟,实在是会让人困扰。运维的意思是他们提供脚本,我们在跳板机上运行脚本,实现文件传输。
      虽然没有一键传输方便,但聊胜于无,总比干等好,同意了这个方案,后续跟进。
      期间还碰到了另一个棘手的问题,那就是测试和正式环境的Node版本过低,比当前稳定版本低了6个版本。
      这就导致很多库不能直接安装,得另想办法或者用该库比较老的版本。
      现在也不能立马更新,一更新就出错,测试也没有额外的资源帮忙一起调试。时间与资源的矛盾暂时还不能妥善解决。

  67. 5)性能分析日志

      公司购买了阿里云的日志服务,之前几个纯前端的项目虽然开通了日志服务,但并没有妥善使用起来。
      这次正好想到可以开通阿里云的WebTracking的采集功能,将性能参数推送到阿里云日志服务器中,参数搜集的库采用了之前自己封装的pineapple.js

  68. <head>
  69.   <title>性能参数demo</title>
  70.   <meta charset="utf-8">
  71.   <script>
  72.     window.pineapple || (pineapple = {});
  73.     pineapple.param = {
  74.       "token": "a0b923820dcc509a"
  75.     };
  76.   </script>
  77.   <script src="pineapple.js"></script>
  78. </head>
  79.  
  80.   在参数搜集好后,就能借助阿里云强大的查询分析功能,分析页面性能了,目前还没想好分析维度。
      1.带团队后的日常 - 图2