いつもの開発のようにOSS開発をしよう

makicamel(@makicamel)氏:それでは「いつもの開発のようにOSS開発をしよう」というお話をします。よろしくお願いします。

ちなみにちょっと爆速でしゃべりますが、さきほどTwitterにも資料を流したので、よければそちらもご覧ください。

自己紹介をします。株式会社ITMONO(いつもの)から来ました、makicamelという名前で各種アカウントをやっています。Ruby歴とRails歴は3年ぐらいで、今ここにいる方とわりと同じぐらいだと思います。あと、Rubyと同じくらいビールとお酒が大好きなので、懇親会ではぜひ仲よくしてください。

本題ですが、OSS活動ってみなさんどんなイメージを持っていますか? 私は前回もTokyoGirls.rbに参加したんですけれど、そのときはこんな「OSS活動ってつよつよエンジニアがするものだし、私はそんな技術ないし、なんか100年早いし、怖いし……」みたいなイメージを持っていました。

ですが今日のタイトル、みなさんさっき聞きましたよね? 「いつもの開発のようにOSS開発をしよう」。なんか「こんなひよっこが、なんてタイトルを打っちゃったんだろう?」みたいな感じで、不安がやってきたんですけど。でも、もう1回言います。「いつもの開発のようにOSS開発をしよう」です。

モチベーションとしては、やっぱり私、図のような思いがすごく強かったんですね。けれどもこれって、根拠のない不安だなというのもすごくあって。「まさかり飛んでくるかもしれない」みたいな、そういう不安もあったんですけど、でも実際やってみたらそんなことはないのかなって。あくまでも根拠のない不安なので、自分がそれを乗り越えた過程を紹介すれば、誰か1人でもOSS活動をやってみようかなって思うかもしれない。そう思って今日はこの話をします。

前後半に分かれるんですけど、前半は実際の事例を紹介しながらお話をしていきます。

DeviseというRubyのGemを実装

ある日、こんな要件がありました。「メールの変更機能を実装してください。変更時には新しいアドレスに確認メールを送るようにしてください」。わりとよくある要件だと思います。 そこでGemfileを見てみたところ、「devise」と書いてありました。

Deviseについては、たぶん多くの方がご存じだと思うのですが、認証用の機能を実装するGemです。いろいろなモジュールをincludeすることで認証用の機能を実装でき、さきほど言ったようなメールの認証変更、メールアドレスの送信、メールの送信とかもこれが担ってくれます。

やり方もすごく簡単で、専用のカラムを追加して、マイグレーションして設定。あとはふだんどおりに保存、アップデートするだけでメールが送信されるんですけれども、まぁちょっと、なにも起きないわけですね。

「なんでかな?」と思ってコードを見にいきます。これはDeviseのConfirmableのコードですが、ここのsend_reconfirmation_instructionsがメール送信を担っていて、これは再確認が必要だったら呼ばれるんですね。

この再確認が必要というのはどこで定義されるかというと、ちょっと読めないくらい長いんですけど、ここのメチャクチャ長いメソッドが呼ばれたときに、もともとfalseだったのがtrueになりますよ、というふうになっていて。これがpostpone_email_change?(メールの変更を延期する?)という判定がtrueになったときだけ呼ばれるんですけど、これが常にfalseになっていました。

「あれ、おかしいな?」と思っていろいろ調べてGemfileを見てみたら、どうやら「devise」だけではなくて「devise_token_auth」も使われている。

じゃあDeviseTokenAuthはなんだろうと思って見てみると、APIサーバ向けの認証用Gemになっていて。つまりトークンベース認証のGemです。Deviseの機能を活用したり、Deviseと併用できるGemですね。

それで調べてみたら、ありました。「DeviseTokenAuthがDevise::confirmableとDevise::reconfirmableを壊してますよ」というIssueがあがっているんですね。

こんどはDeviseTokenAuthのコードを見てみると、こちらも書いてありました。「# don’t use default devise email validation」、「えっ?」みたいな(笑)。

(会場笑)

「# don’t use default devise email validation」ってこれのことなんですね。「いや、そりゃ使えないわ」……というわけで、どうしたかというと、Deviseの標準の機能をこれが壊しているんですね。なのでお仕事のコードは、とりあえず応急手当てで処置をして。

でも、これ一番古いのは2015年なんですけれども、似たようなIssueがパッと調べただけでもこのぐらいはあがってくる。ということは、困っている人がいっぱいいそうなので、「これはもしかしてコントリビューション・チャンスなのでは?」と思ってがんばりました。がんばった結果、マージされました。

(会場拍手)

ありがとうございます。

PR(Pull Request)でやったこと(1):調査と修正

ではこれのPR(Pull Request)でなにをやったかを見ていきたいんですけれども、まずは調査と修正をやりました。今日も「まずは意図を知る」というたださんのお話があったと思います。

DeviseTokenAuthで「will_save_change_to_email?」をfalseにオーバーライドしているのですが、これはどうやら、DeviseのValidatableというモジュールがあって、DeviseTokenAuthではここのvalidationをスキップしたいらしいんですね。これはこのまま使いましょう、使いたいですねというのがあって。

でも、DeviseのConfirmableというモジュールは、このwill_save_change_to_email?がfalseになっていることで、常にさっきのpostpone_email_change?がfalseを返しちゃっているんですね。でも、このvalidationはスキップしたくない。

つまり、Deviseで使っているモジュールが2箇所あって、Validatableでは常にfalseを返したい。でも一方で、今の挙動のままでいたいので、Confirmableでsuperしたい。「じゃあどうすればいいの?」みたいな感じの気持ちになるんですけれど。

そもそも「will_save_change_to_email?ってなんですか?」って思ったんです。Deviseのコードをgrepしても出てこなくて、何かな、と思ったらどうやらRails側で定義されているメソッドのようで。いや、メソッドというかActive Recordが準備してくれている動的なattributeになっていて、will_save_change_to〜というのが各モデル、各カラムに生えるんですね。値が変更されたらtrueを返すし、DBの値と同じだったらfalseを返すものです。

ここがポイントなんですけど、今回だったら変更される前の値はemail_in_databaseで取れるんですよ。つまり再実装ができるんですね。「あっ、やった!」と思って、こんな感じにしました。

DeviseTokenAuth側でpostpone_email_change?というのをオーバーライドして、もともと「 will_save_change_to_email?」 だったのを「email_value_in_database != email 」で再実装をしました。

そしたら、DeviseTokenAuthのもともとのwill_save_change_to_email?……これめっちゃ長いくて言いにくいんですね(笑)。この「will_save_change_to_email?」というメソッドは、もともとオーバーライドしたまま、Validatableモジュールの挙動を変更しない、というのができるようになっているので、これで修正完了です。よかった。

PRでやったこと(2):後方互換性の維持

PRでやったことその2は、「後方互換性の維持」です。どういうことかというと、今までDeviseTokenAuthを使ってDeviseを使ってた人は、確認メールがこの機能では送れていないはずなんです。手元でパッチを当てたりとかしているはず。

それが例えば、bundle updateをしたら急に挙動が変わるのはよくなくて。メールが二重に送信されてしまったりとか、今までメールを送れないはずだったのにそれが送れるようになったりすると、エンドユーザーに直接迷惑がかかっちゃいます。

なので、デフォルトはメールを送信しない、設定をしたらメール送信するというフラグを入れました。それが、このDeviseTokenAuthの「send_confirmation_email」というフラグです。このフラグを設定したときだけ、さっきのオーバーライドをする変更を入れました。

これにプラスして、ドキュメントに説明を追加して、configのジェネレーターがあったので、そこに設定値を追加しました。

PRでやったこと(3):テストの追加

その3は、テストの追加です。今日はテスト番長が主催をされているイベントなので(笑)、当たり前だけどやるわけですね。

(会場笑)

環境構築やテスト方法は、CONTRIBUTING.mdのファイルにあることが多いです。ContributionGuideというもので、これは環境構築とかテスト方法に限らず、コントリビューションの方針がいろいろ書いてあるので、最初に目を通すとよいと思います。

あと余談なんですが、これは設定値のテストのやり方がわからなかったので、「こんなんでいいのかな?」と思いながら書いてしまいました。よければあとで誰かアドバイスをいただけるとうれしいなと思っております。

PRでやったこと(4):マージされる努力

このPRでやったこと最後は、マージされる努力です。

さっきのたださんのお話でもあったんですけど、伝わるコミットというのは粒度がやはり大事だなと思っていて。「このぐらいが適切かな?」ってわかりやすいような粒度で切ったりとか。

あとは「なぜ?」というのを本文に書くのを意識しました。「どうやって?」というのは実装を見ればわかるので、「なぜこうしたのか?」「このコミットはなにをしたのか?」というのをコミットメッセージに書きました。

あとは、わかりやすいPRを目指すということで、概要とか問題・必要性についてはIssueですでに語られているので、それはIssue側に譲って、やったことの概要を大きく2つに分けて書くことにしました。

それでとくに今回は、関連、依存するGem側との実装がぶつかり合いみたいな感じだったので、マージしてくれる人が把握しやすくなるように、現状の実装と問題の発生の理由、実装ポイントなどを書きました。

そして、相談ですね。やっぱりこれもコードレビューの話なんですけど、コードをプッシュしたときにcodeclimate、まぁlinterみたいなものに指摘を受けたんですね。「処理が似たコードブロックがありますよ」って。

ちょっとパッと見わからないぐらい本当に似てるんですけど、これはDeviseのもともとの実装の形だったんですね。なので、「合わせたほうがオーバーライドしていることがわかりやすいと思ったんですけど、どう思いますか?」と聞いてみたら、そのコミッターの人が「まずリファクタしたいです」と。さらにプラスして「このモジュールが責務を持ちすぎているので、別のモジュールに切り出したいです」と言ったので、実際そういうふうにしました。

相談してよかったなと思ったのは、もともと自分だけだったらリファクタで終わりだったなと思うので、プラスしてモジュールを別に切り出せたのがよかったなと思いました。

まとめてみるとこんな感じなんですけれども、振り返るとわりと普通じゃないですか? なんかいろいろ……いや、普通かなと思って。

なにが普通なのかなと言ったら、いろいろやったのはやったんですけれども、これっていつものお仕事でやっていることと同じだなって思ったんです。なので、OSS開発だからといってとくにすごく難しいことをやっているとか、なにか特別なことをやっているわけではないんですね。というのが今日一番言いたいことです。

ただいつもと違うことももちろんあって、やっぱり言語は英語が多いです。あと、相手が目の前にいないことが多い。基本的にインターネット上でのやりとりだなと思います。また夜とか休日にやっている人が多いので、レスポンスの早さがけっこう緩かったりとかします。あと、これがちょっと自分の中で難しいな、というか大変だなと思ったのが、コードのコンテキストがわからないこと。

なので後半では、OSS開発で逆にとくに大変だなって思うことについてお話しします。

OSS開発で大変だったこと

OSS活動についてこんなことを思っていたことがありました。「継続的に続けてこそ価値があるんじゃないだろうか?」と思ったんですけど、もちろんそんなわけはないわけですね。自分ができるときにできるペースで関わればいい。だってお仕事じゃないわけですし、OSS活動なので、自分が好きでやっているわけですし。

でも、継続しないとやっぱり大変なこともあって。それがコンテキストがわからないということ。設計とか歴史的経緯において過去どんな議論があったかとかって、やっぱり継続的に関わっていかないとキャッチアップが大変だったりするんですね。

ですがこれって別にOSS活動に限ったことではなくて。私は12月1日に転職をしたんですけど、そのときもまったく同じことがあって。「あれ、このコードってどこにあるんだろう?」とか「この過去の議論ってなにがあったんだろう?」というキャッチアップが大変だったんですね。別にこれって特別なことじゃなくて、チームに新しくジョインしたときには必ず起こる問題なんです。

なので、OSSだから大変なわけじゃなくて、新しくプロジェクトに関わるから大変というだけで、OSSは特別なことじゃないと思いました。

それから、わからないことってたくさんあって。とくにコードがわからない。でも、仕事のコードも難しいものは難しいじゃないですか。これも特別なものじゃないし、メタプログラミングは私もわからないので、「勉強します」みたいな感じですね。

それから、「難しいなにか」がわからないということなんですけれども、わからないことはたくさんあると思います。今日、塩井さんの発表を聞いていてすごく印象的だったのは、わからないことをわかるようになるのをすごく楽しんでるなという印象があって、それってエンジニアの醍醐味のひとつだなって思うんですね。なので、このわからないことがたくさんあって、やることいっぱいあるみたいなのって、むしろ特別だし楽しいと思っています。

それでわからないなら、知ればよいんじゃないかということで、@sinsokuさんがすごくいいpostを書いてくれてるんですね。「Railsのissueを解決するまでの手順とOSS初心者でもできること」というpostで、それでもハードルが高いと思っている人向けに、いくつか初心者向けにできることを紹介しています。

それが「rails/railsのIssueの中から興味あるタイトルを読んでみる」というプラクティスで、「Issueを全部読むのは大変なので、自分の興味のあるところを読んでみるとよいと思います」って書いてあって。

私、これをやってみたんですね。10個ぐらいもいかないので、毎朝、前日のRailsのIssueを全部読んでみるというのをやったんですけど、わからないままあっという間に時間が溶けていったので、最近の習慣は、毎朝rails/railsのIssueまたはPRを1つ以上見るようにしています。

でもなにもわからないです。この間DHHが「モナドを入れようぜ!」みたいな感じでワクワクしてたんですけど、「えっ、モナドってなんでしたっけ?」みたいな感じで終わる朝もすごくよくあります。

あと、これやってよかったなって思っているんですけど、「なにもわからないことがわかった」というですね。今までは、Railsっていうなんかすごく巨大ですごいものが、なんか知らないけど動いてる、みたいな感じだったんですけど、わからないものはすごく無限大にあるんですけど、これが具体化されたことで、「わからん」「怖い」という漠然とした苦手意識がなくなりました。これはオススメです。

不安に関してはみんなやさしい

最後です。不安に関してなんですけど、みんなやさしいです。前回のTokyoGirls.rbの懇親会で、そこに座っているようさんに「ようさんが作ったライブラリがすごくおもしろいと思います。ただ、うまく起動できなくて……」って言ったら「ぜひ見せてください!」って言われたんですね。

「自分が間違っているだけだと思うんですけど……」と言ったら、なんて言われたと思います? 「それはそれで、こんなふうにミスしやすいんだなって参考になるから大丈夫ですよ」って言われて、いや本当にやさしいなと思ったんです。

なんかOSSってこういう気風があるなとすごく思うんですね。初心者に対してすごくウェルカムだし、できないとかわからなかったことに対してマウントを取る人っていないなと思っていて。なので、安心して飛び込むだけだなって思うんですけれども、私はこの結果、ようさんのリポジトリで、初めて人生でIssueをあげるということができました。

最後まとめです。OSS開発、大変なことはたくさんあるけれども特別なことじゃないので、ぜひ興味のある方はやってみてください。そのときに、今日見た中で好きなリポジトリを今日帰って開いてみて、そのIssueタブを開いてみるとよいんじゃないかなと思います。参考は先人たちがいろいろ書いてくれているので、ぜひ見てください。

以上です。ありがとうございました。

(会場拍手)

司会者:どうもありがとうございました。いい感じに第1回から第2回につながっているというところで、次の第3回にも誰かつなげてほしいなと僕は思いました。