articles
articles copied to clipboard
蟹老板的小经验
## 前言 该文章主要介绍如何把SonarQube集成到gitlab中,通过持续集成,实时获取代码质量报告,控制项目代码质量和减少技术债务。 ## SonarQube是什么? SonarQube是一个代码质量管理平台,提供多语言支持,可以统计代码重复率,复杂度,覆盖率,不规范代码等指标。 [官网地址](https://www.sonarqube.org/),这里不介绍安装方法,可以在官网查看。其中要注意SonarQube只作为管理平台,要进行代码检测,还需要使用sonar-scanner。 ## 代码质量的重要性 判断代码好坏的标准是在阅读别人代码时,说WTF的次数。 如果你所处的开发环境是团队开发,那必然会修改他人编写的代码,但是我们会发现,阅读不规范的代码,会影响你一天的心情,而且你有时候为了插入几行代码,需要花数天时间阅读整块业务代码,你生怕修改会引起副作用。 为了避免产生副作用,你用了最保险的方法修改,但是并不是好的设计,给项目增加了技术债务,后续维护的人继续在债务上累加,最终导致项目无法维护。 我们知道越早偿还债务,成本越低,项目质量仪表盘能在你产生债务的时候,立刻给你提醒,同时这些指标,也在推动团队的维护意识,保持代码的整洁。 ## 集成到gitlab CI #### step 1、安装SonarQube 我推荐大家使用docker安装,一条命令即可。 ``` docker run -d --name sonarqube -p 9000:9000 -p 9092:9092...
## 前言 小程序由于封闭性较强,要像web应用一样实现灵活的数据收集,会有一定难度。目前开源的埋点SDK,一般采用手动埋点的方式,这种方式有较强的侵入型,为了解决这个问题就有了该文章。 ## 手动埋点 以腾讯移动分析的SDK为例,如果要记录埋点信息,只要插入一句代码即可 ``` // 例如,记录搜索行为 search(keyword) { if (keyword) { ...业务代码 } mta.Event.stat("ico_search", {"query":keyword}); } ``` 示例代码看起来是比较简洁的,但是埋点需要收集的数据往往不是单一的,复杂的埋点代码插入业务代码,会**影响代码的阅读体验**,而且**埋点代码散落在各个地方,不方便管理**。 由于手动埋点必须插入到函数中,有时候我们为了获取页面某一元素点击信息,产生了一种叫无业务相关埋点,简单来说就是你的函数定义,就只有埋点代码,当这种埋点频繁出现,**代码会被严重污染**。 ``` // wxml 这只是一个展示view //js track() { mta.Event.stat("eleClick",...
### 背景 目前就职的培训机构,老师会给学生布置每日作业或者阶段考试。检查学生作业时非常耗时的,你要不断的打开学生完成的页面,验证功能的完整性,例如一个涉及到ajax请求的增删改查功能,平均需要花费5分钟检查一个,一个班平均50人每次检查作业就要250分钟,如果持续做这件事情,会耗费太多时间。 ### 问题分析 检查作业的目的就是验证功能的完整性,那在企业中验证功能的完整性,一般会利用单元测试或者e2e测试验证。单元测试多用于对函数或者代码块的验证,在该场景中不适用,因为作业中包含html页面,页面中包含js逻辑,所以e2e测试会更适合该场景的适用。我们可以把学生的代码当成黑盒子,只验证最终实现效果即可。 ### 解决方案 e2e测试框架有很多,但是由于我以前只使用过jest编写单元测试,对jest的语法比较熟悉,所以这次编写e2e测试,也使用jest这个框架来实现。由于需要进行dom操作,jest提供了一个叫`jest-puppeteer`的库用来处理dom,它其实是基于puppeteer做的二次封装,使用API和puppeteer差不多,但是做了一些优化。 ### jest.config.js配置运行环境 jest-puppeteer给我们提供了jest与puppeteer快速整合的能力,它会自动在我们的测试文件自动注入`page`和`browser `对象,你只需要调用page对象打开页面即可,省去不少麻烦事,当然如果你需要自行配置,也是可以的。 如果你需要让jest-puppeteer帮你配置,需要在根目录创建一个`jest.config.js`文件,写入`preset: "jest-puppeteer"`这句即可。 ```js module.exports = { preset: "jest-puppeteer", testEnvironment: "./custom-environment.js" }; ``` ### testEnvironment自定义启动脚本 在运行测试前,往往需要一些准备工作,例如,我测试的内容是一些静态页面,而puppeteer只能访问http页面(可能访问本地路径也可以,没试过),我就需要在测试前启动一个静态服务,那我们可以利用`setup`设置运行脚本前做的事情,`teardown`设置结束脚本时做的事情。 ```js const...
已经有半年时间没写文章了,不是因为这半年太忙而是太懒,期间也冒出过很多想法,但没动力尝试。我感觉现在状态非常差,自信不足,做事敷衍了事,同事关系糟糕。 我想通过这篇文章总结自己为什么跳槽后,变成现在这样,下面的内容会有点记流水账。 > 文章出现这种格式为如果我作为部门leader,我会怎么解决问题 ### 面试 4月中经过两周时间投递和面试,虽然收到的offer不少,但是普遍薪酬较低,只有两个offer薪酬能达到预期,其中一家是创业公司,刚获得天使轮投资,虽然薪酬占优,但是考虑到发展与稳定性,最终选择了另一家国内传统零售龙头公司,下面称其为Y公司。 ### 选择 选择Y公司有两个因素:1、Y公司的传统业务在国内零售行业占比较大份额,有自己的供应链,长期处于盈利状态,稳定性较高。2、Y公司得到腾讯高额融资,试水新零售业务,需要IT系统支持,团队尚未成熟,有机会可以施展拳脚。 ### 入职体验 入职第一天,被安排到一个临时工位,没有告诉你文档在哪里,代码仓库在哪里,去哪里开通账号,所有东西都要问同事,同时由于不同权限负责人不同,开通所有账号,花费约一周。 > 入职体验作为新员工接触公司的第一印象,尤为重要。B公司这方面做的比较好,在员工入职前一天,HR发送邮件让负责账号管理的同事,开通所有账号,并邮件抄送给其上级主管,员工入职当天,需要主管接待新员工,跟团队成员做一下互动,让大家互相认识。 ### 接触代码 拿到代码后,第一时间了解项目架构与开发规范,但是发现项目由于人员变更过于频繁,同时前期没有做严格的开发规范,导致项目出现较多问题。 **1、代码格式和风格多样。** > 引入eslint做静态检测,可以增加git hook强制提交代码时校验。统一代码格式化规则,使用prettier插件导出配置文件。 **2、由于小程序早期版本不支持组件,项目存在大量应用template开发,但是template的css是全局的,为了防止css冲突,template的class命名会很长,但是也还是无法解决样式冲突。另外template还会操作setData方法,会导致数据不可控。** > 多人开发的项目,代码的隔离性较为重要,但是template模式明显违反了该原则。在小程序支持组件后,应该在编写新功能时使用组件开发,逐步替换template。同时规范UI组件和业务组件,维护好组件文档。但是在推行组件模式开发时,有部分开发表现得较为排斥,最终未能推进组件化,导致项目仍然有大量混合开发。 **3、代码分层与职责不清晰。由于没有独立接口层,网络请求定义会被嵌入到逻辑层,不仅无法复用请求代码还会导致层级职责不清,修改代码时较难找到对应代码** > 加入独立的apis目录,将项目用到的所有接口统一在apis目录,同时优化http层,统一处理网络错误和服务端通用异常。 **4、代码圈复杂度高。圈复杂度表示一个函数具有的分支个数,例如一个if else复杂度就是2,如果一个函数圈复杂度高,就表示该函数逻辑过于复杂,维护和理解成本高**...
## 前言 最近用户反馈我们的小程序很卡,打开商品列表需要四五秒时间,带着这个疑问,我决定对小程序做个全面的性能优化,要做性能优化,必须先理清以下三个关键点。 1. 产生性能问题的关键点 2. 度量性能指标 3. 寻找解决方案 在阅读案例分析前,建议能先了解小程序的工作原理和性能关键点。 ## 工作原理 (官方说明) 小程序的视图层目前使用 WebView 作为渲染载体,而逻辑层是由独立的 JavascriptCore 作为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的 `evaluateJavascript` 所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。 而 `evaluateJavascript` 的执行会受很多方面的影响,数据到达视图层并不是实时的。...
写这篇文章是因为最近在看业务代码,发现存在大量意大利面代码,一个函数上百行代码一个js有一千多行代码,理解的过程会让人非常痛苦。 我们就这个问题,讨论下如何编写让人能快速理解的代码。 ## 从小明的一天开始 我们以小明的一天为故事编写两份代码,对比两个阅读体验。 ``` class Person { constructor(name) { this.name = name; this.walkSetp(10) this.turnLeft() this.pickUpToothpaste() this.pickUpToothbrush() this.walkSetp(20); this.trunRight(10); this.turnLeft(10); this.sit(); this.pickUpChopsticks(); this.pinchUpFood(); this.putInMouth(); } } const xiaoMing =...
## 单元测试概念 在计算机编程中,单元测试(英语:Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。 -- 维基百科 我们会发现,一些优秀的开源项目,都有较全面的单元测试,但是我们维护的业务系统,却少有单元测试的踪影,难道单元测试实施成本真的这么高吗,下面我们将讨论单元测试有什么优点。 ## 防止产生遗留代码 《修改代码的艺术》中说作者认为,**遗留代码**就是那些没有编写相应测试的代码,没有编写测试的代码是糟糕的代码。不管我们有多细心地去编写它们,不管它们有多漂亮、面向对象或封装良好,只要没有编写测试,我们实际上就不知道修改后的代码是变得更好还是更糟了。反之,有了测试,我们就能迅速、可验证地修改代码的行为。 ## 降低开发维护成本 当提到单元测试应用到业务系统开发流程时,也许大多数听到的反馈是成本太高,开发周期过长,维护困难。 我们得出这样的结论,也许是因为没搞清楚成本的概念,软件的成本远远不止开发成本,我理解的成本应该像下面这条公式的。 **软件成本=开发成本(20%)+ 维护成本(30%)+ 异常成本(50%)** 如果你正在维护一套开发超过两年的系统,当你需要添加一个需求或者改动旧代码的时候,你总是小心翼翼的,你不得不认真的理解整块代码,生怕一个改动,会导致旧的功能无法运行。 你担心的事情,总是会发生的,不知道会在什么时候,也许是在业务最关键的时刻爆发,造成业务中断,给企业造成的损失将会远远超出开发成本。 如果你的业务代码包含完整的单元测试,你的公式就变为下面: **软件成本=开发成本(20%)+ 单元测试成本(10%)+ 维护成本(10%)+ 异常成本(10%)** 虽然开发过程中需要时间来编写单元测试代码,但是在以后改动需求的时候,你就可以大胆的修改了,单元测试可以帮助你控制软件的质量,你也可以信心满满的把应用部署到线上,万一出现意外,也可以通过单元测试帮助你定位问题。 下面为引用《单元测试的艺术》中的一个段落,两个团队分别使用和不使用单元测试,各项指标的差异。  下面为《有效单元测试》中关于bug修复成本的片段 ...
#### 破窗效应是犯罪心理学的一个理论,指如果一个建筑,当出现小量破窗的时候,会诱发更多的人为破坏。如果一个建筑出现破窗的时候及时修复,会受到更少破坏。 我们是否有这样的经历,当接手一个代码质量较差的项目,例如一个函数有上百行的代码,函数里有大量的if else,如果让你增加一个功能,你更倾向于直接在目标函数上加入你的改动代码,而不是通读该方法,再进行封装修改呢。 其实这样的修改方式,并没有错,也和个人能力没有关系,因为这种修改方式是最保险,最快捷的,他不但维持代码原有功能正常运行,还添加了新的功能。 但是,这样的项目,就是典型的破窗效应,因为第一个人产生了破窗,没有及时修复,后面来的人,就会更大胆的破坏,最终项目没法维护。 ### 那如何避免项目形成破窗效应呢? 1、**制定代码规范**:尽量使用自动化工具实时检测,不要试图通过文档规范,文档一般都不会有人看的,前端集成eslint就最好了,vs code可以安装相应插件实时提醒。另外,可以加入git hook,对不符合规范对代码,拒绝进入代码仓库。 2、**code review**: 静态代码检测,只能检查语法问题,但是对于代码设计问题,需要code review进行纠正,code review可以利用gitlab 或者 github的 pull request模式,对需要合并到主分支的代码进行review。 3、**控制圈复杂度**:代码好坏的一个重要标准是,函数的圈复杂度,如果一个函数有大量分支,会让人很难理解,所以控制圈复杂度可以有效提高代码质量,vs code可以利用CodeMetrics这款插件实时检查。 4、**控制代码重复率**:《编写有效的单元测试》书中提到,重复的代码是造成代码bug提高很重要的因素,我们可以利用SonarQube对代码重复率进行扫描,删除重复代码或者对相近的代码进行封装。 5、**自动化单元测试**:很多人可能会觉得单元测试成本太高,为什么会产生这样的感觉呢,我觉得主要是大家把开发成本理解为开发功能所需要的时间,但是实际上,项目的成本,包含开发成本,维护成本,bug处理成本,代码二次开发成本。开发成本也许只占项目成本的10%,后面功能越是复杂,维护成本将会出现指数增长,前期不去控制复杂度,会给后期带来巨大的成本开销。 自动测试就像房子的管家,哪个坏小子想要搞破坏,立刻就会收到警告。 下面为引用《单元测试的艺术》中的一个段落,两个团队分别使用和不使用单元测试,各项指标的差异。  ### 那如果已经是一个破烂不堪的项目,又如何拯救它呢? 1、**eslint自动修复**:还是上面说的代码规范,我们需要利用eslint进行老代码清理,使用eslint...
《代码整洁之道》中说,你的测试代码应该像业务代码一样认真编写,因为测试代码会随着业务代码一块演进,糟糕的测试代码会使你的项目难以维护。 下面聊一下如何给测试用例取一个好名字,当该用例不通过时,可以帮助我们快速定位问题。 ## 准确的断言 假设我们的业务代码是一个网络请求的封装。 ``` function _request(url, data, method = 'GET') { return new Promise((resolve, reject) => { wx.showLoading({ title: '加载中' }); wx.request({ url: url, data, method, success: (res)...