Ragate JavaScriptコーディング規約
社内向けのドキュメントですが、ご質問やご意見等あればコメント大歓迎です!
はじめに
Ragate株式会社では、エンジニアを募集しています!
https://recruit.ragate.co.jp/
コーディング規約の規約
- 規約で縛りすぎない(エンジニア上級者にとって細かすぎる規約は足枷でしかなく、開発スピードが落ち、やる気も損ねるため)
- それぞれの項目に、「なぜこの規約を設定するのか」という目的(
GOAL
)を書く - 各項目には
MUST
かSHOULD
をラベリングする -
MUST
は必ず守る規約 -
SHOULD
はできれば守ってほしい推奨項目 - なるべく規約の例をコードで書き示す
- 個人的な好みではなく合理性を追求する
命名
GOAL
命名規則を統一し、直感的に分かりやすく命名することで、可読性を向上させる
ケース
MUST
変数や関数の名前はキャメルケース
const date = new Date()
function startCoding () {}
MUST
定数の名前は全て大文字
const WIDTH = 123
SHOULD
ENUMまたはENUMのような機能を持つ変数の値は全て大文字
const mode = 'ADMIN'
SHOULD
クラスやVueコンポーネントの名前はパスカルケース
SHOULD
ファイル名はキャメルケース(クラスやVueコンポーネントの定義ファイルはパスカルケース)
class UserReport {}
品詞/文法
MUST
変数や関数の名前は英語の文法的に問題ない範囲で命名する
MUST
変数名は名詞
MUST
関数名は動詞から始める
MUST
単語を略さない(誰もが分かる略語を使うのはOK)
SHOULD
名前は短く(30文字以上はできるだけ避ける)
const createdDate = new Date()
function startCoding () {}
MUST
配列の変数名は複数形
const users = []
SHOULD
真偽値の変数名はis/has/canのいずれかから始める
SHOULD
真偽値の変数名にflgやflagという単語を使わない
const user = {
isGood: true,
hasCar: true,
canDrive: false,
}
基本文法
GOAL
基本文法の書き方を統一し、ミスを防ぐような書き方をすることで、可読性を向上させる
SHOULD
末尾にセミコロンを入れない
SHOULD
なるべくletではなくconstで変数定義する
const hoge = 'fuga'
SHOULD
オブジェクト定義時などに末尾にカンマを入れる
SHOULD
インデント数を統一する(トレンド的な観点ではスペース2個が一般的)
const user = {
isGood: true,
hasCar: true,
canDrive: false,
}
SHOULD
三項演算子はネストしない(見づらい)
// 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
波括弧の開始「{」は行の最後に書き、終了は「}」は行の最初に書く
function startCoding () {
return 123
}
配列
GOAL
配列操作の書き方を統一し、分かりやすく、かつDRYに書くことで、可読性を向上させ、不具合を防ぐ
for
SHOULD
非常にシビアな動作スピードを求められる場面以外ではforを使わない
// 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()**を使う
// 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()**を使う
// 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による変数定義は同じ関数内でたくさん使わない(変数のスコープが広くなりバグの温床となるため)
// 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を効果的に使うことで、不具合を防ぎ、可読性を向上させる
SHOULD
オブジェクトがundefinedやnullになる可能性がある場合は**_.get()**を使う
const user = undefined
// Bad
user.hoge // Error
// Good
_.get(user, 'hoge') // Not Error
SHOULD
配列がundefinedやnullになる可能性がある場合は**_.map()**を使う
SHOULD
mapだけでなくforEachやreduce等も同様
const users = undefined
// Bad
users.map(user => console.log(user)) // Error
// Good
_.map(users, user => console.log(user)) // []
SHOULD
配列がundefinedやnullになる可能性がある場合はlengthではなく**_.size()**を使う
const users = undefined
// Bad
users.length // Error
// Good
_.size(users) // 0
SHOULD
変数を定義しすぎず**_.chain()**を活用する(変数定義が多いとスコープが汚染され、不具合の温床となる)
// 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/