Perlがくしゅう帳(Rubyも)

プログラミングの勉強会の参加記録や学んだことなど。 twitter ID : @tomcha_で活動しています。 最近は主にPerl関連の勉強会やコミュニティに参加しています。移転前のブログはこちら->http://ruby.doorblog.jp/

パーフェクトRubyを読んでの疑問

冬休みの課題として、オレオレCLIツールが書きたいと思ってググっていたら、なんと今読み進めている「パーフェクトRuby」の第15章でCLIツールの作り方の記事があったので、それを読みながら書いている時の疑問のについてメモ。

パーフェクトRuby

パーフェクトRuby

記事では「Todo」というアプリを、bundlerをつかってGemを作る構成。 Gemを作る為のファイル構成の中で、中心部分は

./bin/todo
./lib/todo.rb
./lib/todo/command.rb
./lib/todo/version.rb
./lib/todo/command/opions.rb

とファイルが構成されていて、"./bin/todo"を実行すると、"./lib/todo"が読み込まれ、そこでrequireしている"./lib/"以下のファイルを読み込んでいる。 疑問点は、"./lib/"以下のファイル全てで「module Todo」とモジュール宣言されていて、そのモジュール内のほぼ全てで「Class Todo」が書かれていたが、書かれたモジュールを「include」も「extend」もしていなかった点、そして、同じクラス名で書かれていた点でした。

最初は誤植かな?とも思ったのですが、その様子は無く、この書き方がセオリーだとしたら、何なのか?をサンプルコードで試してみる事にしました。 1つのファイルに延々と色々な機能のコードを書くと肥大化してしまうので、ファイルを分けて書く点はその通りなのですが、クラス名を同じにしている点について仮説を立てて考察してみました。

別のファイルで同じクラス名の定義を書く

直感では、これはオープンクラスを利用して、「1つの仕組み(クラス)」を「機能ごとのファイルに分けて書いた」手法なのではないかという事。 メインのファイル"./lib/todo.rb"が、次々にClass Todoにメソッドを追加していっているという理解で良いのか実験をしてみました。 実験用のコードは、「衣笠丼を作る」というコード。

Class Kinugasadon に「油揚げを投入するメソッド」「葱を投入するメソッド」「玉子を投入するメソッド」「ご飯に乗せるメソッド」を順番に追加して、かつ、オープンクラスであれば同名のメソッドであれば後から追加したものが優先される特性を利用して、「フルーツを投入する」というメソッドを追加して上書きされるかも実験してみました。

f:id:tomcha0079:20141231183959p:plain

実験結果から、多分、1つのクラスを分解する方法として、オープンクラスを利用するセオリーなのだろうという結論です。

includeもextendもされない同じ名前のmodule

さっきの"age.rb"、"negi.rb"、"age.rb"の3つのファイルのmodule宣言部分をコメントアウトして、class宣言だけのファイルにし、実行ファイルのkinugasa.rbのオブジェクト生成コード部分を

kinugasa = Kinugasa.new

と変更して同じように実行してみた結果は、

f:id:tomcha0079:20141231184140p:plain

うーん、特に変化なくきちんと実行されました。
どうやらmodule宣言は無くても動くようです。そもそも、moduleをmix-inして使うときに必要な「include」も「extend」もしてません。
実験結果と状況からの自分なりの答えとしては、module宣言をした理由は「名前空間」の利用の為なのでしょうか。自分だけの小さなプログラムなら全体を把握できますが、他人が見た時とかにちゃんと外部ファイル管理されているクラスという事を明示させ、わかりやすくする為にmodule宣言をしているのでしょうか?
今のところはその様な理解という事でブログ記事を書いてみました。

なんかPerlのpackage宣言する効果と似てるなーと思ったり。
あ、あと、衣笠丼に苺とかバナナを入れてはいけません。入れるとエラい事になりますのでご注意を。