質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

オブジェクトの変数名、どのようにしていますか?

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 4
  • VIEW 8,506

score 166

レジ会計のプログラムを作っております。

以下のオブジェクト変数は、バーコード番号をキーとして商品の情報を取得出来るようにしております。

以下のオブジェクト変数の名前をどうするべきかが分かりません。
回答者様であれば、どのようにしていますか?

いつも、ついつい付けてしまう名前は
’itemObjs’です。
これは、後でlodashのforEachで回すことを考えておりますので、
配列風に語尾にsを付けています。
ただ、名前的に配列と見分けがつかないので、悩んでおります。

const noName = {
  "1": {
    barcode: 1,
    name: "name_1",
    taxInPrice: 123,
    category:'drink',
  },
  "2": {
    barcode: 2,
    name: "name_2",
    taxInPrice: 108,
    category:'drink',
  },
  "3": {
    barcode: 3,
    name: "name_3",
    taxInPrice: 154,
    category:'food',
  },
};

const exampleBarcode = 1;
const name_1_taxInPrice = noName[exampleBarcode].taxInPrice;

//lodashのサンプルコード、カテゴリー毎に商品を分ける。
const eachCategoryItemsObj = {'drink':[], 'food':[]};

_.forEach(noName, (itemObj) => {
  eachCategoryItemsObj[itemObj.category].push(itemObj);
});
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+7

 変数名

配列([])に変更して、

  • itemList
  • productList
  • goodsList

または、new Map に変更して、

  • itemMap
  • productMap
  • goodsMap

 配列風の名前

配列風に語尾にsを付けています。

私は「末尾に s を付ける名前」を避けるようにしています。
理由は「item と items を一目で見分けられないから」です。
item と itemList なら違いが明確になります。

ただ、名前的に配列と見分けがつかないので、悩んでおります。

個人的には配列のように見えるので、配列を使いたくなります。
バーコードはオブジェクト内に含まれており、バーコードをキーにする理由が明確でない為です。
バーコードをキーにする方が都合が良いのであれば、new Map を選択します。

 変数名の末尾にsを付ける命名規則の是非

変数名の末尾に s を付ける事で複数形である事を示せますが、実際のところ、複数形の中にも種類があります。

/**
 * 末尾に s を付ける(複数形)
 */
var items = [{barcode: 1, name: "name_1"}, {barcode: 2, name: "name_2"}, {barcode: 3, name: "name_3"}];
var items = new Map([[1,{barcode: 1, name: "name_1"}], [2,{barcode: 2, name: "name_2"}], [3,{barcode: 3, name: "name_3"}]]);

/**
 * 末尾にユニークな名前を付ける
 */
var itemList = [{barcode: 1, name: "name_1"}, {barcode: 2, name: "name_2"}, {barcode: 3, name: "name_3"}];
var itemMap = new Map([[1,{barcode: 1, name: "name_1"}], [2,{barcode: 2, name: "name_2"}], [3,{barcode: 3, name: "name_3"}]]);

前者は配列と new Map を区別できませんが、後者は区別できます。
「末尾に s を付ける命名規則」が通用するのは、次のどちらかのルールが課せられている為です。

  • 複数形が一種類しか存在しない
  • 複数形は配列であるとコーダが決め打ちしている(この場合、new Map は itemMap のように命名して区別する)

前者はコードリーディングする人がオブジェクト初期化部分のコードまで追いかけないと、変数の中身を確認できない事を意味します。
後者はコーダが勝手に「複数形は配列」と決め打ちしていますが、コードリーディングする人がそのルールとは限りません。
複数形である以上、配列以外のオブジェクトにも s を付ける可能性があります。
例えば、DOMノードを使ったコードでも s を使った命名規則を見かける事があります。

var imgs = document.getElementsByTagName('img');

一見、このコードは問題ないように見えますが、変数 imgs に格納されるのは HTMLCollection です。
DOMの複数形には NodeList があり、「querySelectorAll() で参照した変数(NodeList)」と「getElementsByTagName で参照した変数(HTMLCollection)」を区別できない、という問題があります。
両者を区別するには、次のように書きます。

var imgCollection = document.getElementsByTagName('img'); // HTMLCollection
var imgList = document.querySelectorAll('img');           // NodeList

HTMLCollection は live ですが、NodeList は live ではない、という性質の違いもあり、名前を区別する事で性質の違いも明確となります。

ところで、DOM Interface には Node がありますが、複数形は Nodes ではなく、NodeList もしくは HTMLCollection である点に気が付いたでしょうか。
Nodes と命名すると、「Node の複数形」が一つで決め打ちされてしまう為、ユニークな単語を末尾に着ける事で両者を区別しています。
英語でも Interface 名、コンストラクタ名などには末尾に s を付ける文化はないように感じています。
少なくとも、私が今までに DOM の仕様書を読んだ中では、末尾に s を付けた Interface 名を見ていません。
これは後から複数形の種類が拡張されて増える可能性を踏まえて、ユニークな名前を付ける配慮があるのだと思います。

DOM 上で「単語の末尾に s を持つプロパティ/メソッド」には次のものがあります。

  • getElementsByTagName (HTMLCollection を返す)
  • Node#childNodes (HTMLCollection を返す)
  • HTMLFormElement#elements (HTMLFormControlsCollection を返す)

これもいろいろと「決め打ち」しているからできる事です。

  • 同様の「他の複数形式(NodeList等)で返す」機能が存在しない
  • 返り値を決め打ちしている

コーダは名前からではなく、仕様書から各APIが持つ返り値を確認する必要があります。

 new 演算子で生成されるオブジェクトの変数名

原則としてコンストラクタから生成されるオブジェクトはコンストラクタ名を反映したものであるべき、と考えています。

var object = new Object;
var array = new Array;
var map = new Map;

ただし、new Objectnew Array だけは例外で、この2つは利用用途が広範で要素の中身が重要な為、コンストラクタ名だけでは「内容を表す名前」として不十分であり、要素に準じた名前を付けるようにしています。
また、DOMの要素ノード系も省略形を使う事が多いですね。

/**
 * 厳密系 (Interface HTMLParagraphElement)
 */
var htmlParagraphElement = document.createElement('p');

/**
 * 省略系 (tagName)
 */
var p = document.createElement('p');

DOMの Interface 名を基にするなら、HTMLParagraphElement に準じた名前にすべきですが、名前が長すぎるので tagName 準拠の名前にしています。

 更新履歴

  • 2017/11/19 13:11 「変数名の末尾にsを付ける命名規則の是非」「new 演算子で生成されるオブジェクトの変数名」を追記

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/20 01:08

    To: LLman さん
    > 日本語を混ぜることが、下に合わせることだ、とも思わないんですよね。
    そうですね。私もそう思います。

    実際に書いてみたところでは、「和英混在」「日本語表現の揺らぎ」「map,objectの日本語訳」など、別の部分で問題を感じました。
    https://jsfiddle.net/0Ln7c2jj/1/
    また、前例が少ないゆえにコードリーディング時に戸惑う事が想定されるので、他の人に引き継ぐ可能性があるコードには採用しづらい側面がありますね。
    しっかりとした命名規則を確保する為には、独自のコーディング規約を作る必要がありそうですが、引き継がれる方はコーディング規約込みでコードを読まなければならないので読み解くのに苦労します。

    キャンセル

  • 2017/11/20 22:53

    > thisnk49さん
    追記部分読みました。
    おっしゃる通り、差別化の為に複数形よりList、Collection等を用意する方がふさわしいケースが多々あるという点納得しました。
    残った疑問点はここで言っても仕方ないものもありますのでオフトピ気味なものですが、一応共有。

    > var imgs = document.getElementsByTagName('img');
    getElementByIdはメソッド名通りElementを返しますが、
    仮にも「getElements」を冠するメソッドが「HTMLCollection」を返すのは詐欺に思えますね。
    かと言って名前だけElementsの配列モドキインスタンスが返ってきても困るわけですが…

    > 複数形の中にも種類があります
    普通は配列、ハッシュくらいしか存在しませんよね。
    JavaScriptに限ってはDOM系にかぎらず配列モドキが至る所に散見されますので、
    プロトタイプ汚染に備えて山のように作らざるを得なかった等の歴史的な背景があるのだろうと思います。

    > LLmanさん
    > 「items」より「itemList」の方が情報量が多いですね。

    情報に於いて大は小を兼ねません。
    大は小を兼ねるなら、同じことをやるコードの行数や1行の文字数は多ければ多い程良いはずです。
    上手く表現するListやCollectionは目からウロコが落ちましたが、情報量が増えるリスクとセットです。

    単なる説明不足に見えるitemsですが、
    この関数やメソッドの中なら文脈的に「○○から××に加工されて、△△で絞り込まれた」結果のitemsと説明出来るはず…といった風に涙ぐましい努力の積み重ねで削られシンプルになった結晶です。

    便利だからとlistとcollectionを足すって悪魔の囁きじゃないですか。
    私としては設計がシンプルになるようにまず頑張って、
    itemsじゃ曖昧になる困ったという場面でのみListやCollectionを解禁していこうと考えています。

    キャンセル

  • 2017/11/20 23:39

    To: miyabi-sun さん
    「items vs itemList」の構図はショートコーディングをとるか、厳密な名前をとるか、のトレードオフの関係なのだと思います。
    array.length を変数に格納する場合に、変数名を l, len, length のどれを採用するか、と同じです。
    判断基準は人それぞれの主観になりますので、唯一解はありません。

    (※以下、個人の見解です)
    私としては変数名は一度宣言すれば、2回目以降はエディタが補完してくれるので、タイプ数を減らす事に神経を使う必要はないと考えています。
    items は複数形を意識する為に「item + s」のように分解して解釈しますが、「item + List」も2つの要素に分解する為、コードリーディング時のスピードも、個人的には変わりません。
    (items はコーディングする時にはいいのですが、コードリーディングする時には名前から種類を判断できず、種類が何かを考える必要がある点で、余計に頭を使う必要があるデメリットがあるように感じています。)

    > 私としては設計がシンプルになるようにまず頑張って、itemsじゃ曖昧になる困ったという場面でのみListやCollectionを解禁していこうと考えています。
    「不要な情報」を削ればシンプルになりますが、「必要な情報」を削る事はシンプルとはいえません。
    では、不要/必要の判断基準をどこに持っていくのか、というところが課題だと思いました。
    結局は主観に依るところが大きいと思いますが…。

    キャンセル

+4

- 以下のオブジェクト変数は、バーコード番号をキーとして商品の情報を取得出来るようにしております。
- これは、後でlodashのforEachで回すことを考えておりますので、

このitemsってそもそも何度も作り直すのですか?
データ構造から推測するに、最初に1回作っておしまいだと思うのですが……

初手は配列、使う段階になってインデックス付きのオブジェクトを生成すれば綺麗に片付きますね。
itemsの配列が数千の要素数にならない限りgroupBy使うのが綺麗に表現できます。

const items = [
  {
    barcode: 1,
    name: "name_1",
    taxInPrice: 123,
    category:'drink',
  },
  {
    barcode: 2,
    name: "name_2",
    taxInPrice: 108,
    category:'drink',
  },
  {
    barcode: 3,
    name: "name_3",
    taxInPrice: 154,
    category:'food',
  },
];
// バーコードはユニークだからitemsByBarcode1件の配列になるとは思うけど
const itemsByBarcode = _.groupBy(items, _.property('barcode'));
const itemsByCategory = _.groupBy(items, _.property('category'));

// ネストさせたらこんな感じか?(動作未検証)
const itemsByCategoryBarcode = _(items)
  .groupBy(_.property('category'))
  .map(it => _.groupBy(it, _.property('barcode')))
  .value();

各命名に関して

itemObjs

itemObjsは実体的にも論理的にも寄り添えてない存在に思えますね。
○○を元に区切る時はLodashのgroupByにあやかってitemByBarcodeという風に命名しています。

eachCategoryItemsObj

eachにはforEachと言った風に処理に着目することが多いですね。
なのでeachを見たら身構えます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/20 02:58

    ご回答ありがとうございます。
    itemsは、1回作るのみです。

    参考にさせて頂いた点
    命名規則は、ライブラリのメソッドを参考にする点。
    処理を連想させる名前を避ける点(コード下部まで命名チェック頂き、ありがとうございます。)
    的確なlodashの関数を発見して頂いた点(lodashのDocument,再度見直します。)

    エンジニア視点の貴重な意見を頂けました。
    どうも、ありがとうございました。

    補足
    とりあえず、まずは、Mapを使用させて頂いて作ることにしました。
    その後、groupBy試させて頂きます。

    const items = [...];

    const itemMap = new Map();

    items.forEach((item) => {
    itemMap.set(item.barcode, item);
    });

    キャンセル

  • 2017/11/20 02:58 編集

    .

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る