Ragate JavaScript Coding Rules

# Ragate JavaScriptコーディング規約

社内向けのドキュメントですが、ご質問やご意見等あればコメント大歓迎です！



## はじめに

Ragate株式会社では、エンジニアを募集しています！
https://recruit.ragate.co.jp/



## コーディング規約の規約

* 規約で縛りすぎない（エンジニア上級者にとって細かすぎる規約は足枷でしかなく、開発スピードが落ち、やる気も損ねるため）
* それぞれの項目に、「なぜこの規約を設定するのか」という目的（ `GOAL` ）を書く
* 各項目には `MUST` か `SHOULD` をラベリングする
* `MUST` は必ず守る規約
* `SHOULD` はできれば守ってほしい推奨項目
* なるべく規約の例をコードで書き示す
* 個人的な好みではなく合理性を追求する



## 命名

`GOAL` 命名規則を統一し、直感的に分かりやすく命名することで、可読性を向上させる

### ケース

`MUST` 変数や関数の名前は**キャメルケース**

```js
const date = new Date()
function startCoding () {}
```

`MUST` 定数の名前は**全て大文字**

```js
const WIDTH = 123
```

`SHOULD` ENUMまたはENUMのような機能を持つ変数の値は**全て大文字**

```js
const mode = 'ADMIN'
```

`SHOULD` クラスやVueコンポーネントの名前は**パスカルケース**
`SHOULD` ファイル名は**キャメルケース**（クラスやVueコンポーネントの定義ファイルは**パスカルケース**）

```UserReport.js
class UserReport {}
```

### 品詞/文法

`MUST` 変数や関数の名前は英語の文法的に問題ない範囲で命名する
`MUST` 変数名は**名詞**
`MUST` 関数名は**動詞**から始める
`MUST` 単語を**略さない**（誰もが分かる略語を使うのはOK）
`SHOULD` 名前は**短く**（30文字以上はできるだけ避ける）

```js
const createdDate = new Date()
function startCoding () {}
```

`MUST` 配列の変数名は**複数形**

```js
const users = []
```

`SHOULD` 真偽値の変数名は**is**/**has**/**can**のいずれかから始める
`SHOULD` 真偽値の変数名に**flg**や**flag**という単語を使わない

```js
const user = {
  isGood: true,
  hasCar: true,
  canDrive: false,
}
```



## 基本文法

`GOAL` 基本文法の書き方を統一し、ミスを防ぐような書き方をすることで、可読性を向上させる

`SHOULD` 末尾に**セミコロン**を入れない
`SHOULD` なるべくletではなく**const**で変数定義する

```js
const hoge = 'fuga'
```

`SHOULD` オブジェクト定義時などに**末尾にカンマ**を入れる
`SHOULD` **インデント数を統一**する（トレンド的な観点ではスペース2個が一般的）

```js
const user = {
  isGood: true,
  hasCar: true,
  canDrive: false,
}
```

`SHOULD` **三項演算子**はネストしない（見づらい）

```js
// Bad
const hoge = fuga <= 5 ? piyo < 0 ? 0 : baki > 0 ? baki : 99

// Good
let hoge = 99
if (fuga <= 5) {
  if (piyo < 0) {
    hoge = 0
  } else if (baki > 0) {
    hoge = baki
  }
}
```



## 関数

`GOAL` 関数の書き方を統一し、直感的に分かりやすく、かつDRYに書くことで、可読性を向上させ、ユニットテストを導入しやすくし、保守性を上げる

`MUST` 最小機能単位（**ユニットテストを書きやすい単位**）で関数を書く
`MUST` 関数一つあたりの**行数は少なく**（100行以内はMUST、10行以内がSHOULD）
`MUST` 一行あたりの**文字数は少なく**（200文字以内はMUST、80文字以内がSHOULD）
`SHOULD` 波括弧の開始「**{**」は行の最後に書き、終了は「**}**」は行の最初に書く

```js
function startCoding () {
  return 123
}
```



## 配列

`GOAL` 配列操作の書き方を統一し、分かりやすく、かつDRYに書くことで、可読性を向上させ、不具合を防ぐ

### for

`SHOULD` 非常にシビアな動作スピードを求められる場面以外では**forを使わない**

```js
// Bad
const array = ['hoge', 'fuga', 'piyo']
for (var i = 0; i < array.length; i++) {
  console.log(array[i])
}

// Good
array.map(value => console.log(value))
```

`SHOULD` 配列から新しい配列を生成する時は**Array.map()**を使う

```js
// Bad
const oldArray = ['hoge', 'fuga', 'piyo']
let newArray = []
oldArray.forEach((value, index) => {
  newArray.push(`${value}_${index}`)
})

// Good
const oldArray = ['hoge', 'fuga', 'piyo']
const newArray = oldArray.map((value, index) => {
  return `${value}_${index}`
})
```

`SHOULD` 配列からオブジェクトを生成する時は**Array.reduce()**を使う

```js
// Bad
const array = ['hoge', 'fuga', 'piyo']
const object = {}
array.forEach((value, index) => {
  object[value] = index
})

// Good
const array = ['hoge', 'fuga', 'piyo']
const object = array.reduce((obj, value, index) => {
  obj[value] = index
  return obj
}, {})
```



## 非同期処理

`GOAL` コードが複雑になりがちな非同期処理を見やすく書くことで、可読性を向上させる

### async/await

`SHOULD` 非同期処理はasync/awaitを使う
`SHOULD` awaitによる変数定義は**同じ関数内でたくさん使わない**（変数のスコープが広くなりバグの温床となるため）

```js
// Bad
const hoge = await getHoge()
const fuga = await getFuga(hoge)
const piyo = await getPiyo(fuga)
const baki = await getBaki(piyo)

// Good
const baki = await getHoge()
  .then(getFuga)
  .then(getPiyo)
  .then(getBaki)
```



## Lodash

`GOAL` [Lodash](https://lodash.com/docs/)を効果的に使うことで、不具合を防ぎ、可読性を向上させる

`SHOULD` オブジェクトがundefinedやnullになる可能性がある場合は**_.get()**を使う

```js
const user = undefined
// Bad
user.hoge // Error

// Good
_.get(user, 'hoge') // Not Error
```

`SHOULD` 配列がundefinedやnullになる可能性がある場合は**_.map()**を使う
`SHOULD` mapだけでなくforEachやreduce等も同様

```js
const users = undefined
// Bad
users.map(user => console.log(user)) // Error

// Good
_.map(users, user => console.log(user)) // []
```

`SHOULD` 配列がundefinedやnullになる可能性がある場合はlengthではなく**_.size()**を使う

```js
const users = undefined
// Bad
users.length // Error

// Good
_.size(users) // 0
```

`SHOULD` 変数を定義しすぎず**_.chain()**を活用する（変数定義が多いとスコープが汚染され、不具合の温床となる）

```js
// Bad
const users = [
  {name: 'hoge', age: 25},
  {name: 'fuga', age: 31},
  {name: 'piyo', age: 48},
]
const over30Users = users.filter(user => user.age >= 30)
const over30UsersCount = over30Users.length

// Good
const over30UsersCount = _.chain(users)
  .map('age')
  .filter(age => age >= 30)
  .size()
  .value()
```



## あとがき

社内向けのドキュメントですが、ご質問やご意見等あればコメント大歓迎です！

また、Ragate株式会社では、エンジニアを募集しています！（2回目）
採用サイトもかなりこだわっているので是非一度ご覧になってみてください！
https://recruit.ragate.co.jp/