不求谌解

不求谌解

💻 Web Dev / Creative 💗 ⚽ 🎧 🏓
twitter
github
jike
email

変数名付けの芸術

これは最近翻訳した訳文1(私の 2 番目の訳文でもあります👏)で、記事の一部に少し変更を加え、元の文に基づいていくつかの内容を追加しました。誤解を招かないことを願っています。楽しんでください!

コンピュータサイエンスの分野で難しいことといえば、キャッシュの無効化(cache invalidation)と命名の問題(naming things)だけです。—— Phil Karlton

命名については、確かに時には非常に難しいことがあります。しかし、それを研究するためにエネルギーを費やす価値があります。振り返ってみると、以前にこのようなコードを見たことがありますか?

const convertObj = (x, y, z) => {
    const k = Object.keys(x);
    return k.map((key) => {
        return {
            [y]: key,
            [z]: x[key],
        }
    });
}

あなたはすぐにそれが何をしているのか分かりますか?もちろん、行ごとにこのコードを読み終えた後には、それが表現しようとしていることを理解するかもしれません。しかし、このコードの変数の命名がもっと優雅であれば、この内容を理解するのがずっと簡単になるでしょう。

良い変数名は非常に重要です。特に動的型付け言語では、すでに定義された変数の基本型を使ってその変数の正確な意味を理解することができません。しかし、動的型付けの言語で良い命名方法を使用できれば、コードは静的型付けの言語よりも読みやすくなります。

次に、命名方法に関する基本的なルールをいくつか共有します。これは私のこれまでの経験に基づいています。変数の異なる基本型を通じて、いくつかの例を比較してみましょう。まずは配列から始めましょう。

配列#

配列オブジェクトは順序付きデータの集合であり、各項目の基本型は大体同じです。配列には複数の変数値が含まれているため、変数の命名は意味のある複数形であるべきです。

// とてもbadでとてもsadでとてもdrama
const fruit = ['apple', 'banana', 'cucumber'];
// まあまあ
const fruitArr = ['apple', 'banana', 'cucumber'];
// まあまあ良い
const fruits = ['apple', 'banana', 'cucumber'];
// とても良い - "names"は配列の内容が文字列(strings)であることを示唆しています
const fruitNames = ['apple', 'banana', 'cucumber'];
// 優雅
const fruits = [{
    name: 'apple',
    genus: 'malus'
}, {
    name: 'banana',
    genus: 'musa'
}, {
    name: 'cucumber',
    genus: 'cucumis'
}];

ブール値#

ブール型には 2 つの値、trueまたはfalseしかありません。変数名には『is』、『has』または『can』を接頭辞として使用すると、読者が変数の型を理解するのに役立ちます。

// bad
const open = true;
const write = true;
const fruit = true;

// good
const isOpen = true;
const canWrite = true;
const hasFruit = true;

述語関数(この関数はブール値を返す)に出会ったとき、具名関数の後に変数を命名するのは少し面倒です。

const user = {
  fruits: ['apple']
}
const hasFruit = (user, fruitName) => {
  user.fruits.includes(fruitName)
}
// この時、ブール変数をどう命名すべきでしょうか?
const x = hasFruit(user, 'apple');

すでに関数名にhasの接頭辞を付けているため、hasProjectPermissionのように x というブール変数を命名することはできません。この場合、hasFruitという関数にcheckまたはgetを付け加えて述語 (has) を修飾することができます。

const checkHasFruit = (user, fruitName) => {
  user.fruits.includes(fruitName)
}
const hasFruit = checkHasFruit(user, 'apple');

数字#

数字型については、数字を表す単語を考えてみてください。例えば、maximumminimumtotalなどです。

// bad
const pugs = 3;
// good
const minPugs = 1;
const maxPugs = 5;
const totalPugs = 3;

関数#

関数は動詞と名詞を組み合わせた方法で命名するべきです。その関数がオブジェクトのプロトタイプ上で何らかの動作を引き起こす場合、その名前はそれを反映するべきです。actionResourceは参考にすべき命名形式です。例えば:getUser

// bad
userData(userId);
userDataFunc(userId);
totalOfItems(items);
// good
getUser(userId);
calculateTotal(items);

通常、私はtoを関数名の接頭辞として使用して、変数の値を変換することを示します。

// 私はこれが好きです
toDollors('euros', 20);
toUppercase('a string')

子項目を反復処理する際、私はこの慣用的な命名方法をよく使用します。関数に引数として受け取るときは、配列名の単数形を使用するべきです。

// bad
const newFruits = fruits.map(x => {
  doSomething(x);
});
// good
const newFruits = fruits.map(fruit => {
  doSomething(fruit)
})

最初に戻る#

最初のコードをリファクタリングします。

const arrayToObject = (array, id, name) => {
  const arrayList = Object.keys(array);
  return arrayList.map((key) => {
      return {
          [id]: key,
          [name]: array[key]
      }
  });
}

自省#

// 以前の命名 => rsshubプロジェクト
// 1. 記事リストを取得
const list = $('.con_list li h3')
      .find('a')
      .map((i, e) => $(e).attr('href'))
      .get();
// 2. 取得した記事のURLにリクエストを送信
const res = await got.get(itemUrl);

// 命名を改善
const articleLists = $('.con_list li h3')
      .find('a')
      .map((i, list) => $(list).attr('href'))
      .get();

const responseData = await got.get(itemUrl);

Footnotes#

  1. 原文リンク

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。