By

Ruby のモジュラリティの再発見(翻訳記事)

これは、弊社のクリス・サルツバーグによる Rediscovering Modularity in Ruby — Commerce Hack という記事の翻訳です。

デジカの開発チームは、広島で開催された、Ruby開発者の世界で一番大規模な集まりである RubyKaigi 2017 に参加しました。これに参加するのは初めてではないですが、チーム全体で用意をして臨むのは初めてでした。CEOと4人の開発者が現地に行きました。私たちはかわいいステッカーを持ち込み、ちょっとシャレた配布物を印刷して、小さなブースで展示しました。さらにはテキストアドベンチャーゲームまで作りました。

RubyKaigi での発表内容

私が一番力を入れたのは、二日目に行なったThe Ruby Module Builder Patternという発表です。これは私が最近書いた ブログ記事 をベースにしたものです。[訳注: 日本語翻訳がこちらにあります→RubyのModule Builderパターン #1 モジュールはどのように使われてきたか#2 Module Builderパターンとは何か]

これまでも何度かプログラミングについてのプレゼンテーションは行なっていますが、プログラミングに関する コンセンプト について発表するのは初めてでした。”Moduler Builder” とはコンセプト以外の何者でもなく、シンプルではありますが、直感的な理解が難しいものかもしれません。

私は、こういう、単純だけど直感的でないコンセプトを好みます。なぜなら、それは誰にとっても「目から鱗」の話になるからです。上級者もそう感じることがあります。そして、その意義が過小評価されていることが多い。

Matz, Me, and Modules (まつもとさんが私と同じく Module について話す!)

私の発表は、Ruby開発者のまつもとゆきひろさんによるキーノートの直後の枠になりました。これは私にとってはありがたいことでした。(まさか、このイベントの参加者の中に寝坊してまつもとさんのプレゼンを聞き逃す人はいないので、私の時間にも間に合うでしょう)。しかし、”The Many Faces of Module“というプレゼンのタイトルを聞いた時にはビックリしました。

あのまともとさんが、Ruby の生みの親が、私と同じく module について話すというのです。私がどれくらい驚いたか想像できますか?

Ruby を作ったまつもとさんが私のテーマに近いことを話す、ということは、module はやっぱり Ruby という彼がデザインした言語にとってとても重要な要素だと私はあらためて実感しました。自分がまつもとさんという偉大な頭脳と同じ発想をしてるって、これはちょっと自慢できることじゃないかな(笑)。

でも逆に、私はまともとさんのキーノートの間、とても不安でもありました。Rubyの module についての私のとっておきのネタと同じことが、彼の次のスライドに書いてあって、私が話すことが無くなってしまうんじゃないか、そうなったら大変だ、直す時間はないし私は40分間何を話したらいいだろう、馬鹿みたいに立ち尽しているしかないんじゃないか?私はずっとそんな心配をしながらキーノートを聞いていました。

もちろん、それは杞憂でした。まつもとさんは、Ruby における module の歴史、それについて彼ら開発者が何をしたか、について話しました。そして、これから行うかもしれないことについても少し。それは、mixin としての module と namespace としての module と singleton としての module の話で、[動的に] module を作成することについての話ではありませんでした。

それともうひとつ、私の話と彼の話には違う点がありました。

まつもとさんは過去について語り、将来について話しました。 彼はどのようなインスピレーションから Ruby が作られて、どのように module が今日のような形になったのかについて話しました。 そして現在の話題としては、最近追加された新機能について、将来の話としてこれから追加される可能性のある新機能について話しました。

私は、Ruby が偉大な言語だと思います。でなければ、毎日それでプログラミングをしようとは思わないでしょう。でも、まともとさんのプレゼンを聞いて、ちょっと違和感を感じました。彼は、世界中で多くの開発者に使われている言語の創造者である彼は、ちょっとおかしな方向に行ってるんじゃないか? module という Ruby 言語の要素が偉大なものであることは誰もが認めるし私も異論はないのですが、彼のキーノートは、最初にこの言語が作られた時点でどういう狙いがあったか、その意図を羅列するだけに終始していました。

驚きを生むための基盤の構築

プログラミング言語は、自然言語と同じように、その基本的な文法をはるかに超えて、誰も予想もしないことを実現することができます。それが言語の驚くべき点のひとつです。私は、何年も前に、セル・オートマトンという全く違う種類の言語を勉強した時に、このことを学びました。セル・オートマトンは、予想を超えたことを実現できるという点で、非常に豊富な実例を持っています。

こういう観点で見た場合、全てのプログラミング言語が同じとは言えません。Ruby は、この点で柔軟性が高い言語として知られています。Ruby はプログラマに、ひとひねりしてからものを作るという他の言語にはないような自由を与えてくれます。ある意味では、「言語を作るための言語」と言えるかもしれません。まともとさんがキーノートで話したように、ここには、プログラミング言語そのものへの愛が、こめられています。

でも、Ruby の柔軟性は、それだけでできているのではありません。同じように重要な要素として、そのオブジェクトモデルがあります。まともとさんは、この点についてもう少し言及してもよかったのではないかと私はちょっと思います。

私がそれに魅せられるのは、このオブジェクトモデルが本当にシンプルだからです。Ruby は時に、perl や smalltalk といった他の言語の寄せ集めのように感じることもありますが、核となるモデルについてはそういうことはありません。それは、本当に統一的でスッキリしています。それどころか、一見ゴチャゴチャしているように見える要素が、このオブジェクトモデルを通して見たとたんに、急に腑に落ちて意味がわかってくることさえ多々あります。

この図は、Paolo Perrotta 氏による “Metaprogramming Ruby” [訳注: 日本語版]にあるものです。この本は、Ruby を本格的に勉強したい方にはオススメです。この図は、Ruby の核となっているオブジェクト、Object,Class,Module と自分で作成したクラスである MyClass とそのインスタンスの関連を示しています。オブジェクトに対するclass とクラスに対するsuperclass という二種類の関係が図示されています。

この図の興味深い所は、同書にあったオリジナルの図では省略されていたので私が赤い線で追加したものですが、この赤い線が意味すること、つまり「Module のクラスは Class」 であるということです。つまり、”Module is a class“、(大文字Mの Module は class である)ということです。これが[Rubyの]オブジェクトモデルの基盤であり、これがなければ全部バラバラになってしまいます。

まともとさんはキーノートで、一見これと逆のこと、つまり “a module is not a class” という話をしていました。なので、私は自分の発表でここに至った時、ちょっと言い訳をする必要がありました。まつもとさんが言っていたのは、Module というクラスの インスタンス についてです。まつもとさんの言っていたこと(“a module is not a class”)と私がここで主張していること(“Module is a class”)は両立します。大文字Mではじまる Module と小文字m ではじまる module は Ruby の中では全く違ったものを指します。

Ruby のオブジェクトモデルを再考する

なんで私が、Module がクラスであるかについてこんなにこだわっているのかと言うと、「もしまともとさんに先に言われちゃったらどうしよう」と私が心配していたのが、まさにこのスライドなんです。このスライドの冒頭にあるのが”Module is a class”という文です。

以下の4つの文が書かれています。どれも、Ruby のオブジェクトモデルについてのあたりまえの話です。

  • Module is a class [Module はクラスである]
  • A class can have subclasses [クラスはサブクラスを持つことができる]
  • (Sub)classes can define methods [(サブ)クラスにはメソッドを定義できる]
  • Modules can also define methods [ Module にもメソッドを定義できる]

ひとつひとつは、ただオブジェクトモデル内に見られる属性をそのまま述べているだけですが、この4つをつなげてひとつのクラスを作って見ると、見たことのない驚くべき性質が生まれます。これが、”Module Builder” と私が呼ぶひとつのコンセプトです。実行時に一部のメソッドを動的に作成する、Module のサブクラスです。

下に RubyKaigi の発表ブログ記事で使ったサンプルを示します。この AdderBuilder というクラスは、加算のメソッド(+)を持った module を作成します。そのメソッドの実装は、initializer で keys として与えられたアクセッサに対応する加算処理になります。

class AdderBuilder < Module
  def initialize(*keys)
    define_method :+ do |other|
      self.class.new(
        *(keys.map { |key| send(key) + other.send(key) })
      )
    end
  end
end

Point = Struct.new(:x, :y)
Point.include AdderBuilder.new(:x, :y)

p1 = Point.new(2, 3)
p2 = Point.new(1, 2)
p1 + p2
#=> #<Point:.. @x=3, @y=5>

この AdderBuilder の本当に凄い所は、その柔軟性にあります。これは、任意の アクセッサの組合せに対応した module を生成します。ですから、このひとつのクラスが、さまざまな用途に使用できます。

LineItem = Struct.new(:amount, :tax)
LineItem.include AdderBuilder.new(:amount, :tax)

l1 = LineItem.new(9.99, 1.50)
l2 = LineItem.new(15.99, 2.40)
l1 + l2
#=> #<LineItem:.. @amount=25.98, @tax=3.9>

このアイディアについて 私のブログエントリ で、詳細を説明しています。そして、 Mobility という gem の開発においては、この module builder pattern を多用して、柔軟でありながらもよくカプセル化された抽象的なクラスを作成しています。もし、このアイディアに興味を持たれたら、ぜひ、これを現実の場面でどう使うのかを知るために、この gem を参照してください。

古さの中にある新しさ

この Module Builder について私が一番驚かされたことは、これはほとんどの Rubyist にとってなじみのない新しいコンセプトであるのに、実際の所どういう意味でも新しいものとは言えないことです。module や それに関するオブジェクトモデルは Ruby の初期からあって変化していない概念ですが、この新しいコンセプトが依存しているのは、そういう古くからある要素だけです。これを実装するのに、新しい言語要素は一切不要なのです

だから、まつもとさんと彼にインスパイアされている多くの Rubyist が、この言語で新しいことをするのに、言語の新しい要素にばかり注目するというのは、ちょっと違うんじゃないかなと私は感じています。

Ruby はもう若い言語と言えないことは否定できません。その開発者は、白髪が目立つ年齢に達しています。多くの Rubyist もそうでしょう。スポーツカーを買って、若返った気になるように、言語に何か新しい機能を追加して、その言語が若返ったように感じたいという誘惑はあります。( 今だと、Type [強い型付け]とかが、ずいぶん 流行っているようです)。それが適切な場合もあるし、そうでない場合もあるでしょう。

私が、ここでハッキリさせておきたいことは、Ruby にはまだまだ多くの秘密が隠されていて、その多くを私たちはまだ知らない ということです。この言語のコアにある柔軟で、これ以外にあり得ないオブジェクトモデルから生まれてくるはずのものが、まだまだたくさんあるでしょう。それはとてもとても単純だからです

私が言いたいことはこうです。「みんなが大好きなこの言語について、もう一度見直してみませんか?よく見てよく知りましょう」

なぜなら、プログラミング言語の興味深い特質は、[与えられた通りに使うしかない]巧みな設計ではなく、[さまざまなアイディアの源泉となりうる]巧みな設計から立ち現れてくるものだからです。たぶん前者はもう十分であり、それに対して後者にはまだまだ可能性が多くあるからです。

一緒にユニークな決済サービスを作ってくれる Rails エンジニアを募集中です!
多国籍なメンバーと一緒に仕事をしてみませんか?詳細はこちらのリンクです:D