個人的に見ることの多いRubyのソースに、次のようなものが多いです。
def methodA
...
end
protected
def methodB
...
end
private
def methodC
...
end
確かに僕も書くならまあこうするっちゃします。でもやっぱりprotectedなメソッドが増えて、privateなメソッドも増えたりすれば今見ているメソッドのアクセス権もわからなければ、privateなメソッドを追加したいときにどこに追加したらいいのかわからないこともあります。
そしてこの問題の解決策の1つとしてネット上でよく見るものに次のようなものがあります。
def methodA
...
end
protected
def methodB
...
end
private
def methodC
...
end
確かにインデントのレベルを変えれば少なくともpublicなメソッドでないことが分かります。もしprivateをすべてprotectedに置き換えてしまえ!なんてプロジェクトだったらもうすぐに判別がつきますね。
ただこの場合、クラス定義全体を見るとこのようになります。
class Klass
def methodA
...
end
protected
def methodB
...
end
private
def methodC
...
end
end
そう、最後の連続のendのインデントが奇妙になるのです。まぁこの辺は慣れればなんてことないのかもしれません…(ちなみにprotected, privateの次の行からbegin...endで囲んでendのインデントを合わせる方法もありました)。
ただ、個人的に「おややっ」となるのがクラスメソッドですね。 privateという記述より後に書こうがprivateメソッドにならない のです。これ知らなかったときはハマりました。
どうすればいいかと言えば
def self.class_methodA
...
end
private_class_method :class_methodA
とするか
class << self # この行は instance_eval do でも(ほぼ?)同じことが可能
private
def class_methodA
...
end
end
# ちなみにこの手法の場合はprotectedなメソッドもprivateと同様に定義可能
# 上の手法だとprivateなメソッドのみ定義可能
とするか、だと思います。
インスタンスメソッド定義とまとめて書けば、
(個人的にメソッドはいつも、アクセス権ごとに分けてクラスメソッドから順に定義してるのでそれに従って書きます)
class Klass
def self.class_methodA
...
end
def methodA
...
end
protected
def methodB
...
end
private
def self.class_methodB
...
end
private_class_method :class_methodB
def methodC
...
end
end
もしくは
class Klass
# もはやアクセス権ごとに分けるルールが適用できない(今回の件では全く重要ではないけど)
class << self
def class_methodA
...
end
private
def class_methodB
...
end
end
def methodA
...
end
protected
def methodB
...
end
private
def methodC
...
end
end
という風になります(インデントレベルを変えるパターンは省略します)。
非常に面倒くさいですね!
僕の理想は次のコードです。
class Klass
def self.class_methodA
...
end
def methodA
end
protected do
def methodB
...
end
end
private do
def self.methodB
...
end
def methodC
...
end
end
end
ということで理想通りに書けるようなモジュールを書きました(Gist)。テストは書いてませんが…。
クラス内でincludeすれば上記のように書けます。
さて、最後ですが皆さんこの辺どうしてますか。むしろテストまで書かれた同じようなモジュールやライブラリ、もしくは別の解決策となるモジュールやライブラリがあるのでしょうか。何かいい案があればご教授下さい。