ようやく、進みます。
早速./lib/indicator/moving_average.rbを観てゆきます。
大変そっけない、コードです。
でも、ちょっと複雑なことやってます。
1.コンストラクタ
生成するときにはStock(株情報)と以下の情報を渡す。
四本値のどれを使うか(指定がなければ終値)、
移動平均の区間。
※ちょっと気に食わないのだが、それは後で。
2.calculate_indicatorの実装
Stockからコンストラクタで指定した四本値のどれかの配列を取り出す。
※ここでsendという特殊なテクニックを使う。
既に、配列には移動平均を計算するメソッドを追加してあるので、
それを呼び出す。
sendという特殊なテクニックとは?
他言語でいうリフレクションのようなもの。
やってることは、以下と一緒です。
case @price_at
when :open then
@stock.open_prices
when :high then
@stock.high_prices
when :low then
@stock.low_prices
when :close then
@stock.close_prices
end
でも、open,high,low,closeという文字以外は、書くこと一緒なので、
こう書いて、
@stock.send(@price_at.to_s + “_prices”)
その4種類を置き換えるだけで短くしたということ。
これがスマートなのかどうか知りませんが。
@price_at.to_s + “_prices” で、 open_pricesとかXXX_pricesという文字列になり、
@stock.send(“open_prices”)は@stock.open_pricesを実行します。
オブジェクト.send(メソッド名)はオブジェクト.メソッドになります。
メソッドを直接呼び出さず、メソッド名を渡すことでメソッド実行してます。
こういうやり方、他言語だとリフレクションとかで実現してます。
ですが、
@stock.map_prices(@price_at)と書けば、やっぱり1行で済みます。
こんなめんどくさいことしなくても、
これはRubyの悪口じゃなく、坂本タクマ先生への批判になっちゃいますが、
こういう意味のない趣味なコード私は嫌いです。
Rubyって、そういう悪趣味助長しやすそうです。
コンストラクタで引数を渡す。
親クラスではinitialize(stock)
ここでは、initialize(stock, params)
これあんまり美しくない。
始めからinitialize(params)全部そこで渡す。
ないし、calculate_indicator(stock, params)とか、
initialize(stock)とcalculate_indicator(params)でもいいけど、
親クラス側でparams渡すとこは定義明確にしときたい。
そうしておけば、
全てパラメータは外部ファイルに書き出すとか出来る。
そういうことは親の方で統一しておきたい。
Indicatorでは、
コンストラクタは定義せずに、
def calculate(stock, params)
@stock=stock
@indicator = calculate_indicator(params)
self
end
def calculate_indicator(params) ; end
が適切じゃないかな。
計算するときしか情報使わなくて、かつ、
stockは全てのインジケータで必要で、それ以外は任意なのだし。
元のやつだと、ムダにコード書く量増えそう。
結局プログラムの話ばかりしてて、申し訳ないですが、
気になってしまいました。
質問コーナー、お問い合わせは、sanpome.net@gmail.com まで。