编码风格

在阅读完以下内容后,你将学习到:

  1. 规范编码风格的意义
  2. 这里推荐的javascript编码风格
  3. 如何通过ESLint自动检查代码风格
  4. Meteor项目特有场景中的编码风格建议(诸如Methods, publications...)

保持编码风格的优势

Countless hours have been spent by developers throughout the years arguing over single vs. double quotes, where to put brackets, how many spaces to type, and all kinds of other cosmetic code style questions. These are all questions that have at best a tangential relationship to code quality, but are very easy to have opinions about because they are so visual. 在无边的岁月中,程序员们为了争论 单引号与双引号之战,如何安装括号之争,以及空格数量等诸多类似的问题 相争不知多少春秋。这一系列的问题好似和编码的质量无甚紧要的联系,但是容易引起纷争,因为他们是可视化的。

While it's not necessarily important whether your code base uses single or double quotes for string literals, there are huge benefits to making that decision once and having it be consistent across your organization. These benefits also apply to the Meteor and JavaScript development communities as a whole. 对于你的编码是用单引号还是用双引号来编写字符,这问题本身不能成为关键性因素。但是提前确认编码规范、保证编码规范在项目中的统一书写却能带来莫大的收获。这些收获同时保障了所有用Meteor以及JavaScript的群体成为一个整体。

易于阅读

The same way that you don't read English sentences one word at a time, you don't read code one token at a time. Mostly you just look at the shape of a certain expression, or the way it highlights in your editor, and assume what it does. If the style of every bit of code is consistent, that ensures that bits of code that look the same actually are the same - there isn't any hidden punctuation or gotchas that you don't expect, so you can focus on understanding the logic instead of the symbols. One example of this is indentation - while in JavaScript, indentation is not meaningful, it's helpful to have all of your code consistently indented so that you don't need to read all of the brackets in detail to see what is going on. 正如你不必一字一字地阅读所有的句子,同样不需要这样阅读编码。通常你只是关注下一部分编码表达的大意,他在你编辑器中highlight的部分,以及大约起到的作用。在保证所有的编码都遵从编码规范的情况下,所有的编码从整体到细节都是统一的,任何你不期望出现的隐形符号或陷阱都不存在,这样才能让你可以把关注集中于理解逻辑上,而非语法表述。其中的一个例子是编码的缩进。对于JavaScript编码的缩进不存在任何语言上的意义,但是在你所有的编码中保证统一的缩进却保证了你不需要阅读所有的细节而是关注在编码运行的整体思路。

// This code is misleading because it looks like both statements
// are inside the conditional.
// 这段编码带有误导性因为看起来像在同一条件下执行了两条状态。

if (condition)
  firstStatement();
  secondStatement();
// Much clearer!
// 干净的写法
if (condition) {
  firstStatement();
}

secondStatement();

自动化错误检测

Having a consistent style means that it's easier to adopt standard tools for error checking. For example, if you adopt a convention that you must always use let or const instead of var, you can now use a tool to ensure all of your variables are scoped the way you expect. That means you can avoid bugs where variables act in unexpected ways. Also, by enforcing that all variables are declared before use, you can easily catch typos before even running any code! 保证统一的编码规范也意味着易于适应错误检测的现代化工具。例如,假如你惯性地坚持用letconst而不再用var,那么你现在可以用工具确认你所有的变量作用域按你所希望的出现。那意味着你将避免一些因为变量而引起的不期望的错误。同样工具能够保证你所有的变量在用以前都被定义过,让你很容易地在运行编码前发现错误。

深度理解

It's hard to learn everything about a programming language at once. For example, programmers new to JavaScript often struggle with the var keyword and function scope. Using a community-recommended coding style with automatic linting can warn you about these pitfalls proactively. This means you can jump right into coding without learning about all of the edge cases of JavaScript ahead of time. 短时间理解一门语言的所有内容绝非易事。例如,对于一个刚涉足JavaScript的编程者,经常纠结于var和函数作用域。通过使用社区性同有的编码规范同时用自动检测工具可以来主动提醒你有哪些隐患问题。这意味着你可以早日进行编程而不用在了解了JavaScript所有边缘案例再着手编程。

As you write more code and come up against the recommended style rules, you can take that as an opportunity to learn more about your programming language and how different people prefer to use it. 若你编写了大量的编码之后,想要起身反对现有的编码规范,你可以把这作为一个契机,来进一步提高你的编程语言同时了解不同大众所期望的编码规范。

关于JavaScript编码规范

Here at Meteor, we strongly believe that JavaScript is the best language to build web applications, for a variety of reasons. JavaScript is constantly improving, and the standards around ES2015 have really brought together the JavaScript community. Here are our recommendations about how to use ES2015 JavaScript in your app today. 作为Meteor Developer的一员,我们有大量理由坚信JavaScript是构建Web Applications最好的语言。JavaScript保持着不断进步,ES2015的标准化也已经在JavaScript中迎来了现世之行。通过ES2015来构建你的应用是我们所共同推荐的。

Use the `ecmascript` package

ECMAScript, the language standard on which every browser's JavaScript implementation is based, has moved to yearly standards releases. The newest complete standard is ES2015, which includes some long-awaited and very significant improvements to the JavaScript language. Meteor's ecmascript package compiles this standard down to regular JavaScript that all browsers can understand using the popular Babel compiler. It's fully backwards compatible to "regular" JavaScript, so you don't have to use any new features if you don't want to. We've put a lot of effort into making advanced browser features like source maps work great with this package, so that you can debug your code using your favorite developer tools without having to see any of the compiled output.

The ecmascript package is included in all new apps and packages by default, and compiles all files with the .js file extension automatically. See the list of all ES2015 features supported by the ecmascript package.

To get the full experience, you should also use the es5-shim package which is included in all new apps by default. This means you can rely on runtime features like Array#forEach without worrying about which browsers support them.

All of the code samples in this guide and future Meteor tutorials will use all of the new ES2015 features. You can also read more about ES2015 and how to get started with it on the Meteor Blog:

Follow a JavaScript style guide

We recommend choosing and sticking to a JavaScript style guide and enforcing it with tools. A popular option that we recommend is the Airbnb style guide with the ES6 extensions (and optionally React extensions).

用ESLint检查你的编码

"Code linting" is the process of automatically checking your code for common errors or style problems. For example, ESLint can determine if you have made a typo in a variable name, or some part of your code is unreachable because of a poorly written if condition.

We recommend using the Airbnb eslint configuration which verifies the Airbnb styleguide.

Below, you can find directions for setting up automatic linting at many different stages of development. In general, you want to run the linter as often as possible, because it's the fastest and easiest way to identify typos and small errors.

安装以及运行ESLint

To setup ESLint in your application, you can install the following npm packages:

meteor npm install --save-dev eslint eslint-plugin-react eslint-plugin-meteor eslint-config-airbnb

Meteor comes with npm bundled so that you can type meteor npm without worrying about installing it yourself. If you like, you can also use a globally installed npm command.

You can also add a eslintConfig section to your package.json to specify that you'd like to use the Airbnb config, and to enable ESLint-plugin-Meteor. You can also setup any extra rules you want to change, as well as adding a lint npm command:

{
  ...
  "scripts": {
    "lint": "eslint .",
    "pretest": "npm run lint --silent"
  },
  "eslintConfig": {
    "plugins": [
      "meteor"
    ],
    "extends": [
      "airbnb/base",
      "plugin:meteor/recommended"
    ],
    "rules": {}
  }
}

Use "airbnb/base" for a normal ecmascript-based config and "airbnb" in a React project.

To run the linter, you can now simply type:

meteor npm run lint

For more details, read the Getting Started directions from the ESLint website.

Integrating with your editor

Linting is the fastest way to find potential bugs in your code. Running a linter is usually faster than running your app or your unit tests, so it's a good idea to run it all the time. Setting up linting in your editor can seem annoying at first since it will complain often when you save poorly-formatted code, but over time you'll develop the muscle memory to just write well-formatted code in the first place. Here are some directions for setting up ESLint in different editors:

Sublime Text

You can install the Sublime Text packages that integrate them into the text editor. It's generally recommended to use Package Control to add these packages. If you already have that setup, you can just add the these packages by name; if not, click the instructions links:

To get proper syntax highlighting, go to a .js file, then select the following through the View dropdown menu: Syntax -> Open all with current extension as... -> Babel -> JavaScript (Babel). If you are using React .jsx files, do the same from a .jsx file. If it's working, you will see "JavaScript (Babel)" in the lower right hand corner of the window when you are on one of these files. Refer to the package readme for information on compatible color schemes.

A side note for Emmet users: You can use \ to expand HTML tags in .jsx files, and it will correctly expand classes to React's "className" property. You can bind to the tab key for this, but you may not want to.

Atom

Using ESLint with Atom is simple. Just install these three packages:

apm install language-babel
apm install linter
apm install linter-eslint

Then restart (or reload by pressing Ctrl+Alt+R / Cmd+Opt+R) Atom to activate linting.

WebStorm

WebStorm provides these instructions for using ESLint. After you install the ESLint Node packages and set up your package.json, just enable ESLint and click "Apply". You can configure how WebStorm should find your .eslintrc file, but on my machine it worked without any changes. It also automatically suggested switching to "JSX Harmony" syntax highlighting.

Enable ESLint here.

Linting can be activated on WebStorm on a project-by-project basis, or you can set ESLint as a default under Editor > Inspections, choosing the Default profile, checking "ESLint", and applying.

Meteor code style

The section above talked about JavaScript code in general - you can easily apply it in any JavaScript application, not just with Meteor apps. However, there are some style questions that are Meteor-specific, in particular how to name and structure all of the different components of your app.

Collections

Collections should be named as a plural noun, in PascalCase. The name of the collection in the database (the first argument to the collection constructor) should be the same as the name of the JavaScript symbol.

// Defining a collection
Lists = new Mongo.Collection('Lists');

Fields in the database should be camelCased just like your JavaScript variable names.

// Inserting a document with camelCased field names
Widgets.insert({
  myFieldName: 'Hello, world!',
  otherFieldName: 'Goodbye.'
});

Methods and publications

Method and publication names should be camelCased, and namespaced to the module they are in:

// in imports/api/todos/methods.js
updateText = new ValidatedMethod({
  name: 'todos.updateText',
  // ...
});

Note that this code sample uses the ValidatedMethod package recommended in the Methods article. If you aren't using that package, you can use the name as the property passed to Meteor.methods.

Here's how this naming convention looks when applied to a publication:

// Naming a publication
Meteor.publish('lists.public', function listsPublic() {
  // ...
});

Files, exports, and packages

You should use the ES2015 import and export features to manage your code. This will let you better understand the dependencies between different parts of your code, and it will be easy to know where to look if you need to read the source code of a dependency.

Each file in your app should represent one logical module. Avoid having catch-all utility modules that export a variety of unrelated functions and symbols. Often, this can mean that it's good to have one class, UI component, or collection per file, but there are cases where it is OK to make an exception, for example if you have a UI component with a small sub-component that isn't used outside of that file.

When a file represents a single class or UI component, the file should be named the same as the thing it defines, with the same capitalization. So if you have a file that exports a class:

export default class ClickCounter { ... }

This class should be defined inside a file called ClickCounter.js. When you import it, it'll look like this:

import ClickCounter from './ClickCounter.js';

Note that imports use relative paths, and include the file extension at the end of the file name.

For Atmosphere packages, as the older pre-1.3 api.export syntax allowed more than one export per package, you'll tend to see non-default exports used for symbols. For instance:

// You'll need to deconstruct here, as Meteor could export more symbols
import { Meteor } from 'meteor/meteor';

// This will not work
import Meteor from 'meteor/meteor';

Templates and components

Since Spacebars templates are always global, can't be imported and exported as modules, and need to have names that are completely unique across the whole app, we recommend naming your Blaze templates with the full path to the namespace, separated by underscores. Underscores are a great choice in this case because then you can easily type the name of the template as one symbol in JavaScript.

<template name="Lists_show">
  ...
</template>

If this template is a "smart" component that loads server data and accesses the router, append _page to the name:

<template name="Lists_show_page">
  ...
</template>

Often when you are dealing with templates or UI components, you'll have several closely coupled files to manage. They could be two or more of HTML, CSS, and JavaScript files. In this case, we recommend putting these together in the same directory with the same name:

# The Lists_show template from the Todos example app has 3 files:
show.html
show.js
show.less

The whole directory or path should indicate that these templates are related to the Lists module, so it's not necessary to reproduce that information in the file name. Read more about directory structure above.

If you are writing your UI in React, you don't need to use the underscore-split names because you can import and export your components using the JavaScript module system.

results matching ""

    No results matching ""