Tech Racho エンジニアの「?」を「!」に。
  • 開発

Rubyスタイルガイドを読む: ソースコードレイアウト(1)エンコード、クラス定義、スペース

こんにちは、hachi8833です。

今回から、Rubyのコーディングスタイルガイドとして最もポピュラーなbbatsov/ruby-style-guidをベースに、スタイルガイドを読みつつ、そのスタイルになった理由などを考えてみたいと思います。よろしくお願いします。

注: この記事はいわゆる翻訳ではありません。スタイルガイドは最新の英語版をベースにしますが、単に翻訳するつもりはありません。英語を読むのが面倒な方は日本語版を参照するか、Google翻訳でも使ってください。

コーディングスタイルガイドについて

コーディングスタイルには、開発者のさまざまな智慧やノウハウが集約されています。また、議論の余地のあるスタイルについても標準を定めることで、余分な論争を避ける効果もあります。

既存プロジェクトなどで独自のスタイルが使われている場合も、標準的なスタイルガイドとの差分だけを示すことで指示の手間を軽減できます。

このスタイルガイド「bbatsov/ruby-style-guid」は、Rubyコミュニティが育て上げたものであるとのことです。

1. ソースコードレイアウト(1)エンコード、クラス定義、スペースなど(link

Nearly everybody is convinced that every style but their own is ugly and unreadable. Leave out the "but their own" and they're probably right...
-- Jerry Coffin (on indentation)

大意: だいたいどんな開発者も、コーディングスタイルは自分で手作りしたものだけが素晴らしく、それ以外はすべて醜悪で読むに耐えないと思っているものだ。「自分で手作りしたものだけが素晴らしく、それ以外は」の部分を除けばまあそのとおりかもしれない。

1-01【統一】ファイルエンコーディングはUTF-8にする

Use UTF-8 as the source file encoding.

ファイルのエンコーディングがエディタや環境ごとに違っているとGitなどでの共同作業に支障が生じるので、エンコーディングを統一します。

Ruby 2.0からはコードファイルのデフォルトのエンコーディングがUTF-8になったので、UTF-8を標準にするのが自然です。

Unicodeベースのエンコーディング(UTF-8/UTF-16など)がほぼ定着しており、その中でもUTF-8は開発現場においてほぼ標準と呼んでよいでしょう。UTF-8ASCIIと完全上位互換なので、ASCIIで書かれたコードファイルであってもそのまま開くことができますし、UTF-8で万一日本語などが文字化けるようなことがあったとしてもASCII部分は影響を受けずに済みます。

これは実は凄いことで、UTF-8を設計したRob PikeとKen Thompsonの筋のよさに震えてしまいます。

なお、UTF-16やUTF-32はASCII上位互換ではありません。また、拡張ASCIIはASCIIを拡張したものであり、UTF-8との互換性はありません。

1-02【統一】インデントはスペース2文字で表現する

Use two spaces per indentation level (aka soft tabs). No hard tabs.

1つのインデントはスペース2つで表します。Tab文字(\tで表される)は使いません。

インデントが不揃いだと可読性が下がり、重大な読み違えが発生することもあるので、それを防ぐために定められたスタイルです。見方を変えれば、Rubyでは連続スペース文字がいくつあってもひとかたまりとして認識するということです。

# 不可: スペース4つのインデント
def some_method
    do_something
end

# 良好: スペース2つ
def some_method
  do_something
end

インデントはたびたび論争の種になっています。さまざまなプログラミング言語でスペース2つ派、スペース4つ派、Tab文字派などがそれぞれ主張を繰り広げていますし、それぞれにもっともな言い分があります。

だからこそ、スタイルをどれかに定める必要があるのです。本スタイルガイド(および多くのRuby/Railsスタイルガイド)では、既にRubyで広く使われている2スペースインデントをスタイルとして定めています。

なお、Go言語ではTab文字が(スタイルレベルではなく)言語レベルで必須になっており、守らないとコンパイルしてもらえません。

1-03【統一】改行文字はUnixスタイル(LFのみ)とする

Use Unix-style line endings. (*BSD/Solaris/Linux/OS X users are covered by default, Windows users have to be extra careful.)
If you're using Git you might want to add the following configuration setting to protect your project from Windows line endings creeping in:
$ git config --global core.autocrlf true

Rubyに限らず、改行文字が開発者ごとに異なっているとGitなどで余分な差分が生じて読みづらくなるので、それを防ぐために改行文字を統一します。


1-03a【ヒント】コマンドプロンプトでgit config --global core.autocrlf trueを実行すると、Windows環境の場合のみ改行文字=CRLFで作業できるようになります。

環境ごとの主な改行文字

以下はあくまで目安であり、エディタやシステムでの用途によって異なることがありますのでご注意ください。

多くのLinux(Mac OS Xを含む)
LF(\nで表される) -- 本スタイルガイドではこれを採用
Windows
CRLF(\r\nで表される)
OS 9 以前のMac
CR(\rで表される)

参考

1-04 【統一】セミコロン;は文の区切りとしては使わない

Don't use ; to separate statements and expressions. As a corollary—use one expression per line.

Rubyではセミコロン;を文の区切りとして使えます。プログラムの実行上は改行文字と同じ機能です。

セミコロンを使う場合と使わない場合を許容してしまうと見苦しくなり、文法チェッカーの処理も複雑になってしまうので、それを避けるためにセミコロンを使わない方で統一しています。

セミコロンの利用は、Rubyでワンライナーを書くなどのお遊び用途にとどめておきましょう。

# 不可
puts 'foobar'; # なくてもよいセミコロンがある

puts 'foo'; puts 'bar' # 1行に式が2つあるのはよくない

# 良好
puts 'foobar'

puts 'foo'
puts 'bar'
puts 'foo', 'bar' # 特にputsはセミコロンではなくこのスタイルで書くこと

1-05 【統一】本文のない、空のクラス定義は1行で書くのが好ましい

Prefer a single-line format for class definitions with no body.

Preferとあるので絶対というより「好ましい」「望ましい」というニュアンスですが、いろんな人が寄ってたかって書いているスタイルガイドなので思惑は違うかもしれません。みんながみんな英語ネイティブとは限らないことを思い出しましょう。

「ここにこう書いてあるんだから」絶対正しいのだと考える前に、そこにいたるまでの成り立ちを考えてみて損はないと思います。

# 不可
class FooError < StandardError
end

# 少しまし(しかしセミコロンがある)
class FooError < StandardError; end

# 良好
FooError = Class.new(StandardError)

1-06 【統一】1行に多数の式を書くメソッド(シングルラインメソッド)は避ける

Avoid single-line methods. Although they are somewhat popular in the wild, there are a few peculiarities about their definition syntax that make their use undesirable. At any rate—there should be no more than one expression in a single-line method.

「そういうのが一部で人気があることは認識しているが、定義のスタイルとして望ましくないので、どうしてもシングルラインメソッドを使うならせいぜい式1つにとどめるべき」という見解が示されています。

シングルラインメソッドにするとセミコロンの利用を誘発するという理由もあります。

# 不可(式が2つ以上)
def too_much; something; something_else; end

# 少しまし(でもセミコロンが最初の式で必要)
def no_braces_method; body end

# 少しまし(でもセミコロンが2番目の式で必要)
def no_braces_method; body; end

# 少しまし(文法は合っているが、セミコロンなしでは読みづらい)
def some_method() body end

# 良好
def some_method
  body
end

One exception to the rule are empty-body methods.


1-06a【例外】以下のような中身が空のメソッドについてはシングルラインメソッドにできます。

# 良好
def no_op; end

1-07 【統一】演算子の前後にはスペースを置き、カンマ・コロン・セミコロンの後ろにもスペースを置く

Use spaces around operators, after commas, colons and semicolons. Whitespace might be (mostly) irrelevant to the Ruby interpreter, but its proper use is the key to writing easily readable code.

このスタイルは読みやすさのためのものであり、連続スペース文字(ホワイトスペース)がRubyインタプリタではほとんど意味を持たない性質を利用しています。

sum = 1 + 2
a, b = 1, 2
class FooError < StandardError; end

演算子の前後にスペースを置くか置かないかもスタイルの問題であり、どちらが正しいかではありませんが、少なくとも両方のスタイルが混じっているのは読みやすさのうえでも自動整形のためにもよくありません。

本スタイルガイドでは、演算子の前後にスペースを置くスタイルを選択しています。

The only exception, regarding operators, is the exponent operator:

1-07a【例外】累乗演算子**の場合はスペースを前後に置かない

累乗演算子**の前後にスペースを置くと、乗算演算子*を間違えて重ねたように見えるためと考えられます。

# 不可
e = M * c ** 2

# 良好
e = M * c**2

補足: Rubyの**の由来

ところで累乗演算子といえばハット記号^を使う言語をよく見かけますが、Rubyで累乗に使われている**はどこからきたのでしょうか。

hydroculのメモ > プログラミング言語の比較 > 数値型 > べき乗演算子によると、PHPやPythonのほかにPerlでも**が使われています。論拠はありませんが、Perlから持ち込まれたと推測できます。

ちなみにRubyのハット演算子^XORを表します。その他に正規表現のメタ文字としても使われます。

1-08 【統一】()[]のすぐ内側にはスペースを置かず、{}のすぐ内側にはスペースを置く

No spaces after (, [ or before ], ). Use spaces around { and before }.

丸かっこ ( )
【統一】内側にスペースを置かない
角かっこ [ ]
【統一】内側にスペースを置かない
波かっこ { }(ブロックの場合)
【統一】内側にスペースを置く
波かっこ { }(ハッシュリテラルの場合)
【選択】内側スペースの有無を選択できる
波かっこ { }(式展開の場合)
【例外】内側にスペースを置かない
# 不可
some( arg ).other
[ 1, 2, 3 ].each{|e| puts e}

# 良好
some(arg).other
[1, 2, 3].each { |e| puts e }

{ and } deserve a bit of clarification, since they are used for block and hash literals, as well as string interpolation.

For hash literals two styles are considered acceptable. The first variant is slightly more readable (and arguably more popular in the Ruby community in general). The second variant has the advantage of adding visual difference between block and hash literals. Whichever one you pick—apply it consistently.

Rubyの波かっこ{}には「ブロック」「ハッシュリテラル」「文字列の式展開」という複数の機能があるため、ハッシュリテラルについては以下の2つのスタイルから選択可能です。それぞれの言い分はもっともなので、おそらく意見を統一しきれなかったのでしょう。

# 良好 -- ハッシュリテラルで{}のすぐ内側にスペースを置くスタイル
{ one: 1, two: 2 }  # 理由: やや読みやすく、Rubyコミュニティでも主流

# 良好 -- ハッシュリテラルで{}のすぐ内側にスペースを置かないスタイル
{one: 1, two: 2}    # 理由: ブロックでも式展開でもないことを示せる

もちろん実際の案件ではどちらを選んでも構いませんが、採用したらそのスタイルで一貫させましょう。

3種類のかっこのスタイルを「すぐ内側はスペースなし」で統一できたらどんなにキモチイイかと思いますが、波かっこ{}で内側のスペースの置き方を機能に応じて使い分けるメリットは確かにあります。現実的なソリューションだと思います。

With interpolated expressions, there should be no padded-spacing inside the braces.

1-08a 【例外】式展開(interpolation)では波かっこ{}のすぐ内側にスペースを置かない。

ただでさえ長くなりがちな文字列リテラルをこれ以上冗長にしないためと考えられます。

# 不可
"From: #{ user.first_name }, #{ user.last_name }"

# 良好
"From: #{user.first_name}, #{user.last_name}"

次回: Rubyスタイルガイドを読む: ソースコードレイアウト(2)インデント、記号

関連記事



CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。