第二章 复杂度
2.1 代码大小
- 可以让函数保持最小代码量的一个方法是让命令(setter)和查询(getter)保持分离
- 命令函数用mock测试
- 查询函数用stub测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var Obj = (function(){
return function(){
var docRoot = '/somewhere';
this.validateDocRoot = function(val){
// validation logic - throw Exception if not OK
};
this.setDocRoot = function(val){
this.validateDocRoot(val);
docRoot = val;
};
this.getDocRoot = function(){
return docRoot;
}
Object.preventExtensions(this); // 任何人尝试在该对象上添加属性都会抛出TypeError
}
}())
2.3 圈复杂度
- 最简单的重构修复,是将方法分解成更小的方法,或使用一个lookup表。
1 | function doSomething(a){ |
lookup表重构后1
2
3
4function doSomething(a){
var lookup = {x:doX,y:doY},def = doZ;
lookup[a] ?lookup[a]():def();
}
- jscheckstyle 计算圈复杂度 圈复杂度尽量小于10
2.5 扇出
- 扇入(fan_in):内部流程数量及欲从A中获取信息的数据结构数量之和(检测重用部分)
- 扇出(fan_out):内部流程数量与所更新的数据结构(相对于A外部)数量之和(A的扇出:A调用B,B调用A,A返回一个B可利用的值,C调用A和B,A的返回值传给B)
- 复杂度 = (fan_in * fan_out)^2
- 控制不含事件的扇出的策略是创建一个对象,并让该对象封装一些高扇出的模块,并保留该模块最初功能的单一依赖。
1 | function makeChickenDinner(ingredients){ |
降低扇出后
1 | function Cooker(oven){ |
注入外观负责cooking
- 依赖注入 TODO
2.11 注释
文档生成器:
- YUIDoc
- JSDoc
- Docco/Rocco
第3章 基于事件的架构
3.2 事件集线器
- 尽管所有的通信都是通过EventHub对象进行的,但在EventHub对象里,它们之间没有共享状态,不能通过改变它或改变它的状态去共享信息。
- EventHub TODO
第4章 单元测试
- PhantomJS
- Selenium
- Jasmine
第5章 代码覆盖率
第6章 集成测试、性能测试、负载测试
6.2 性能测试
- HAR文件(HTTP存档文件)
- 生成HAR文件
- tcpdump,以PCAP格式捕获HTTP流量;pcap2har,生成HAR
- 使用代理。browsermob-proxy/Fiddler/Charles
- 查看HAR文件
- 拖到浏览器中
- YSlow
- 性能测试 Speed Tracer
6.3 负载测试
- nodeload
6.4 跟踪资源利用率
- JavaScript内存泄露的唯一途径是保持对不再需要对象的引用
- chrome://memory-redirect/
- webkit-devtools-agent
第7章 调试
7.3 远程调试
场景
- 调试移动浏览器
- 调试服务端JavaScript
- 调试浏览器工具
- 编程化调试
远程调试Chrome中运行的JavaScript,需要启动一个带有调试器可监听端口的Chrome可执行文件。
window %chrome.exe –remote-debugging-port=9222
mac /Applications/Google\ Chrome.app/Contents/Mocos/Google\ Chrome –remote-debugging-port=9222
第8章 自动化
- 运行单元测试并生成覆盖报告 JUTE
- 代码审查 Review Board
- 修复基本的JSLint fixmyjs
- Jenkins
- 遍历代码查找重复部分 dupfind