日本語プログラミングする時の変数名を探る（データベースシステムとの関係）

# はじめに

 だいぶ前、日本語プログラミング言語プロデルの開発者@jpl_produireさんが、「[日本語プログラミングする時の名前の付け方を考える](https://qiita.com/jpl_produire/items/7fe130f1fc7a41efd268)」という記事で、件名のとおりの問題について検討されています。このあたりの問題について改めて考察してみたいと思います。

# 英字プログラミング言語ユーザーからみた日本字プログラミングの不便さ
 このあたりは（この見出しのような表現ではないのですが）jpl_produireさんがまとめられているので、本記事でもその要点を使わせていただきます。

**・クラス名とインスタンス名**
**・配列**
**・一時変数**

ひとによっては実装言語記述時に、日本字をカナ漢字変換して打ち込むのがやだという方もいらっしゃるようですが、この記事ではある程度ソースコードのなりとして、一度宣言された変数名や関数名はコピペして使うことを想定していますので、そのような「不便さ」については言及いたしません。

## どの程度の冗長表記を好むか許容するかは書き手の個人の感覚の他、テキストの記述目的による（読み手の想定）
本記事の特徴は、日本語プログラミング（言語）を通常のソフトウェア実装だけではなく、その前工程の設計工程（モデリングや内部ロジック記述）でも構造化された日本語として使用することを想定することにあります。

従いまして、私の思うところとしての許容範囲の想定にはテキスト（ソースコード）の記述目的という条件が存在します。

# 設計工程でよく使われる構造化言語
話はいったん本題から離れるようですが、業務システム経験者以外の方も読者想定するため、業務システム開発の現場で、設計工程でもよく使われる構造化言語について触れさせてください。それはなにか？

##  構造化照会言語SQL
データベース照会言語のSQLです。今日のプログラミング言語上ではC#のLINQなどの登場により直接書かないケースも増えてきていますが、リレーショナルデータベースを使用したシステムでは、アプリケーション部分を実装しているプログラミング言語とほぼ確実に併用されているデータベース操作言語です。（どこにこのソーステキストをおくかは別として）

# 設計上のSQLと実装上のSQL
これはデータベースのテーブルや列にどのような文字が使われるかということに大きくかかわります。プログラミング言語と同様、今日のリレーショナルデータベースは日本語字をスキーマに使えるようにはなってきています。しかし、現在運用されている一定規模以上の多くの実データベースのテーブル名、列名などは英字のままでしょう。

## 物理名が英字の場合
SQLは基本的に半角空白の分かち書きのため、英字のテーブル名、列名などの場合、ある程度長い名称になってくると、半角空白以外の区切り文字が必要になってきます。それは多くの場合アンダスコアで、アンダスコアで区切ることを「スネークケース」と言います。

また、このテーブル名や列名を英字プログラミング言語で使用する場合、アンダスコアがシステムトークンとなっている言語もあり、そうでなくもて、長い変数名は大文字を単語先頭に使用する「キャメルケース」に変換することが一般的です。（フレームワーク側で自動的に変換させる場合が多い）

※実装言語側は変数名の最初の１文字を小文字のままとするか大文字とするか（ローワーキャメルまたはアッパーキャメル）で、別途ルール化されている場合があります。（推奨または必須）


## 論理設計レベルのデータベースでは日本字が使われる場合が多い
ユビキタス言語や業務用語集との関係で、物理名に日本字が使われていなくても論理設計レベルのデータベースでは日本字がよく使われています。

この影響もあってアプリケーションの内部設計情報に相当するSQLの情報ではテーブル名、列名に日本字がそのまま使われる場合も多く、そのような設計情報ではSQL構文がそのまま使われていることも多いです。（多少表形式にした方が見やすい場合もあります。）

下記は日本字が使われたSQLの例です。

```SQL
SELECT 
    LN.言語ID
    ,LN.言語名
    ,LN.よみがな
    ,DLN.開発言語ID
    ,DLN.開発言語名 
FROM 言語名 AS LN
LEFT JOIN 
    開発言語 AS DL 
    ON LN.言語ID = DL.言語ID 
LEFT JOIN 
    開発言語名 AS DLN 
    ON DLN.開発言語ID=DL.開発言語ID 
WHERE LN.言語ID IN (?,?)
```
下記は英小文字のスネークケースによる表現です。
```SQL
SELECT 
    LN.language_id
    ,LN.language_name
    ,LN.phonetic
    ,DLN.development_language_id
    ,DLN.development_language_name
FROM language_name AS LN
LEFT JOIN 
    development_language AS DL 
    ON LN.language_id = DL.language_id 
LEFT JOIN 
    development_language_name AS DLN 
    ON DLN.development_language_id=DL.development_language_id 
WHERE LN.language_id IN (?,?)
```

システムの開発ターゲットが日本国内の業務システムの場合、ユビキタス言語または業務用語ディクショナリが日本語のため、データベースの物理名はローマ字表記されるという場合もよくあります。ほんとうの英語に直訳してしまうと日本人感覚では長すぎて扱いづらいようです。（英語のまま適宜省略する場合もあります。development_language　→　dev_lang）


※余談ですが、日本人的にはこの英字名の長さに多少くじけて、独自の略称が使われてしまいやすい環境下にはあります。

```SQL
SELECT 
    LN.gengo_id
    ,LN.gengo_mei
    ,LN.yomigana
    ,DLN.kaihatsu_gengo_id
    ,DLN.kaihatsu_gengo_mei
FROM gengo_mei AS LN
LEFT JOIN 
    kaihatsu_gengo AS DL 
    ON LN.gengo_id = DL.gengo_id 
LEFT JOIN 
    kaihatsu_gengo_mei AS DLN 
    ON DLN.kaihatsu_gengo_id=DL.kaihatsu_gengo_id 
WHERE LN.gengo_id IN (?,?)
```

以上本題がなんだったかわからなくなるくらいSQLについて説明してまいりましたが、かなり日本字が使われる例として例示させていただきました。
以下の変数名の表記方法の比較の評価にはSQLだったらという例示が含まれます。

# 変数名の表記方法の比較の評価
## クラス名とインスタンス名
オブジェクト指向プログラミングまたはモデリングを日本語識別子で記述する場合、よく問題になるのがクラス名とインスタンス名をどのように表記するかということです。

これは一般的に、Java系言語などでは、クラス名は大文字で始める(アッパーキャメルケース）で、インスタンス名は小文字で始める(ローワーキャメルケース)ことから、日本字に大文字小文字が（ひらがなカタカナの一部の文字種を除いて）ないことが問題にされます。

以下に、前述のSQLの例にあったテーブル名とその列名がR/OマッパーでJavaのEntitiyクラスに変換された場合を例示します。

| No. | クラス名 | インスタンス名 | メンバー<br>装飾識別 | 読易さ<br>設計目的| 読易さ<br>実装目的 |
|:-:|:-|:-|:-|:-|:-|
| 1  |LanguageName  |languageName |languageName.languageNameId |  C | B  |
| 2 |GengoMei  | gengoMei  |gengoMei.gengoMeiId |  C+ | B+  |

No.1はテーブル名・列名を英語でスネークケースとした場合、No.2はローマ字のスネークケースとした場合から、それぞれ（ローワー）キャメルケースに変換された例です。

日本字のままのテーブル名・列名は、漢字が表意文字のためもともと横文字のようには横に長くならないので、単語名としては区切り文字は不要ということから、このような変換は基本的に要らないとも言えます。

この点を踏まえて、以下の表に表記例を列挙しました。各案No.毎に評価してみます。想定している日本語プログラミングの制約は識別子として異なっていればOKということだけとしています。

| 案No. | クラス名 | インスタンス名 | メンバー<br>装飾識別 | 読易さ<br>設計目的| 読易さ<br>実装目的 |
|:-:|:-|:-|:-|:-|:-|
| 1  |言語名クラス  |言語名   |言語名の言語名ID |  A+ | B  |
| |  |  |言語名.言語名ID |  A++ | B  |
| 2  |言語名Class  |言語名   |言語名.言語名ID |  A  | B  |
| 3  |言語名称  |言語名   | 言語名.言語名ID | B  | B  |
| 4  |言語の名  |言語名   | 言語名.言語名ID | B  | B  |
| 5 |言語名Cls  |言語名cls| 言語名cls.言語名ID | B  | B+  |
| 6 |言語名Cls  |言語名| 言語名.言語名ID | B  | B  |
| 7  |c言語名  |言語名 | 言語名.言語名ID | B  | A  |
| 8  |_言語名  |言語名   |言語名.言語名ID  |  C | A  |
| 9  |GengoMei  |言語名   | 言語名.言語名ID | C  | B  |

**案No.1**は、クラス名には「～クラス」と装飾してしまう例です。これは設計書の表記としてはわかりやすく、丁寧な書き方と思います。

案No.1だけ、クラスのメンバー変数の装飾記法を、日本語として自然な「の」を使った場合と、SQLのテーブル名装飾としても一般的な「.」ピリオドを使った2パターン記述しました。基本的な読者をシステムエンジニアにフォーカスはしておりますので、その表記には慣れているひとが読むことを想定して、以降の例ではピリオド装飾としています。

**案No.2**は、クラス名には「～Class」と装飾してしまう例です。こう書くなら設計書用途ならば案No.1でよい気がします。案No.5と6に関係しますので、また後で説明します。

**案No.3**は、クラス名にはインスタンス名の「名」の冗長同意他語「～名称」と装飾してしまう例です。日本語にはこのパターンは多数あります。「方法」「方」など。

コンパイラ的には宣言部に一意に解釈が帰結できればよいので、このあたりは読み手とのバランスになりますね。

**案No.4**は、クラス名にはインスタンス名の名称に「の」などの区切り用のひらがなを挿入する方法です。「の」の場合はメンバー装飾識別子の区切りに「の」を使う場合は紛らわしいという面はあります。「.」ピリオドの場合は問題ありません。

**案No.5**は、クラス名にはClassの略字の「～Cls」と装飾してしまう例です。
**案No.6**は、クラス名にはClassの略字の「～Cls」と装飾して、インスタンス名にはその先頭小文字の「～cls」と装飾する例です。

Javaなどでクラスのインスタンスを宣言する際には、先に説明したアッパーキャメルとローワーキャメルのルールの存在により、クラスを「～Cls」と装飾することはまずないのですが、レイヤードアーキテクチャのフレームワーク（SpringBoot+Mybatisなど）で実装する場合、このクラスがどのレイヤーのどの種のコンポーネントであるかをわかりやすくするため、クラスとインスタンスを「～Ctrlr」「～Logic」「～Dao」「～Dto」などと装飾する場合はよくありますので、その装飾を使う場合はその装飾子を大文字小文字で区別するという小技もあります。

**案No.7**は、クラス名にはClassの略字cを接頭子として「c～」と装飾してしまう例です。
**案No.8**は、クラス名にはなんでもよいので半角１文字を接頭子として装飾してしまう例です。
いずれもさっと書く分には書きやすいです。意味はわかりにくくなりますが、クラスやインスタンスの意味自体は表現されているので、これがどちらかということを認識することはエディタに宣言部を表示または宣言部へジャンプする機能がサポートされていれば、問題なくなるでしょう。


**案No.9**は、クラス名には半角英字を使ってしまうという大胆な案です。わたしの感覚では、プリミティブな整数型などの表記はint、long、byte、stringなどでぜんぜん構わない派ですので、その延長として記載してみました。

## 配列
つづいて配列の例です。プリミティブ型の配列というのもありますが、ここではいちばんごちゃごちゃしそうなオブジェクト配列、クラスのインスタンスの配列を例にしてみます。

| 案No. | 型名 | インスタンス名 | メンバー<br>装飾識別 | 読易さ<br>設計目的| 読易さ<br>実装目的 |
|:-:|:-|:-|:-|:-|:-|
| 1  |言語名クラス配列  |言語名配列   |言語名配列(1)の言語名ID |  A+ | B  |
| |  |  |言語名配列(1).言語名ID |  A++ | B  |
| 2  |言語名Class配列  |言語名CArr   |言語名CArr(1).言語名ID |  A  | B  |
| 3  |言語名称配列  |言語名配列   | 言語名配列(1).言語名ID | B  | B  |
| 4 |言語名型[]  |言語名ary| 言語名cls(1).言語名ID | B  | B  |
| 5 |言語名Cls[]  |言語名ary| 言語名ary(1).言語名ID | B  | B  |
| 6  |c言語名[]  |言語名Items | 言語名Items(1).言語名ID | B  | A  |
| 7  |_言語名[]  |言語名ary   |言語名ary(1).言語名ID  |  C | A  |
| 8  |GengoMei[]  |言語名Items   | 言語名Items(1).言語名ID | C  | A  |

**案No.1** から **案No.3** までは、配列ということの明示に「～配列」という装飾を使う例です。型名部分はクラス名の表記との組み合わせとなります。

**案No.4** からは「[]」で明示する例です。

インスタンス側のインデックスの表記はすべて「()」表記としています。

## 一時変数
本記事での「一時変数」は、関数や処理単語内のローカル変数という意味を含みます。宣言するヶ所は関数や処理単語の宣言部分などを想定します。

| 案No. | 型名 | インスタンス名 | メンバー<br>装飾識別 | 読易さ<br>設計目的| 読易さ<br>実装目的 |
|:-:|:-|:-|:-|:-|:-|
| 1  |言語名クラス  |言語名   |言語名の言語名ID |  A+ | B  |
| |  |  |言語名.言語名ID |  A++ | B  |
| 2  |言語名クラス  |ln   |ln.言語名ID |  A  | A  |
| 3  |言語名Cls  |ln   | ln.言語名ID | B  | A  |
| 4  |GengoMei  |ln   | ln.言語名ID | C  | B  |

ここはわたしの好みが大きくでているところで、関数内で局所的に使われる変数名は英字でいいんじゃないか派です。

**案No.1**は、グローバルまたはクラスローカルレベルで広い範囲で使用される場合と同様に通常の記法をとる例として、とくにインスタンス名は日本語のままとしてます。

**案No.2** からはインスタンス名・変数名を半角英字の略字で定義する例です。SQLの場合もそうなのですが、適度に英字と日本字が役割分担して混在するとかえって読みやすいです。

# おわりに
日本語プログラミング（言語）処理系のメリットは文字種の多さにあると私は考えます。日本語プログラミング（言語）だから、英字や半角記号は使わないといった制約を取り除くと、表記の幅は広がります。

日本語の主たる文字種は漢字であり、表音文字ではなく表意文字であることから、同意他語の多様性が自然言語としてソフトウェアを記述する際に解釈の曖昧さへとつながります。

しかし、構造化プログラミング的なルールを設定するもしくは実際のコンパイル処理系を実装することで、基本的に定義が宣言部に由来することになりますので、定義されたトークンとして日本字を運用すれば曖昧さは除去されると考えられます。