たくろぐ!

世界一のチラ裏

Ruby Style Guideを読んだ

はじめに

自身の備忘録としてなので、私が知っているコーディング規約は除いてます、すみません。

事前に以下を読んでおくとよさそうです。

目次

General

Layout

Syntax

Naming

Classes and Modules

Exceptions

Collections

Strings

Regular Expressions

Percent Literals

Testing

General

SLAPを使って複雑なメソッドを同じレベル(粒度)の抽象度で実行できるようにしよう

Make all lines of your methods operate on the same level of abstraction. (Single Level of Abstraction Principle)

参考:

防御的プログラミングを避けよう

Avoid defensive programming

将来起こるかどうかわからないエラーや例外のためにコードを書くべきではないということ。

RubyistにはYAGNIという格言で有名だと思います。

参考:

読んでみると、実は結構議論の余地があるのかも。

Layout

ラムダでスペースを避けよう

Avoid space in lambda literals.

# bad
a = -> (x, y) { x + y }

# good
a = ->(x, y) { x + y }

begin句の結果の代入時はresque/ensure/endは行頭に書こう

When assigning the result of a begin block, align rescue/ensure/end with the start of the line

# bad
host = begin
              URI.parse(value).host
            rescue URI::Error
              nil
            end

# good
host = begin
  URI.parse(value).host
rescue URI::Error
  nil
end

Syntax

レシーバ::メソッドのようなメソッド呼び出しは使わないようにしよう

Use :: only to reference constants (this includes classes and modules) and constructors (like Array() or Nokogiri::HTML()). Avoid :: for regular method invocation.

参考:

変数が初期化されていないときにしか ||= で初期化しない(変数が初期化されていないときだけ ||= で初期化する)ようにしよう

Use ||= to initialize variables only if they're not already initialized.

メモ化のことなんだろうけど、日本語が難しい。

その直後に false に意味があるときは使わないということが書いてありました。

参考:

# bad
name = name ? name : 'Bozhidar'

# bad
name = 'Bozhidar' unless name

# good - set name to Bozhidar, only if it's nil or false
name ||= 'Bozhidar'

不正なデータが入力されたらガード節を使ってなるべく早めに返す

Prefer a guard clause when you can assert invalid data. A guard clause is a conditional statement at the top of a function that bails out as soon as it can.

時間の変換にはiso8601メソッドを使う

Prefer Time.iso8601(foo) instead of Time.parse(foo) when expecting ISO8601 formatted time strings like "2018-03-20T11:16:39-04:00".

Naming

クラス名やモジュール名にはスネークケースを使おう、大文字略語はそのまま使おう

Use CamelCase for classes and modules, but keep acronyms like HTTP, RFC, XML uppercase.

Rubyのクラス(モジュール)では、XmlHttpRequestにしないで、XMLHTTPRequestにする

injectメソッドの引数には何がinjectされるのかわかりやすいニーモニックを使おう

When using inject with short blocks, name the arguments according to what is being injected, e.g. |hash, e| (mnemonic: hash, element)

「mnemonic(ニーモニック)」の意味は「記憶を助ける」とか「記憶術の」とかです。

ニーモニックってアセンブラのやつが語源なのかな。あのAT&TIntelかみたいなの。

二項演算子を定義する場合、パラメータに other を付ける( << と は意味合いが異なるので例外)

When defining binary operators, name the parameter other(<< and are exceptions to the rule, since their semantics are different).

ちょっと言ってる意味がわからないので誰か教えて。

Classes and Modules

クラスメソッドしかないクラスよりもモジュールを使用しよう

Prefer modules to classes with only class methods. Classes should be used only when it makes sense to create instances out of them.

Exception

シグナル例外には raise を使おう

Signal exceptions using the raise method.

どうやら以前は シグナル例外用に fail があったようですね。

rescueなどで捕捉した例外を再度発生させる時には「何かがfailなわけではないので」raiseを用い、それ以外の場合はfailを用いる、というような使い分けのパターンがあるようだ。

たぶん以下が一番詳しい。

よくわからないけど、必要になったら調べる。

ensure 節で return をすると例外を補足しても破棄されるので避けよう

Avoid returning from an ensure block. If you explicitly return from a method inside an ensure block, the return will take precedence over any exception being raised, and the method will return as if no exception had been raised at all. In effect, the exception will be silently thrown away.

特殊変数で例外を補足しない

Avoid rescue in its modifier form.

厳密には特殊変数に限らないんだろうけど、コメントのように

$! にどんなエラークラスが入るかがぱっとわからないので明示的に書くようにする。

# bad - this catches exceptions of StandardError class and its descendant
# classes.
read_file rescue handle_error($!)

# good - this catches only the exceptions of Errno::ENOENT class and its
# descendant classes.
def foo
  read_file
rescue Errno::ENOENT => error
  handle_error(error)
end

ちなみに特殊変数と require 'English' したときのグローバル変数の対応表?もありました。

ローカル変数なのにグローバル変数っぽいみたいな特殊グローバル変数もあったような気がしたけど、わすれた。。。

has_key? よりも key? を使おう

Prefer Hash#key? over Hash#has_key?.

Effective Rubyでは key? のことは書いてなくて、 存在しない key にアクセスしたら nil が返るので、

以下を混同しないように has_key? で確認しろと言っていた(と思う)。

  • key は存在するが、 valuenil
  • key が存在しない(が、アクセス自体はでき、 nil が返る)

文字列結合よりも文字列補間か文字列書式化を使用しよう

Prefer string interpolation and string formatting instead of string concatenation:

"#{a}" のような表現をstring interpolation(=文字列補間)というのを知らなかった。

Percent Literals

正規表現でよく見られるように、括弧がリテラル内にある場合を除き、すべての % リテラルの区切り文字として () を優先します。()、{}、、<> のうち、リテラル内に現れないものを使用します。

Prefer () as delimiters for all % literals, except, as often occurs in regular expressions, when parentheses appear inside the literal. Use the first of (), {}, , <> which does not appear inside the literal.