LeoYuan / leoyuan.github.io

This is my blog repo.
http://leoyuan.github.io
17 stars 2 forks source link

Node开发的一些经验分享 - npm包最佳实践 #34

Open LeoYuan opened 8 years ago

LeoYuan commented 8 years ago

当你跳进Node坑的那一天起,怎么组织一个好的包代码结构将是你面临的第一个挑战~

那么,一个好的npm包应该是由哪几方面构成呢?我想无非是以下几点:

  1. 包元数据描述清晰、完整;
  2. 包代码结构清晰,目录划分合理,代码组织结构清晰;
  3. 统一的编码风格;
  4. 遵守通行的版本化方案,比如semver;
  5. 完善的单元测试,再进一步的话,可以加上覆盖率测试;
  6. 良好的文档描述,这个是用户敢不敢用你的包的一个非常重要的衡量标准;

下面分别介绍以上几点:

1. 包元数据描述清晰、完整

npm包的元数据是通过包根目录下的package.json文件来描述的,首先我建议通读一下 npm pacakge.json 这篇文档后,再往下看~

挑出个人认为非常重要的几个来讲一下

目录划分方面,基本上可以遵循个比较好的实践,代码组织方面,还得靠你不断重构代码,遵循模块单一职责,函数单一职责,可复用等方面去考量,在该篇文章将不做重点讲述~

介绍一个比较好的目录划分实践

my-module
  - bin
  - lib
    - util
  - doc
  - test
  - index.js
  - package.json
  - .gitignore
  - .eslintrc

3. 统一的编码风格

统一的代码风格,有助于后续代码的维护,多人协作起来也更加顺畅,另外,这里的代码风格也包含了代码质量方面的一些检测,比如未定义变量,定义变量未使用,分支太多,分支嵌套太深,这些都应该在代码开发的时候就发现,并加以处理~

个人感觉,遵循一套严格的代码质量检测方案,是提高代码质量的一种最简单、性价比最高的方式,远比应用设计模式来重构代码要简单的多~

编码风格的工具有很多,比如霸道的jslint,花式风格的jscs,灵活的jshint,或者是兼顾风格、质量、可自定义的新贵eslint,以上工具你都可以去了解一下,不过个人还是推荐eslint~

eslint的配置可谓真是事无巨细,体位丰富,要读完所有rules估计得大半天了,不过读一遍感觉也是对质量意识的一种提高了~

当然,业界也有一些已经被人配置好的集合,比如 eslint-config-egg~

4. 遵守通行的版本化方案,比如semver

遵循一套社区版本的版本化方案,才能让别人放心使用你的包,否则,整天提心吊胆,不知道哪天应用就挂了,这种捉摸不定,我们还是敬而远之吧~

semver是一套语义化版本号标准,node-semver是这个标准的node版实现~

5. 完善的单元测试,再进一步的话,可以加上覆盖率测试

单元测试是最被大家忽视的一个必须流程,回想一下,你是否会在敲下npm publish时心慌气短,手脚发抖,究其原因就是测试不到位,不确定自己是否把场景测完全了,不确定是否影响了其他模块功能,不确定...

所以,我建议,对于一个好包,应该把单元测试当然必须的!

至少有以下几个好处:

  1. 保证当前模块场景测试完全;
  2. 保证不影响其他模块功能;
  3. 便于多人协作,否则谁敢改一行你的代码,可能致命啊!
  4. 节约时间,不用自己手动构建场景一个个测了,且不会遗漏任何场景;

单元测试的工具分为两部分,一是测试框架的选择,二是断言库的选择~

测试框架,我一般选择mocha,确实使用简单,功能强大,附上一段官方安利~

Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on GitHub.

断言库,分为两类,BDD && TDD

测试代码写起来像是在写spec,比如

espect(students).to.have.length(3);
foo.should.be.a('string');
foo.should.equal('bar');
foo.should.have.length(3);
beverages.should.have.property('tea').with.length(3);

测试代码的代码行更强一点,更像是代码,而不是语言

assert.typeOf(foo, 'string'); // without optional message
assert.typeOf(foo, 'string', 'foo is a string'); // with optional message
assert.equal(foo, 'bar', 'foo equal `bar`');
assert.lengthOf(foo, 3, 'foo`s value has a length of 3');
assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea');

选择BDD / TDD,这个还是交由你自己了解再决定用哪个好了,反正不管你选择哪个断言库,mocha基本上都能跟它们很好的搭配使用~

如何跟npm包结合起来,假如你理解了package.json中scripts / devDependencies字段的用法,我猜你已经知道答案了~

// package.json
{
  "devDependencies": {
    "chai": "^3.5.0",
    "mocha": "^2.4.5"
  },
  "scripts": {
    "test": "./node_modules/mocha/bin/mocha test"   // 更多mocha参数请查官方文档
  }
}

// shell
$ npm run test  // npm test也行

6. 良好的文档描述,这个是用户敢不敢用你的包的一个非常重要的衡量标准

这个你自己假如有选择过第三方库就应该有感受,假如一个库API文档都没写清楚,怎么敢用啊?!

---- eof ----

fengmk2 commented 8 years ago

👍