- Ruby / Rails関連
READ MORE
こんにちは、hachi8833です。
Rubyスタイルガイドを読む、第2回目です。今さらですが、スタイルガイドをただ読むよりも頭に入りますね。
!
の後ろにはスペースを置かないNo space after !.
原文では他に記述がありませんが、この感嘆符はRubyの単独の否定演算子!
を指しています。
# 不可
! something
# 良好
!something
以下は否定演算子ではないので、この項には該当しません。
!=
などの記号の組み合わせによる演算子!
(例: String#gsub!)..
や...
の前後にはスペースを置かないNo space inside range literals.
範囲演算子の前後にスペースがあると、範囲演算子であることがわかりにくくなるためです。
# 不可
1 .. 3
'a' ... 'z'
# 良好
1..3
'a'...'z'
case
文内部のwhen
のインデントの深さはcase
と同じにするIndent when as deep as case. This is the style established in both “The Ruby Programming Language” and “Programming Ruby”.
これは意見が割れそうなスタイルですが、『The Ruby Programming Language』と『Programming Ruby』の2冊の書籍を論拠にしています。繰り返しになりますが、重要なのは「どちらかに決める」ことです。
# 不可
case
when song.name == 'Misty'
puts 'Not again!'
when song.duration > 120
puts 'Too long!'
when Time.now.hour > 21
puts "It's too late"
else
song.play
end
# 良好
case
when song.name == 'Misty'
puts 'Not again!'
when song.duration > 120
puts 'Too long!'
when Time.now.hour > 21
puts "It's too late"
else
song.play
end
When assigning the result of a conditional expression to a variable, preserve the usual alignment of its branches.
1-12a【選択】この場合のインデントスタイルは、以下の「良好1」「良好2」から選べます。
# 不可 - 文がわかりにくい
kind = case year
when 1850..1889 then 'Blues'
when 1890..1909 then 'Ragtime'
when 1910..1929 then 'New Orleans Jazz'
when 1930..1939 then 'Swing'
when 1940..1950 then 'Bebop'
else 'Jazz'
end
result = if some_cond
calc_something
else
calc_something_else
end
# 良好1 - 処理内容が明確
kind = case year
when 1850..1889 then 'Blues'
when 1890..1909 then 'Ragtime'
when 1910..1929 then 'New Orleans Jazz'
when 1930..1939 then 'Swing'
when 1940..1950 then 'Bebop'
else 'Jazz'
end
result = if some_cond
calc_something
else
calc_something_else
end
# 良好2 - コードの表示幅を節約できる
kind =
case year
when 1850..1889 then 'Blues'
when 1890..1909 then 'Ragtime'
when 1910..1929 then 'New Orleans Jazz'
when 1930..1939 then 'Swing'
when 1940..1950 then 'Bebop'
else 'Jazz'
end
result =
if some_cond
calc_something
else
calc_something_else
end
「良好」が2つあるのは、議論で決着がつかなかったようです。
case
、when
、if
、else
、end
の縦が揃っていて、見ていてキモチイイですね。このスタイルは多くの言語で採用されています。=
で改行することで、条件式の結果の代入で幅を取りすぎないようにできます。面白いのは、どちらの場合もcase
やif
に対応するend
まで縦が揃っていることです。深入りはしませんが、Rubyのcase
やif
は例に示されているとおり結果の値を返すので、case
やif
全体で値を返すことを強調するという意図なのだろうと理解しました。
morimorihogeコメント:
Ruby styleなcase-whenインデントは、ソフトウェア解析分野での条件分岐命令のネスト深度測定とも一貫する(インデントの深さが条件分岐の深さとそろう)ので、そこがよいですね。
コメント中の「不可」で使われていたconvolutedは、ここでは「わかりにくい」「込み入っている」程度の意味です。最近だと機械学習方面のConvolutional neural networkなどでよく見かけますね。
Use empty lines between method definitions and also to break up methods into logical paragraphs internally.
「lines」と複数形になっているので、1行より多く空行を置いてもよいということになります。
def some_method
data = initialize(options)
data.manipulate!
data.result
end
def some_method
result
end
Avoid comma after the last parameter in a method call, especially when the parameters are not on separate lines.
「不可」のコメントについて詳しくは「ケツカンマ」でググるのがよいと思います。
# 不可
#(末尾にもカンマがあればパラメーターの追加や削除が楽になるのはわかるが、それでも推奨しない)
some_method(
size,
count,
color,
)
# 不可
some_method(size, count, color, )
# 良好
some_method(size, count, color)
=
の前後にはスペースを置くUse spaces around the = operator when assigning default values to method parameters:
# 不可
def some_method(arg1=:default, arg2=nil, arg3=[])
# do something...
end
# 良好
def some_method(arg1 = :default, arg2 = nil, arg3 = [])
# do something...
end
While several Ruby books suggest the first style, the second is much more prominent in practice (and arguably a bit more readable).
多くのRuby書籍では前者のスタイルが採用されていますが、後者の方がやや読みやすく明快であるという判断がなされています。
なお、前者のスタイルが多くの書籍で使われているということは、他の言語のスタイルからの影響など何らかの理由があると考えられます。
\
で行を継続するのは避ける(文字列の結合での利用のみ認める)Avoid line continuation \ where not required. In practice, avoid using line continuations for anything but string concatenation.
特に英語圏にはエディタの行折り返しを好まない開発者が意外にいるので、そうした設定での行分割に\
を使うと考えられます。
# 不可
result = 1 - \
2
# 少しマシ (でもまだまだひどい)
result = 1 \
- 2
long_string = 'First part of the long string' \
' and second part of the long string'
長い文字列ならヒアドキュメントにする方がよいでしょう。
.
によるメソッドチェーンの行分割はOption AとOption Bのいずれかに揃えるAdopt a consistent multi-line method chaining style. There are two popular styles in the Ruby community, both of which are considered good—leading . (Option A) and trailing . (Option B).
A discussion on the merits of both alternative styles can be found here.
Option AとOption Bのどちらがよりよいというものではありません。重要なのはどちらかに揃えることです。
以下のコメントで両陣営の言い分がよくわかります。
When continuing a chained method invocation on another line keep the . on the second line.
ドット.
を次の行の最初に置くスタイルです。
# 不可
one.two.three. # 1行目を読まないと2行目がメソッドチェーンであることがわからない
four
# 良好
one.two.three # 2行目がメソッドチェーンであることがひと目でわかる
.four
When continuing a chained method invocation on another line, include the . on the first line to indicate that the expression continues.
ドット.
を前の行に残すスタイルです。
# 不可
one.two.three # 2行目を読まないとメソッドチェーンが継続しているかどうかがわからない
.four
# 良好
one.two.three. # 1行目のメソッドチェーンが継続していることがひと目でわかる
four
両方にドットを残せる言語仕様であればよかったのかなと一瞬思ったりしましたが、改行がなくなったときに範囲演算子..
と誤認されそうなのでよくありませんね。
『宗論はどちらが負けても釈迦の恥』という言葉をなぜか思い出してしまいました。もっとも釈迦は本を一冊も書いていないそうですが。
1-18a【選択】幅が足りない場合は「2インデント」でもよい
Align the parameters of a method call if they span more than one line. When aligning parameters is not appropriate due to line-length constraints, single indent for the lines after the first is also acceptable.
原則、以下の上図のようにパラメータの縦をキモチヨク揃えますが、表示幅が狭い場合は下図でもよいということですね。
# この長すぎるメソッドを分割するとする
def send_mail(source)
Mailer.deliver(to: 'bob@example.com', from: 'us@example.com', subject: 'Important message', body: source.text)
end
# 不可(4スペースインデント)
def send_mail(source)
Mailer.deliver(
to: 'bob@example.com',
from: 'us@example.com',
subject: 'Important message',
body: source.text)
end
# 良好
def send_mail(source)
Mailer.deliver(to: 'bob@example.com',
from: 'us@example.com',
subject: 'Important message',
body: source.text)
end
# 良好 (通常の2スペースインデント)
def send_mail(source)
Mailer.deliver(
to: 'bob@example.com',
from: 'us@example.com',
subject: 'Important message',
body: source.text
)
end
Align the elements of array literals spanning multiple lines.
# 不可 - シングルインデント
menu_item = %w[Spam Spam Spam Spam Spam Spam Spam Spam
Baked beans Spam Spam Spam Spam Spam]
# 良好
menu_item = %w[
Spam Spam Spam Spam Spam Spam Spam Spam
Baked beans Spam Spam Spam Spam Spam
]
# 良好
menu_item =
%w[Spam Spam Spam Spam Spam Spam Spam Spam
Baked beans Spam Spam Spam Spam Spam]
1-19a【選択】ブラケット[
も次の行に送ると縦が揃ってないように見える気もしますが、これも認められています。
_
で区切るAdd underscores to large numeric literals to improve their readability.
この記法は他の言語では見かけないような気がしますが、カンマを使わなくてよいので便利ですね。
# 不可 - ゼロがいくつあるかわかりにくい
num = 1000000
# 良好 - 目に優しい
num = 1_000_000
Prefer smallcase letters for numeric literal prefixes. 0o for octal, 0x for hexadecimal and 0b for binary. Do not use 0d prefix for decimal literals.
0o
0x
0b
【統一】通常の10進リテラルにも0d
というprefixが一応ありますが、これは使ってはならないというスタイルになっています。
Rubyでは大文字でも書けることを初めて知りました。
# 不可
num = 01234
num = 0O1234
num = 0X12AB
num = 0B10101
num = 0D1234
num = 0d1234
# 良好 - prefixを見分けやすい
num = 0o1234
num = 0x12AB
num = 0b10101
num = 1234
Use YARD and its conventions for API documentation.
YARDは標準ではないんですね。
577765bの更新を反映しました。
Limit lines to 80 characters.
もちろん半角英数字(alphanumeric)での80文字です。1行にそんなにたくさん押し込めたことがないのでわかりませんが、個人的にはエディタのワードラップアラウンドにおまかせしたいところです。
Avoid trailing whitespace.
trailingといえば通常は対象の末尾を指します。
End each file with a newline.
Unix系環境でのテキスト処理における一種のマナーとして、EOF前に空行を置く慣習があります。
末尾空行がないと、たとえばソースをcat
したときの出力が以下のようにプロンプト行と重なってしまいます。
# 改行なし
[morimori] $ cat .ruby-version
2.3.3[morimori] $
# 改行あり
[morimori] $ cat .ruby-version
2.3.3
[morimori] $
また、行指向なプログラムのの中には「行頭から行末(改行コードの手前)まで」を1行と見なすものがありますので、EOL前改行がないと最終行だけ処理されないことがあります。
逆に言えば、EOL前改行を置くことで「すべての行が改行で終わる」ので処理が一貫します。
=begin
と=end
によるブロックコメントは使わないDon’t use block comments. They cannot be preceded by whitespace and are not as easy to spot as regular comments.
なお、=begin
と=end
の間のコメント行の先頭にはスペースを置けません。
# 不可
=begin
comment line
another comment line
=end
# 良好
# comment line
# another comment line
=begin
と=end
によるブロックコメントはデバッグで特定の処理を抑制するのには便利ですが、読みにくいのでコミットには残してほしくないですね(morimorihoge)。