ソースコードのインデント(字下げ)に、タブを使うか半角スペースを使うかという話
2016-01-20
今回は、コーディングスタイルに関する話です。
皆さんはプログラミングするときに、そのプログラムのインデントスタイル(字下げスタイル)は、どのようにしてますでしょうか。プロジェクトや言語ごとに異なることが多いコーディングスタイルの一つである、インデントスタイルについて、今回は考えてみます。
インデントスタイルとは
まず初めに、インデントスタイルとは何ぞやという方向けに簡単に説明しておきます。Wikipediaには、下記のような説明があります。
字下げスタイルまたはインデントスタイル(英: Indent style)とは、プログラミングにおいてプログラムの構造を明らかにするために、コードのブロックの字下げをどうするかを決めたものである。(中略)字下げスタイルはプログラミング作法の一部である。
まあ、よくあるプログラムの行頭の空白のスタイル・ルールのことです。例えば、以下の2行目・3行目・4行目の行頭の空白のスタイル・ルールのことです。
while (true) {
if (true) {
myFunc(myArg);
{
}
主に処理をネストするときに、可読性を向上させる目的でその処理部分を1段高く見せるルールのことです。プログラマーなら誰もが1度は使ったことがあると思います。
メジャーなインデントスタイル
今現在、一般に知られているインデントスタイルに使われる空白には、主に以下があります。
- 1字下げにつき、タブスペース1字
- 1字下げにつき、半角スペース4字
- 1字下げにつき、半角スペース2字
果たしてどのスペースを選択するのが良い選択であるのか、考えてみます。
インデントスタイルに使われる空白の歴史
まず、歴史的にどの空白が多く使われてきたかを振り返ってみます。
Wikipediaによると、初期のプログラムの多くは、字下げにタブスペースを使用していたそうです。
タブスペースを使うメリットとしては、まず単純であり、1字であるが故に他のスペースに比べファイルサイズを最も節約できる点があります。しかし、デメリットとして、多様化する開発環境によって、タブスペースが半角スペース8個分の幅で表示されたり、半角スペース4個分の幅で表示されたりしてしまい、字下げの見た目が変わってしまうことがありました。また、ターミナルの画面(CLI/CUI)では、環境によってタブスペースも半角スペースの羅列で表現され、コピーすると半角スペースになってしまうことがあるというデメリットもあります。
そこで、空白の幅を明確に定義できる、半角スペースによる表記が、次にメジャーになりました。
これまでの歴史から、半角スペース4字が最も見やすいとされ、現在では言語にもよりますが、半角スペース4字を採用したコーディングスタイルが最もメジャーとなっています。
そしてその後、さらに半角スペース4字ではファイルサイズが必要以上に大きくなってしまうことから、容量削減と可読性向上の間をとって、半角スペース2字を採用したコーディングスタイルも登場しました。ただ、半角スペース2字はネスト構造を認識しにくく、嫌がるプログラマーも多いようです。
また、可読性向上のために、ネスト構造ではなく、関数の引数やメソッドチェーンなどを改行することもありますが、その場合は見やすいように前の行に合わせた形で任意の数の半角スペースでインデントするように定めたコーディングスタイルも、現在は多いようです。そのため、半角スペースをネスト構造のインデントに使用するスタイルが主流のようです。
if (bool) { // ネスト構造は半角スペース2字
foo.bar.foo.bar.foo.bar.foo.bar.foo.bar.foo.bar.myFunc(
arg1,
arg2,
arg3
); // 処理改行は半角スペース4字
}
while (bool) { // ネスト構造は半角スペース2字
foo.bar.foo.bar.myFunc(exampleArgumentNumberOne,
exampleArgumentNumberTwo,
exampleArgumentNumberThree); // 引数部分を揃える
}
myClass.myMethod1(myArg1)
.myMethod2(myArg2)
.myMethod3(myArg3); // メソッドチェーンでメソッド部分を揃える
各空白文字のメリット・デメリット
以上で挙げた各スペースのメリットとデメリットは以下のようになっています。
種類 | メリット | デメリット |
---|---|---|
タブスペース1字 | 1回のキー入力で入力できる。 ファイルサイズが削減できる。 エディターで好きな幅に設定できる。 | 環境によって見た目が異なる。 引数部分をインデントする場合に半角スペースと混同しなければならなくなる。 |
半角スペース4字 | 多くの人にとって読みやすい。 どの環境でも同じように表示される。 引数部分を同様にインデントできる。 | ファイルサイズが大きくなる。 入力に4回のキー入力を要する。 |
半角スペース2字 | どの環境でも同じように表示される。 引数部分を同様にインデントできる。 | 多くの人にとって読みにくい。 |
言語ごとに異なるインデントスタイル
大抵、言語ごとにメジャーなコーディングスタイルは異なります。特にコーディングスタイルに制約がない場合、その言語で最もメジャーなコーディングスタイルを採用するのが賢い選択かと思います。
参考までに、私が使用しているIDEに登録されているデフォルトのコーディングスタイルでは、インデントに使う空白は以下のようになっていました。各言語ごとに文化がありますし、あなたの組織の文化もあるかと思いますので、適宜そのチームのコンセンサスをとって決定していけばいいかと思います。
言語 | インデント文字 |
---|---|
Scala | 半角スペース2字(ネスト構造) 半角スペース2字(処理改行) |
Java | 半角スペース4字(ネスト構造) 半角スペース8字(処理改行) |
ActionScript | 半角スペース4字(ネスト構造) 半角スペース8字(処理改行) |
CoffeeScript | 半角スペース2字(ネスト構造) 半角スペース2字(処理改行) |
CSS | 半角スペース4字(ネスト構造) 半角スペース8字(処理改行) |
HTML | 半角スペース4字(ネスト構造) 半角スペース8字(処理改行) |
JavaScript | 半角スペース4字(ネスト構造) 半角スペース4字(処理改行) |
JSON | 半角スペース2字(ネスト構造) 半角スペース8字(処理改行) |
PHP | 半角スペース4字(ネスト構造) 半角スペース4字(処理改行) |
Python | 半角スペース4字(ネスト構造) 半角スペース8字(処理改行) |
Ruby | 半角スペース2字(ネスト構造) 半角スペース4字(処理改行) |
SQL | 半角スペース2字(ネスト構造) 半角スペース4字(処理改行) |
TypeScript | 半角スペース4字(ネスト構造) 半角スペース4字(処理改行) |
XML | 半角スペース4字(ネスト構造) 半角スペース8字(処理改行) |
まとめ
当然のことですが、既存のプロジェクトで既にインデントスタイルが確立されている場合は、そのスタイルに合わせて記述するようにしましょう。大事なことは、全体的にコーディングスタイルに統一感があるということです。コーディングスタイルに統一感がないと、可読性は向上できません。
この記事が、あなたのプロジェクトでインデントスタイルを検討する際の、参考になれば幸いです。