アプリリニューアルを楽しくやりきる話

こんにちは。レシピ事業開発部 クロスファンクショナルグループの @kaa です。

クックパッドAndroidアプリは昨年秋にフルリニューアルを実施しました。 リニューアル内容としては半年ほど先にiosでリニューアルを実施したものを導入になります。 弊社はこのリニューアルプロジェクト開始の2ヶ月ほど前からリモート主体の勤務体制になっており、期間中は週1で出社という状況でした。まだリモート勤務にもみんなが慣れているとは言えないタイミングでの実施となりました。

このプロジェクトのため3ヶ月程度の期間、部署横断でメンバーを集め進めました。 体制は以下の通り。

  • アプリエンジニア6名(1名はAPI兼任)+決済・基盤・テストのサポートに2名
  • デザイナー2名(デザインディレクション+1名)
  • ディレクター3名(PdM,PjM,開発ディレクション)

このプロジェクトについて、開発ディレクションの立場から楽しくやるために行っていたことをお話します。

モチベーションに関する課題

評価に対する不安

部署横断プロジェクトにありがちな課題ですが、メンバー本人の年初にたてた個人目標・チーム目標とは直接関係がない仕事をすることになります。 自分の仕事に対して評価が行われるのかわからない、最終評価者は詳しく見ていない、さらには自分がやりたいと考えていた今年の仕事とは異なる可能性もある。

この課題の対応のため、開発進行をしている人(自分ですが)が期末の追加の評価者として開発メンバー全員の評価にディレクションの立場から参加するということを事前に決めました。

主体性を持ってもらうための仕組み

人がパフォーマンスを出す条件として、次の3点を考えています。

  • やりたい仕事であること
  • 裁量があること
  • 仕事に集中できること

やりたい仕事であること

初耳の、3ヶ月拘束される本来の仕事と違うプロジェクトでいきなりパフォーマンスが出せる人はまずいません。 さらに今回は別プラットフォームでリリース済みのことを実装なので新規性もありません。 どうやって自分のやりたい仕事だと思ってもらうかが必要になります。

まず、参加する開発メンバーにいまのアプリ開発で改善したい点をだしてもらいました。

参考:大規模プロジェクトにおけるモバイル基盤の取り組み

長く運用しているアプリですので棚卸ししたい負債や制定したい実装ルールは溜まっています。 minSdkVersionあげたい、マルチモジュール化すすめたい、遷移ルールの統一、スタイルの再定義などなど。やりたいけど実施タイミングがとりにくいものはたくさんです。 これらの話題を事前に時間とって話し合い、共通の理想とする実装方法・改善をまとめます。今回は普段は基盤チーム(弊社ではサービス開発と開発基盤は部署として分かれています)に所属しているメンバーも多く参加しておりプロジェクトの事前準備の段階から関わっていました。

そしてこれらを実現できるプロジェクトとして進めました。他の部の仕事にお手伝い参加ではなくいま自分達の考える理想のアプリ開発に近づける仕事にしていきます。

裁量があること

各メンバーに対して、任せたタスクについてはほぼ一任しました。 仕様は事前に細かく詰める、でも仕様の実現方法については任せきります。 条件はコードレビューが通ること。 (クックパッドではPRのマージには一人以上のapprovedが必要です)

これだけでは実装方法にばらつきが発生しそうですが、事前に実装方法についての方針を開発陣で話し合って方針を決めているため、そこから外れることはありません。自分達の考えたルールに縛られるのはつらいことではなく自分達の理想を実行している状態ですので、やりたいようにやりつつ統一された実装方法で進めている、という状態になります。

また、仕様の実現が難しい場合はいつでも相談が可能としました。 実装して触ってみないとわからない問題はどうしても起きるものですしその画面について一番時間を使っているのは実装者本人なので気付ける改善も必ずあります。

ただし、相談には本人のどうしたらいいと思うかをあわせて伝える、というルールです。 どうすればよくなるか考えるきっかけにもなり、同時に仕様策定者に対する別の視点の提供になります。実際ほとんどの場合は開発者の意見をそのまま採用しました。 NGの場合は明確な理由があるものなので説明します。サービスの方向性の目線合わせもかねて。

集中できること

基本的に、人は考える必要のあることが少ない状態にあるほどパフォーマンスが上がると考えています。 考えてもすぐに結論のでないことはいくらでもありますし、違う話を理解するのも脳と時間のコストがかなり持っていかれます。スイッチングコストは本当にたいへん。

今回は2週間単位にフェーズを切り、タスクは画面単位に分けました。 その期間中、または完了するまでの間、他の人のコードレビュー以外で担当画面以外のことを考える必要がない状態を目指しています。

タスク単位を判りやすくしたのは、実装者の成果をわかりやすくする意味合いもあります。〜〜をやりました、とわかりやすく言えると評価に限らず仕事の実感としても感じやすいことを狙っています。 画面単位の実装段階は2つにわけ、機能実装と最終デザイン反映を別にしました。これは複数人でフェーズ単位の進め方をすると各実装のデザイン確認の時期がフェーズ終盤に集中し実装者に待ちが発生するのを避けるためです。機能実装が完了した段階ではデザイナーのチェックをなくし(スタイルは反映されているため大きく破綻はしません)、エンジニアは次のタスクに移ることが可能になります。

弊社では通常時はUI変更がある場合にデザイナー確認なしでのPRのマージは禁止ですがこのプロジェクト中は例外としました。

リモートにまつわる課題

リモートではただでさえ距離感が難しくなりますが、今回はそもそも所属している部も異なるメンバーが集まっています。エンジニア同士であればリポジトリ上、slack上でのやりとりはしていたとはいえ、職種が変わるとこれまであまり関わりがない人もいます。実際に開発ディレクションの自分とほとんど話したことのない開発メンバーもいました。

レスポンスを確約する

質問したいことがあった際にすぐ反応がもらえるか、も重要ですが今回は質問に対していつ答えを出すかを事前に決めました。 その日のうちに質問しておけば、翌日の昼会で決定した内容を伝えます。昼会で話題にする、相談するでなく決定状態にする、です。持ち越しダメゼッタイ。ディレクションのメンバーもきっちり仕事していると見せないといけません。すぐに反応するとか相談できるではなく確定させるタイミングをルール化します。 いつ決定した仕様がわかるのかが事前にわかっていれば実装の段取りもたてやすくなります。 どんなことでも知りたいことは翌日には確定したものがわかる、という状況を作ります。もちろん即答できるものは即答です。

情報の公開

実装に集中すればするほど、slack追ってらんないし関係ないかもしれないzoom色々はいっていられない。 しかしいまプロジェクトでなにが話題になっているか知りたい時に知れる状態を目指します。 これが所属している部での仕事であればミーティングのルール整備といったことになりますがこれは3ヶ月の短期プロジェクトですので整備している暇はありません。

ではどうするか。ほとんどすべてのミーティングに参加している人が1人はいますよね、その人が全部やりましょう。今回の場合自分です。 大丈夫数ヶ月の短期プロジェクトならこれでなんとかなる。意地で議事録取り続ける、ミーティング終わったら整理してslackで共有。すべてを明文化です。

楽しくやる

いいものができてきていると言い続ける

リモートによらないことでもありますが、リモート主体であるからこそいま自分達がいいものを作っているという実感を得ながらやっていきたいものです。チームの皆が頑張っている様子を可視化します。

基本姿勢はホメ&ポジティブです。なにかできていたらこれすげーいいじゃんとかばっかり言ってました。 ディレクションとしては内心スケジュール間に合うかとか考慮もれがないかとか不安が色々と発生し続けてますが、それらはあくまで自分の責任であって、それをうまくやるのが仕事なので特に周りに伝える必要はありません、不安なとこ見せない。

メンバーにこのプロジェクトうまくいくか不安なんて伝えても集中できなくなるだけですし、不安は伝搬してしまうし自分の多少のストレス軽減になるだけでなにもいい効果を生んでくれません。 であればぶっちゃけるタイミング以外では不安を周囲に伝える必要はありません。

裏目標を作る

最後に、自分自身のモチベーションの話。 以前に別プラットフォームで行ったリニューアルの導入プロジェクト、どうしても単なる移植になりがちでモチベーションの確立が難しい部分があります。 このプラットフォームにあわせたUIを設計し、仕様に落とし込むのですがその際、先にリリースした時よりもさらに考えることは難しい。OSにあわせて自然に、という意識がどうしても働きます。要は無難なことをしがち。

なので意識的にプラットフォームごとにUIを変更する部分において、いくつかの指標について先にリリースしたものの数字を超えることを目標としました、個人的に。 とはいっても特殊なことをするのはダメですし以前のプラットフォーム(今回でいうとiOS)のものをそのまま導入するよりandroidにマッチしたUIである必要があります。プラットフォームへの最適化と数値目標の両立を目指します。導入するのはリニューアルの体験・コンセプトであって焼き直しや単なるOS最適化ではありません。

これにより画面仕様策定の楽しさが格段に上がります。別プラットフォームですでにリリースしたアプリとそのアプリでの数字は既に知っています。これから作るプラットフォームでのアプリでは先にリリースした時よりも理解が進んでいてもっといいものができますよね?

最後に

今回は短期・社内横断プロジェクトでのモチベーションの観点で話しました。

クックパッドではチーム開発をやっていきたいメンバーを職種限らず募集しております。興味のある方はぜひご気軽にご連絡ください。

emruby: ブラウザで動くMRI

こんにちは、フルタイムRubyコミッタの遠藤です。

Ruby 3.0が出てもう4ヶ月経ってしまいました。最近のTypeProfの開発ですが、vscode拡張として使えるようにするために、一生懸命Language Server Protocolをいじって遊んでるところです。

こっちのほうはまだ実験段階なので、まとまったころに説明するとして、今回は、Ruby 3.0リリース後にほそぼそとやっていたemrubyをご紹介してみます。

emrubyとは

ブラウザの上で動くMRI(Matz Ruby Interpreter)です。

「エムルビー」だと組み込み向けRuby実装の mruby と紛らわしいので、「イーエムルビー」と読んでください(とmatzに言われています)。

デモ

このページを開いてみてください。

mame.github.io

"Code"の下のエディタ部分にRubyコードを書き、Runのボタンを押すと、実行結果が"Result"の下に出てきます。

f:id:ku-ma-me:20210430180447p:plain

たとえば

p 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10

と書いて実行すると 55 と出てきます。

require "stringio"
p StringIO.new("foobar").read(3)

のように(一部の)拡張ライブラリも使えます。

JavaScriptでは考えにくいですが、同期的なウェイトも可能です。

puts "waiting..."
sleep 1
puts "done"

とても実験的ですが、JavaScriptコードを呼び出すことも可能です。

p emscripten_run_script_int(<<JAVASCRIPT)
(function() {
  var sum = 0;
  for (var i = 1; i <= 100; i++) sum += i;
  return sum;
})();
JAVASCRIPT

JavaScriptで1から100まで足して、その結果をRubyのKernel#pメソッドで出力します(いまのところ、intの返り値しか対応してません)。

技術的な話

原理的には、C言語ソースコードをWebAssemblyにコンパイルしてくれるEmscriptenを使ってMRIをコンパイルしただけです。

しかし現実的には、コンパイルだけでも細々とした修正や対応が必要でした。

  • Emscriptenでは使えないC APIをいろいろケアした(たとえばIO.popenはNotImplementedErrorにしたとか)
  • 保守的GCがそのままでは動かないので、Emscriptenが提供している保守的GC用のAPIを使うようにした *1
  • 動的リンクは実験的サポートらしかったので、必要な拡張ライブラリを静的リンクするようにした
  • その他こまごまとコンパイルオプションを調整した

これらの変更はRubyソースコードへのパッチにする必要がありますが、幸いコミット権限を持っているので、すでにmasterを更新してあります。パッチを管理しなくてすんでよかった。

コンパイルしてみたい人は、emscriptenを使えるようにして(Emscriptenのドキュメント参照)、Rubyのmasterブランチを次のようにコンパイルすると ruby.wasm などができるはずです。

$ ./configure \
  --build x86_64-pc-linux-gnu \
  --host wasm32-unknown-emscripten \
  --with-static-linked-ext \
  --with-ext=ripper,date,strscan,io/console,…,psych \
  optflags=-Os debugflags=-g0 \
  CC=emcc LD=emcc AR=emar RANLIB=emranlib

$ make

フロントエンド、といってもemrubyは全部フロントエンドですが、特にユーザインターフェイスの部分はNext.jsxterm.jscodemirrorで自作しています。↓のHackarade(社内ハッカソン)に乗っかってエイヤと作りました。

techlife.cookpad.com

想定問答

なんで作ったの?

RubyがWebフロントエンド市場に本格的に進出する足がかり!という意気込みが当初は少しだけありました。実際、WASMが話題になった2017年ごろは、ブラウザでも適材適所で言語を選べるのでは、という期待感があったと思います。が、最近のTypeScriptの隆盛を見ると、なかなかそういう感じにはなってないですね。やっぱりJavaScriptは強い。

しかしそれでも、RustやGoやKotlinなど、最近の言語はWASM対応をうたっていることが多いです。どの言語がどのマーケットをとるかは運ですが、動いてない言語は候補にもならないので、動くようにしておくことは大切かなと思っています。宝くじを買う気分。*2

などと適当なことをいいましたが、正直に言えばJust for funなところが大きかったです。ブラウザの上でRubyが動くのはそれだけで楽しい。

完成度は?

rubygemsやirbも含めて一応動いています。意外と動くなあ、という感じです。

https://mame.github.io/emruby/irb/

とはいえ、やはりEmscriptenは普通の環境ではないので、普通の環境のMRIに比べるといろいろ問題があります。たとえば、Fiberが動かない*3、Threadも動かない、など。もし興味のある人がいたら一緒に改良しましょう。

(ちなみにirbのデモではSharedArrayBufferを使っているのですが、これはChrome 91から制限が強化されるらしいので、Chrome 90以前でしか動かない見込みです。Chrome 91は5月にリリースされるらしいので、つまり、今しか動きません……)

なお、もし今すぐブラウザの上で動くRubyを書きたいなら、Opalを検討するのがよいと思います。他には、次の記事も参考になると思います。

blog.unasuke.com

まとめ

ブラウザの上で動くMRI、emrubyを紹介しました。遊んでもらえるとうれしいです。

先日銀座Rails#32でもemrubyについて話したので、発表資料を貼っておきます。Rubyのビルドプロセスや、Emscripten自体に興味がある人は面白いと思います。

www.slideshare.net

*1:マシンスタックやレジスタを走査してオブジェクトの参照を探すということをするのですが、そのためにスタックの先頭と終端を得るAPI emscripten_scan_stack やレジスタをスキャンするためのAPI emscripten_scan_registers がEmscriptenによって提供されていたので、それらを使うようにしました。

*2:似たような気持ちで、AndroidエミュレータでもRubyをCIテストしてたりします。こっちは意外と全テストが完走するのですごい。だれかiOSもやらないかな。

*3:emscripten_fiber_init や emscripten_fiber_swap などのAPIを使っているので、動くはずなのですが、minirubyでは動くけどrubyでは動かない状態です。原因もよくわからないので、デバッグが必要。

Cookpad Summer Internship 2021 (10 day Tech コース)を開催します!

f:id:fufufukakaka:20210426121451j:plain

研究開発部の深澤 (@fukkaa1225) です。今年になってエンジニアの立場から新卒採用を担当しています。

クックパッドでは、毎年恒例のサマーインターンシップを今年も開催します!本記事では、エンジニアコースについてご紹介いたします。

以下のインターンシップ特別サイトからご応募いただけます。

日程と講義内容について

エンジニアコースは、今年は 10 日間の日程で行います。

前半 5 日間は講義・ハンズオン形式です。 クックパッドのアプリケーション開発技術や、サービス開発のノウハウについて学びます。 開発技術として、モダンなフロントエンド化のために採用した React、TypeScript、Next.js、クックパッドを長く支えているRuby on Rails、AWS などを題材に講義を実施します。 サービス開発講義では、クックパッドにおけるユーザーの課題解決のための考え方をインプットし、それを体感していきます。

後半 5 日間は実践的なプログラムとして、OJT プログラムと PBL プログラムの2種類を実施します。 OJT プログラムではクックパッドの部署に配属され、メンターの指導のもとサービス開発を実践します。 PBL プログラムでは社員エンジニアのサポートのもと、身近な課題を解決するサービスを自ら提案し実装していきます。

今年は以下の日程で開催されます。

  • 8/16(月) 〜 8/27(金)

昨年の様子については、以下の記事をご覧ください。

開催形式について

前半の講義はオンラインで行われますが、後半の実践プログラムでは OJT プログラムをオンサイト、PBL プログラムをオンライン、オンサイトのいずれかを選択できる形式で実施することを予定しています。

クックパッドオフィスは 2021 年 5 月より、恵比寿からみなとみらいに移転します。今回のインターンは移転後初のサマーインターンということもあり、参加される方々が新しいオフィスの雰囲気、そこで働く社員の人たちとの交流をできる限り体感できるようにしたいと考えました。 COVID-19 の感染拡大状況を注視しつつ、オンライン、オンサイト両方の準備を現在進行中です。


参加してくださる皆さまのため、サマーインターンシップには毎年会社を挙げて取り組んでいます。 クックパッドのエンジニアになった「未来の自分」を体験できた、と参加して頂く皆様に実感してもらえることを目指して準備を進めていきます。

また、長期の就業型インターンシップも通年で募集しています。 興味のある方は、以下のページからご応募ください。

皆さまのご応募をお待ちしています!

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/