不求谌解

不求谌解

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

変数名付けの芸術

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

コンピュータサイエンスの分野で難しいことは 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;

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

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

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

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. 原文リンク

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