トレタ開発者ブログ

飲食店向け予約/顧客台帳サービス「トレタ」、モバイルオーダー「トレタO/X」などを運営するトレタの開発メンバーによるブログです。

RubyKaigi2017とModule Builder Pattern #rubykaigi

サーバサイドエンジニアの中村です。先日開催されたRubyKaigi2017に参加しました。 その中で最も興味深かったセッションである The Ruby Module Builder Pattern について自分なりの理解をまとめてみようと思います。

Moduleの問題

module内でdefine_methodを使ってメソッド定義を行ったmethodに対して、そのmoduleをextendしたclass内で該当のメソッドに対して super を呼び出すことができません。

module AdderDefiner
  def define_adder(*keys)
    define_method :+ do |other|
      self.class.new(
        *(keys.map { |key| send(key) + other.send(key) })
      )
    end
  end
end

class LineItem < Struct.new(:amount, :tax)
  extend AdderDefiner

  define_adder(:amount, :tax)

  def +(other)
    puts "Enter Adder..."
    super.tap { puts "Exit Adder..." } #=> No Method Error
  end
end

これは、+ methodが define_methodを使ってmodule内 で定義されているため、super で呼び出す祖先Object内で+ methodが定義されていないためだと認識しています。

これを回避するために、Anonymous Moduleを使ってこの祖先Object内で定義済みにするテクニックを今回のセッションで初めて知りました。

module AdderDefiner
  def define_adder(*keys)
    adder = Module.new do
      define_method :+ do |other|
        self.class.new(
          *(keys.map { |key| send(key) + other.send(key) })
        )
      end
    end
    include adder # この時点でAnonymous Moduleをincludeすることでsuperが利用可能
  end
end

このテクニックを応用したパターンがModule Builder Patternです。

The Ruby Module Builder Pattern

発表者の @shioyama さんに Module Builder Pattern を理解するための良いサンプルコードはありますかと質問したところ、 http://dry-rb.org/dry-equalizer というgemのコードがオススメだと教えていただきました。

そこで、本記事では dry-equalizer のコードを例にModule Builder Patternを理解していきたいと思います。

dry-equalizer

dry-equalizer gemはincludeしたclassの以下4つのmethodを再定義します。

Object#inspect
Object#hash
Object#eql?
Object#==

具体的な挙動は Examples のようになります。この挙動を踏まえて実際のコードを見ていきましょう。

Module Builder Patternのポイントは、Module.class #=> Class であることを利用して、動的にModuleを生成している部分です。

class Equalizer < Module

このように、Equalizer classを Module のsubclassとして定義することで、Anonymous Moduleのメリットが利用できます。

次に、included を見ていきます。

def included(descendant)
    super
    descendant.send(:include, Methods)
end

Equalizer が他classにincludeされた際に、

def eql?(other)
    instance_of?(other.class) && cmp?(__method__, other)
end

def ==(other)
   other.is_a?(self.class) && cmp?(__method__, other)
end

をincludeして再定義します。

そして最後に initializeです。

def initialize(*keys)
  @keys = keys
  define_methods
  freeze
end

初期化するkeyを受取り、define_methods を実行し、cmp?, hash, inspectを定義します。

このように、Module Builder Patternを使うと、非常にわかりやすくメソッドを動的に生成することができます。

おわりに

私はAPIのコードを書く上で常に設計についてどうするのがより良いか、チームの人と議論することが多く、今回のModule Builder Patternのような話は良い設計の1つのテーマとして非常に良いお話でした。

http://dry-rb.org というRubyの素晴らしい設計を集めたリポジトリも今回のRubyKaigiに参加するまでは知りませんでした。他のリポジトリのコードからも学びつつ、社内で良い設計とは何かについてまたさらに議論したいと思います。

またありがたいことに、弊社では国内・海外のカンファレンス参加は出張扱いになっており、カンファレンス参加費・交通費・宿泊費(一部)は会社負担になります。業務として色んなカンファレンスに参加したい!という方はぜひご応募お待ちしています。

iOSDC 2017に参加してきました

iOSエンジニアの高です。

去年に引き続き、今年もiOSDCに参加してきました。

iosdc.jp

今回は前回以上に色んな所がパワーアップしていて、運営のみなさんの本気を感じました。 トレタとしてはゴールドスポンサーとしてスポンサードさせていただいています。 バッグの中にお風呂♨️のチラシがありましたよね。あれが弊社です。

またスポンサー読み上げをアークエンジェル艦長のマリューさんにして頂けるとはなんとも嬉しい限りです。
iOSDC Japan 2017 スポンサー紹介 - YouTube

弊社登壇メンバー

弊社からは増井と堀見が登壇しました。

増井はトレタ初のBluetoothデバイスの開発について。 堀見は誰もが悩むログ収集について登壇しました。

f:id:y_koh:20170917133256j:plain 初めて作るIoT機器とBLEの光と闇 | iOSDC Japan 2017

ここで話していた実際の製品はこちらになります。トレタフォン ボックスタイプ

f:id:y_koh:20170917162326j:plain サポート効率を上げるログ収集環境の構築 | iOSDC Japan 2017

気になったセッション

以下、個人的に気になったセッションをいくつか上げていきます。

Build high performance and maintainable UI library | iOSDC Japan 2017
パフォーマンスの話だけでなく、テストしやすいUIコンポーネントの書き方に至るまで幅広い内容でした。 iOSエンジニアであれば誰でも一度はViewControllerになんでもかんでも書いてしまうと思うのですが、テストしやすくするために、データの流れを一方向にして、状態をモデルに分離することが大切とのことです。

アプリエンジニアはどのように事業に貢献すべきか | iOSDC Japan 2017
Fablicのhuinさんの発表。発表を聞いていて非常にトレタと同じ悩みを持っているなと感じました。アプリエンジニアはアプリの使い勝手を良くしたり、ユーザーに喜んでもらえることを一番に考えることが多いと思います。ただ、それだけでは足りなくて、当然ビジネス的な観点も必要になってくるんですよね。

何を持ってユーザーが喜んでいると判断するのか、と質問してみたのですが、定性的にはアプリのレビュー等、直接聴こえてくる声を。定量的にはAnalyticsの結果を元に判断しているとのことでした。

Human Interface Guidelinesから滲み出る限界感を考える | iOSDC Japan 2017
Human Interface Guidelines(HIG)を守れと言うけれど、最近のAppleの標準アプリも守ってないのでは?というところから始まり、HIGとは何なのか。どこまで守ってどこからはみ出してもよいのか?という話でした。

HIGを狩野モデルを用いて解説しているのがとても印象的でした。

触り心地の良いInteractive Transitionをマスターしよう | iOSDC Japan 2017
さわり心地の良いアプリ。アプリエンジニアであれば誰もが目指すところですよね。このセッションではeasing curveに始まり、durationはどれくらいがベストなのかなど、具体的な数値を見せてくれているのがとても貴重でした。

iOSデバイス3,500台を管理する、東急ハンズのデバイス管理手法とは | iOSDC Japan 2017
普段聞く事の少ないMDMのお話。MDMというのは端末を管理するためのもので、管理側でアプリをインストールしたり、端末でできることを制御することが出来ます。普段聞けない話ということもあってとてもおもしろかったです。

業務アプリの切札、Programable Kiosk Mode大全 | iOSDC Japan 2017
こちらもなかなか聞く事の少ない話の1つですね。iPadにはSingle App Modeという1つのアプリしか立ち上げられないモードが有ります。KIOSKスタイルで専用端末や、店頭で展示する場合なんかに使われています。

クラッシュした時の話が面白くて、おそらくOSバグだと思うんですが、Single App Modeでクラッシュするとそのアプリだけでなく、他のアプリも一切起動できなくなるという恐ろしい現象が起きるそうです。一応ワークアラウンドも紹介されていましたが、完璧ではないそうです。

まとめ

今年のiOSDCもとても楽しめました。運営の皆さんには感謝しかありません。 どれも興味のあるセッションばかりで、直接見れなかったものに関してはこれからキャッチアップしていこうと思っています。

今年も素晴らしいiOSDCをありがとうございました。

トレタはRubyKaigi 2017に参加しています

サーバーサイドエンジニアの芹沢です。広島のホテルでこのエントリを書いています。

トレタはSilver SponsorとしてRuby Kaigi 2017にスポンサードしています。
また、トレタからは私を含むエンジニア3名とCTO増井が参加しております。

トレタはスポンサーブースは設置しておりませんが、増井が会場中を歩き回っておりますので、会場で見かけたらお気軽に話しかけてみてください。

f:id:serihiro:20170918102225j:plain

また、今回参加するエンジニア3名がそれぞれこのブログにて参加レポートを書く予定です。
そのレポートの中では、事前に決めた各自の担当セッションについて解説する予定です。こちらもご期待ください。

さきほど初日のセッションが全て終了しましたが、とても濃いセッションが多い1日でした。

ruby commiterであるnobuさんのruby開発生活を紹介するキーノートから始まり(nobuさんのトークはruby界隈では大変貴重です)、

  • RailsにおけるAPI開発のトレンドの移り変わりと最近の取り組み
  • productionで動作しているRails appを用いたベンチマーク環境の構築
  • opalでdruby対応した話
  • web application frameworkであるhanamiの紹介
  • pycallの紹介とデモ
  • 去年もすごく盛り上がったruby commiters vs worldのコーナー

という、以前から興味のあった話題が沢山聞けてとても楽しかったです。(英語トークもあってとても疲れましたが。。) 残り2日も楽しんでいきたいと思います。

f:id:serihiro:20170918184154j:plain

© Toreta, Inc.

Powered by Hatena Blog