クックパッドアプリ(Android)の開発効率化のためにやったこと/やっていること

モバイル基盤部のこやまカニ大好き(id:nein37)です。 モバイル基盤部では、CI環境の改善やアプリのリリースサイクル自動化といった開発・リリースフローの効率化に加え、アプリのビルド速度改善や開発のしやすさを改善する様々な取り組みを行っています。 今回はその中から、クックパッドアプリ(Android)に対して行った開発効率化の取り組みの一部を紹介したいと思います。

あわせて読みたい : Android版クックパッドアプリで採用している技術の現状確認 2018年版

日々のメンテナンス系

不要になったソースコードやリソースの削除

気がつくとどこからも参照されなくなったソースコードやリソースはどうやっても発生するので定期的に消しています。 特にモバイル基盤部のタスクと決まっているわけではないですが、単に綺麗になって嬉しいこととapkサイズが少しでも小さくなれば良いという気持ちで手の空いた時に Android Studio の Analyze ツールや konifar/gradle-unused-resources-remover-plugin で検出されたものをシュッと消しています。

Lint設定の最適化/Lint警告の除去

クックパッドアプリでは以前、朝Lintという取り組みで細かいLint指摘事項への対応を行っていました。 この取り組みは警告も減るしなんとなく成果が出た気持ちになって良いものだったのですが、最終的に修正コストが異常に高かったり本当に対応が必要かと思えるような警告が残って誰も手を付けられなくなり、やがて途絶えてしまいました。

僕もすっかり朝Lintのことを忘れていたのですが、ある時なんとしても令和の朝Lintというプルリクエストを出したいと思い手元で Lint を動かしてみるとおよそ280件の指摘事項があり、うちいくつかはクックパッドアプリでは考慮しなくても良いようなものだとわかりました。 lintOptions を見ると、これは逆に対応したほうが良いと思えるものもいくつかあります。 この lintOptions をクックパッドアプリの現状に合わせたものを令和の朝Lintとしてプルリクエストにしました。

f:id:nein37:20191021143111p:plain

このときのプルリクエストでは各指摘事項の変更に対して、なぜ enable/disable にするのか、どのように修正すれば良いのかをコメントしておいたので、今後 Lint 設定を再度見直すときにも利用できると考えています。

f:id:nein37:20191021143140p:plain

同じくモバイル基盤メンバーの吉田さんが社内ブログでも朝Lint活動について広報してくれていて、朝Lintという習慣がひっそりと復活しつつあります。

※ クックパッドアプリではプルリクエストに含まれる変更に関する Lint や ktlint の指摘事項は Danger によってプルリクエスト中に指摘され修正するようになっており、朝Lintの対象となるコードを増やさないような仕組みづくりも同時に行っています。

画像リソースのWebP化/WebPおじさん化

あるときどうしても apk サイズを小さくしたくなり、画像リソースをまとめてWebPに変換しました。 Android Developers にはWebPはサイズが小さくて最高とか画像リソースをWebPに変換するとビルドが速くなるといった夢のようなことが書いてあり、それを信じて変換しました。 Android Studio には WebP の変換ツールが組み込まれていて、アプリ内の画像を一括で WebP に変換することができます。 また、クックパッドアプリは minSdkVersion21 になっているため、ロスレスや透過といった WebP の機能をフルに活かすことができるのも利点でした。 Lossy WebP への変換では画質が劣化するために以前のバージョンと比較する必要がありますが、Lossless WebPへの変換であれば理論上画質の劣化はありません。 WebP に乗り換えるためにすべての画面のすべての画像の画質チェックをしなくても良いのは便利でした。

f:id:nein37:20191021143203p:plain

6月頃に一括でアプリ内の画像およそ1000個の画像を Lossless WebP に変換し、その結果、apk サイズを1.2MB縮小することが出来ました。 それ以降は主にプルリクエストレビュー時に WebP おじさんとして活動しています。

f:id:nein37:20191021143229p:plain

得られた知見として、 Lossless WebP への変換ではほとんどの場合画像サイズが小さくなりますが、以下の2パターンではうまく縮小できませんでした。

  1. 元画像が十分に小さい Indexed Color のみで縮小されたPNGである場合
  2. 元画像がまったく軽量化されていない巨大な画像である場合

1. はWebPに変換した場合に仕組み的に縮小される余地がないためか、ほぼ誤差範囲ですがPNGよりもWebP画像のほうが大きくなる事があります。 Android Studio の変換ツールに容量が節約できない場合は変換をスキップするという設定があるため、この場合は変換対象から外しています。

2. は Lossless WebP ではなく Lossy WebP で変換すべきものです。正直見た目では Lossless にすべきか Lossy にすべきかわからないので、現状は解像度とファイルサイズをみて判断しています。

将来的にはLossless/Lossy WebPへの変換はDangerに指摘させることができると良いなと思っています。 この記事を書いている途中でプルリクエスト内に png, jpg や大きすぎる WebP が含まれている場合は Danger に指摘させるような修正を入れたのでWebPおじさん業はなくなりました。

Danger により機械化されたWebPおじさんの様子 f:id:nein37:20191021143256p:plain

なお、ビルド速度への影響は計測できないほどわずかでした。

minSdkVersion 21 後の変更

Ripple 対応

これまで background リソースを StateListDrawable で切り替えてタッチフィードバックを実装していたような箇所を Ripple によるタッチフィードバックに置き換えていきました。 API 21から RippleDrawable も使えるようになっていて、この部分は素直に minSdkVersion21 の恩恵を受けられた部分でした。

android:elevation の指定で影をつける

当たり前なんですが古い端末での挙動とか何も考えずに elevation で影が落ちるというのが本当に楽で良いのです。

*-v21 系代替リソースの整理

Style や Theme 系リソースに *-v21 で分岐させていたリソースがあったので、minSdkVersion 21 を期に整理しました。 これまで Material Design のバックポートに関する知識がないと Theme を変更するのが難しかったのですが、minSdkVersion21 になったことで Theme や Style の編集はだいぶ簡単になりました。

ツール導入など

AndroidKTX導入

クックパッドアプリ内の Kotlin 比率が高くなって来たのでAndroidKTXを導入しました。 去年の11月時点ではクックパッドアプリのおよそ20%が Kotlin でしたが、現在ではさらに Kotlin への置き換えが進み半分ほどがKotlinで書かれている状態です。 f:id:nein37:20191021143324p:plain

Firebase Performance Monitoring

去年突然アプリのパフォーマンス監視がしたくなりFirebaes Performance Monitoringを導入しようとしました。 このときはクックパッドアプリが依存していた一部のjarと競合してうまく導入できなかったのですが、今年になり Android Gradle Plugin を更新したりFirebase Performance Plugin 自体が更新されたりした結果、いつのまにか導入できるようになっていました。 現在は社内の主要なアプリでは大体有効になっていて、特にレスポンスが遅い API の特定やアプリ起動時間の測定に使われています。

Stetho から Flipper への乗り換え

もともと Stetho を利用していたのですが、Mirrativ tech blogさんの記事を参考に Flipper を試してみたら良かったので乗り換えました。 アタッチしなくても良いのは本当に素晴らしく、アプリのデータ削除などでプロセスキルを挟んだ場合でもアプリを立ち上げれば自動でログを見られるようになるのはとても便利です。

R8導入

Android Gradle Plugin v3.4 でデフォルト有効になったR8ですが、クックパッドアプリではそれ以前からR8を利用して難読化処理を利用するとビルド時間が倍になるという問題が発覚していました。 BetaやRCでバージョンが上がるたびに試していましたがまったく改善せず、とうとう v3.4 が stable になっても解決しなかったため一時的にR8を無効化していました。 そのままでもアプリのビルドはできるのですが、標準ツールが自分のアプリで利用できないのは悲しいので、定期的に時間をとって調査していました。

やるぞ!という気持ちのissue f:id:nein37:20191021143401p:plain

あるとき annotations.jar という古代のProguard設定の仕組みがビルド時間に影響をしていることに気が付き削除することで無事に有効化することができましたが、普段から最新のビルドツールや設定を試して問題を検出することの重要性を感じました。

マルチモジュール関連

以前マルチモジュールにしていく話をしてから一年以上経ち、クックパッドアプリも25モジュール構成になりました。 最初の頃は StyleTheme などをまとめたUIモジュールやログ用の仕組みをまとめたログモジュールなど、比較的変更の少ない静的なモジュールばかり切り出していましたが、これらのモジュールは切り出した後もほとんど変更が入っておらずビルドキャッシュを最大限利用できた上、位置づけもわかりやすいので早めに切り出しておいてよかったと思います。 そこから各種機能をモジュールに切り出す作業を進めていますが、:legacy に依存しないモジュールで機能を実装できるようになるまではまだもう少し掛かりそうです。

モジュールの命名

最近 Google Developers の日本語ブログにもAndroid のモジュールのパスに関するちょっとしたヒントという記事が出ていましたが、クックパッドアプリでもAndroidビューにおけるモジュール表示がわかりにくいという問題は早い段階で発覚していました。 上記の記事で紹介されていたような projectDir による解決も検討したのですが、結局 features_ のような prefix をモジュールにつけることにしました。 クックパッドアプリでは単純な解決方法を選ぶという方針でこのようにしましたが、このあたりはチームやモジュール分割の方針によって最適解が変わると思います。

モジュール切り替えによるアプリの設定変更

以前のクックパッドアプリはビルドバリアントによって接続先とデバッグ機能の有無を切り替えていました。

  • stage flavor dimension(開発用設定の切り替え)
  • mode flavor dimension(接続先設定の切り替え)
    • internal(社内ステージングサーバ向け、Hyperionなどの開発用機能あり)
    • external(本番サーバ向け、リリース用設定)
  • buildType
    • debug(minify,Proguard なし)
    • billingBeta(決済確認用の特殊なビルド)
    • release(minify, Proguard あり、リリース用証明書)

上記設定の組み合わせによってビルド時に必要な設定を利用していましたが、マルチモジュール構成のプロジェクトではアプリがこれらのビルドバリアントを設定している場合、依存しているライブラリプロジェクトにも同様のビルドバリアントを設定する必要があります。 (ライブラリプロジェクトに同名のビルドバリアントが存在しない場合、 ./gradlew testProdInternalDebugUnitTest のようなテストコマンドでライブラリプロジェクトのテストが実行されなくなる場合があります)

モジュールが増えていくにしたがってこの設定が面倒になり、 Android Studio 上でのビルドバリアントの切り替えも大変になってきたことから、 flavor ではなく依存先モジュールの切り替えによって接続先の切り替えや開発用機能の追加を行うように切り替えました。 変更後の各モジュールの依存は以下のようになっています。(dev flavor は minSdkVersion 21 化したことにより分岐がほぼなくなったので不要になりました)

  • :app_cookpad (本番サーバ向けビルドをリリースするためのモジュール)
    • :settings_external (本番サーバの接続先情報モジュール)
  • :app_cookpad_internal 社内向けアプリをビルドするためのモジュール)
    • :settings_internal (社内サーバの接続先情報モジュール)
    • :features_debug (開発用機能モジュール)
  • :app_cookpad_billingBeta 決済確認用のアプリをビルドするためのモジュール)
    • :settings_internal (社内サーバの接続先情報モジュール)
    • :features_debug (開発用機能モジュール)
    • アプリモジュールとして定義したことにより buildType billingBeta は廃止しました

この変更により、今まで ./gradlew assembleProdExternalRelease という呪文のようだったビルドコマンドが ./gradlew :app_cookpad:assembleRelease だけで良くなります。 AndroidStudio 上でもビルド対象のモジュール(=必要なアプリの種類)とbuildType(=minify,proguard,証明書)だけ意識すればよくなり、GUIでの操作もかなり簡略化されました。 クックパッドアプリはこれまでの長期間の開発で Gradle ファイルがかなり複雑化していたのですが、ビルドバリアントの整理とモジュール分割によってそれぞれ設定を書く場所がわかりやすくなり、多くの部分を共通化してシンプルな構造になっていきました。 この方式を採用するとモジュール数はどうしても増えていくのですが、クックパッドアプリのような大きいプロジェクトでも ./gradlew testDebugUnitTest のような基本的なコマンドが何も考えなくてもちゃんと動くというのは開発のしやすさという点で非常に重要だと思っているので、今年やっておいてよかった変更の一つだと考えています。

おわりに

僕の趣味で比較的地味な変更ばかり紹介してしまいましたが、今年はこの他にも多くの(機能追加以外の)変更が行われています。 モバイル基盤部ではこれからも新機能を簡単に開発し、素早くユーザーに届けるためにモバイルアプリの開発効率化を続けていきます。

興味がある方はぜひ一度クックパッドオフィスに遊びに来てください。 https://info.cookpad.com/careers/

データ活用基盤の今 〜DWH外観図〜

こんにちは、今年の1月に会員事業部から技術部データ基盤グループへ異動した佐藤です。先日、京まふ2019前夜祭イベントに参加するために人生で初めてピカピカ光る棒を買いました。

新卒で入社してから2年ほど分析作業をしていた身から、データ活用基盤を作る側へ立場を変えました。今回は新たに身を移したデータ活用基盤の外観を説明したいと思います。

2017年にも同内容の記事が投稿されていますので、当時との違いを中心に説明していきます。

外観図

以下が2019年10月現在におけるクックパッドのデータ活用基盤の全体像です。

クックパッドのDWH外観図
クックパッドのDWH外観図

masterデータのインポートがMySQL以外にも複数種対応し始めたことと、PrismとSpectrum(S3+Glue)周りと、Tableau Serverが大きな変更点となっています。2017年の図にDmemoはありませんでしたが、記事本文にある通り当時から活用していました。

図が煩雑にならないよう、レシピサービスを中心にまとめていますが、クックパッド社が運営する全サービスについて同様のワークロードでRedshiftにデータを集約させています。また、図では省略しましたが、Firebaseなどの外部サービスから得られるデータもRedshiftに集めています。

一つ一つの処理をみていきましょう。

入力: マスターデータの取り込み (master data flow)

クックパッド社内でサービスのマスターデータを管理するDBとして利用するDBMSは主にMySQL・PostrgreSQL・DynamoDBがあります。最も多いのがMySQLで、最近DynamoDBが増えつつあります。

MySQLについてはpipelined-migratorという独自開発の専用システムを利用しています。 こちらは管理コンソール用の専用Webサイトが社内ネットワーク上にあり、テーブル取り込みの様子を確認できます。また、ボタンひとつでRedshiftに取り込むテーブルやDBの追加・削除が手軽にできるようになっています。

pipelined-migratorのコンソール
pipelined-migratorのコンソール

PostgreSQLについてはAWS Database Migration Service(以下DMS)を利用しています。pipelined-migratorがまだ現段階ではMySQLにしか対応しておらず、かつ社内でPostgreSQLの利用が比較的少ないため、一時的にDMSを利用しています。PostgresSQL対応版も開発中であり、今後PostgreSQLからのテーブル取り込みもpipelined-migratorに一本化していく予定です。

DynamoDBについてはまだ実績が少ないのもあり、定型化しているものの手作業でインポートしています。 DynamoDB Streamでデータの更新を検知し、LambdaとKinesis Firehose経由で、S3に追加データを吐き出します。S3に配信後は後述するログデータと同様にRedshift Spectrumでクエリアクセスができるようになります。

DynamoDBデータの取り込みフロー
DynamoDBデータの取り込みフロー

pipelined-migratorはbricolageとmys3dumpを組み合わせて作られています。

入力: ログデータの取り込み (log data flow)

ログデータの取り込みには、2017年の記事に書かれたStreaming Loadシステムと昨年末に書かれた記事に登場したPrismの両方が使われています。 クックパッドのDWHではRedshift Spectrumを中心にして構築するようにデータ移行作業を実施中です。このため、Streaming Loadシステムからのログ取り込みはゆくゆくは退役する予定です。 現在は移行期であるため外観図にはStreaming LoadからRedshift内部へのロードとPrismからRedshift外部(Spectrumでアクセス可能なS3バケット)の2経路が同時に存在していますが、次にまたDWH外観図を書く頃にはPrismに一本化されていることでしょう。

サービス開発者側から「新規にログを取り始めたい」となった場合、以下の手順でロードを行います。

  1. *.strdefというYAML形式のファイルにログ定義を書く
  2. tech/dwhというDWHが管理するリポジトリへ上記ファイル追加PRを出してもらう
  3. ログ関係者&DWHチームメンバーがログ定義に関するレビューをする
  4. アプリケーションから送られてきてS3にログが到達したしたことを確認し、strdefファイルの適用を行う

サービス開発者に1~3までを行ってもらい、DWHでは3~4を担当します。 こうしてみるといちいちログをとるのに手順が多く、面倒に思われるかもしれません。このフローで運用している背景には、ログを取りたいと思った人にstrdef定義を通してきちんとログ設計をしてもらいたいという意図があります。これはDWHに限らない話ですが、ロギングが始まってしまえばログは修正できません。プログラムのリファクタ感覚でカラム名や型定義は変更できないのです。どうしてもやむを得ず発生することはありますが、問題を先送りにした場合はツケが回ってきます。ログ取り自体は気軽に行えるが、その設計にはきちんと考える時間を取りましょうという思いがあって、こういった手順となっています。

Streaming Load・Prismのどちらもコンソールが用意されており、ログが順次ロードされていく様子を確認できます。

Streaming Loadのコンソール
Streaming Loadのコンソール
Prismのコンソール
Prismのコンソール

Streaming Loadの実装はbricolage-streaming-preprocssorとbricolage-streaming-loaderとして公開されています。

Redshift内部での加工処理

Prism登場によりRedshift Spectrum活用が進んできましたが、Redshift内部の処理に関しては既にだいぶ完成していたため新たに手を加える必要はありませんでした。 2017年当時と同様、bricolageを用いて書かれたSQLバッチをKuroko2というジョブ管理システムで定期実行しています。Redshift内部のデータアーキテクチャについても従来通りの入力層・論理DWH層・論理データマート層の3層区切りとなっています。ただ、2年間運用してきたことでこれら各層に格納されているデータは充実してきており、2年前と比べて3層ともに成長しています。

Redshift内部の加工処理はbricolageとKuroko2を組み合わせて作られています。

出力: アドホックな分析

社内からのアドホックな分析に用いられるツールに関しては特に変化がなく、Bdash・Postico・Jupyter がそのほとんどです。あるいはTableau Desktopでアドホックな分析作業を行っているかもしれません。これら各ツールは全て内部テーブルと同じようにSpectrumテーブルへアクセスできるため、各自分析者が自分の使いたいツールを自由に選べる状態になっています。

分析者は後述するDmemoやSlackにおけるデータ分析お悩み相談チャンネル、#data-analysisを駆使して社内のデータを分析しています。日々、#data-analysisやissue上で分析用SQLのレビューが行われています。

BdashはこちらのGithubリポジトリで公開されています

出力: ダッシュボード用BIツール

from redash to tableau

2017年の記事においてRedashからTableauへの移行を検討中と書かれていましたが、現在では完全に移行体制が整い社内のほとんどのダッシュボードはTableau Serverに移行されました。移行に至った理由は過去の記事にも書かれた通り、Redashのキューまわりの実装に難があったためです。

Tableau Serverに移行した今では各部署で活用されており、エンジニア以外にも職種を問わず広く利用されています。

ただし、Tableau ServerとTableau Desktopではライセンスが別契約となるため、実際にダッシュボードを作りたい人はライセンス申請が必要となります。この申請フローは定型化されており、ヘルプデスクへ申請を出すだけでライセンスキーが割り当てられるようになっています。

Redashは諸事情がありまだ完全退役とはなっていませんが、アクセス&更新がなされているダッシュボードはほぼありません。

出力: DWH内のデータベースドキュメント

データベースドキュメント管理システム dmemo のご案内 にて登場したDmemoも現役で活躍中です。 Dmemoは毎晩Redshiftにアクセスし、DWH内部にある最新の全テーブル情報を取り込みます。取り込んだDB・スキーマ・テーブル・カラムの各階層ごとに説明を書くことができ、その履歴も残せます。Dmemoに十分情報が蓄積されていれば、PR上でのやり取りやデータ分析についてSlack上で聞かれたときなどにDmemoのURLを貼って一言二言伝えるだけでスムーズにデータに関する情報伝達が行えるようになります。

Dmemo操作例
Dmemo操作例(Techlife用にローカル開発環境上でダミーデータを用いて撮影したものです)

新しく入社した社員やインターン生にデータに触れてもらうときに一旦DmemoのURLを共有しておくとその後の話が円滑に進むようになります。また、ログに関する何かしらのインシデントが発生した際には「v1.0.0のアプリケーションではIDがズレている」等々のメモを書いておくことで、後でログデータを集計して奇妙な結果が出たときに即座に気づくことができるようになります。

Redshift Spectrum移行作業に合わせて、外部テーブルやRedshift特有の機能であるlate-binding viewにも対応しました。

DmemoはこちらのGithubリポジトリで公開されています。

出力: バッチ処理用バルクエクスポート

こちらも2017年の記事と変わらず、Queueryとredshift_connectorが使われています。他のサービスからも利用できるようなDWHを構築しておくことで、データ活用基盤が分析のみならず様々なサービスやプロダクトにまで活用されるようになります。

過去にTechlifeでご紹介したデータ活用基盤を利用したシステム運用の記事を下記に載せておきます。

Redshiftから外部システムへのバルクエクスポートはQueueryとredshift_connectorが使われています。

DWHの課題

上記がデータ活用基盤の外観図となります。しかし、まだこれで完成ではなくこれからも開発を続けていく必要があります。最後に、DWHに残っている主な課題について述べたいと思います。

Redshift Spectrum移行

ログデータ取り込みの項目でも書きましたが、現在は内部テーブルへロードする旧方式のStreaming Loadと外部テーブルへロード(S3へのParquet変換)する新方式のPrismの両システムが並列で稼働しています。 Streaming Loadでのロードを廃止するためには内部テーブルに依存している全ジョブの停止・外部テーブルへの移行が必要となります。 186のジョブと284テーブルを一つ一つ検証した上で移行と削除を行っていく作業は自動化ができない、泥臭い手作業となります。その中で歴史的経緯に基づく仕様を発見したり、現状のジョブが間違っていたり等が発見されていきます。 この移行作業についてはDWH総出で丁寧に移していく他無く、地道にやっていくことになります。

Tableau Server運用

Tableau Serverの運用も依然として作業コストがかかっており、なんとかすべき課題です。 まず、Tableau ServerはTableau社側から新しいバージョンが提供されるたびにアップグレードしていく必要がありますが、ダッシュボードのポータルサイトという重要なサービスであるためこの作業は慎重に行う必要があります。アップグレード作業の際には事前に社内アナウンスを出し、メンテナンス時間を確保して行っています。 過去にアップグレード作業に失敗し、Tableauサポートと連絡をとりつつアップグレードをするということもありました。このアップグレード作業をより低コストに抑えることができないか、というのがTableau Server運用における1つ目の課題です。

また、TableauはSlackとの連携が弱いという弱点があります。一応、メール通知とZapierという外部のオートメーション化サービスを組み合わせることで自動通知を実現できますが、こちらにも実は問題があります。現在クックパッドでは専用botでの通知運用をしつつ、Tableau公式によるSlack連携機能がくる日を待ちわびています。

さらにライセンス管理についても課題があります。先にはダッシュボード用BIツールの項目で「ヘルプデスクへ申請を出すだけでライセンスキーが割り当てられる」と書きましたが、定型化したとはいえここは裏側で手作業が発生しています。根本的な負荷削減にはなっていないため、できる限りライセンス付与の作業負荷がなくなるよう自動化をしたいところです。

データ活用の推進

データ活用基盤が整いつつある今、基盤業務のその先のデータ分析の啓蒙活動に比重を置くフェイズに突入しつつあります。 今までも社内でSQL勉強会が開かれたり等、各所でデータ分析の民主化は進んできていました。ですが、草の根運動に頼るだけでなく、DWHが組織として継続的にデータ活用を推進していく必要があります。 こちらに関しては具体的な方策やマイルストーンもありませんが、来期からの一番の課題となることでしょう。

まとめ

今回は以前お伝えしてから2年経ったデータ活用基盤の全体像をお話しました。一度に書ききるには多すぎるため、前回との差分を中心に書きましたのでぜひ2017年に公開した記事と比較してみてください。

私達、技術部データ基盤グループは「クックパッドの全社員がデータに基づいた意思決定を行えるようにする」を目標に日々の業務に取り組んでいます。 分析者の望む最強のデータ分析環境を提供したい方、余計な手間をを要せず分析作業にのみ集中できる最高のデータ分析環境に浸ってみたい方、ぜひ私達と一緒にデータを駆使してより良いサービス作りをしてみませんか。

クックパッド株式会社 | クックパッド株式会社 採用サイト

クックパッド社内に工房(Fab)を作ってプロトタイプ開発をした話

今年1月に研究開発部から分離して発足しましたスマートキッチン事業部の山本です。
スマートキッチン事業部では、クックパッドが提供するレシピ情報を様々な家電機器と連携させて、料理体験をより楽しく快適にする、スマートキッチンサービス OiCy の開発をすすめています。

クックパッド社内に工房(Fab)を作りました

スマートキッチンサービスOiCyは、レシピ情報と家電機器の連携で生み出されるサービスで、サービス開発に加えてサービスと連携する家電機器が必要になります。そのため、家電メーカーとの連携をすすめていますが、同時に自前での家電機器開発も行っています。そして、自前の家電開発を効率的に行なえるようにする目的で、社内で加工製作ができる工房(Fab) を、恵比寿のクックパッドオフィス内に立ち上げました。工房には、3Dプリンタやレーザーカッターなどの加工設備が設置されており、業務内外を問わず社員の利用が可能になっています。(要安全講習)

f:id:ymmttks:20191016150422j:plain:w420
工房の様子

工房生まれの自前(改造)家電たちの紹介

この工房で生まれた、クックパッド自前(改造)家電の一部が、先日開催されたスマートキッチンサミットジャパン2019(SKSJ2019)で公開されました。

OiCyService動画

SKSJ2019クックパッドデモの動画
↓SKSJ2019の関連記事はこちらを参照
・PC Watch ロボット化する家電から寿司シンギュラリティまで、人を食でエンパワーする「スマートキッチンサミット2019」 森山 和道
・CNET JAPAN 未来の台所を創造する「SKSJ 2019」から見えてくるもの 近藤克己

OiCy Water

f:id:ymmttks:20191016150433j:plain:w320
OiCyWater外観
OiCy Waterは、水の『硬度』と『分量』をレシピに合わせてボタン一つで出してくれる、電動ウォーターサーバーです。スマートフォンのアプリ上でレシピを閲覧すると、そのレシピに書かれている水の『硬度』と『分量』(※)が自動的に装置に転送されます。ユーザーは装置上のボタンを押すだけで、閲覧しているレシピで使うための適切な水を得ることができます。『硬度』と『分量』は、ジョグダイヤルを回して手動で調整することもできます。

※現状ではクックパッドのレシピ全てに硬度に関する記述があるわけではありません。

↓水の硬度が料理に与える影響についてはこちらを参照
SKSJ2019 ⾃分の「おいしい」を⾃分でつくれる感動を クックパッド 金子晃久

OiCyWaterの構成

f:id:ymmttks:20191016150453p:plain:w420
OiCyWaterの構成
本機は、2つのチューブポンプを用いて、『硬水』と『軟水』2つのボトルから水を排出する装置です。使用したチューブポンプは3.5ml刻みで排出量を制御、最速で1分間に1.4Lの水を排出することができます。
制御用のマイコンシステムにはM5Stackを使いました。理由は、技適が取れていてかつとても安価、ネット上に参考にできる情報が豊富にあって、ライブラリも充実しているからです。周辺デバイスへの信号は、モーターの速度制御をするPWM信号のみM5StackのGPIOから直接出していますが、それ以外はI2C接続したGPIOエクスパンダを経由してやり取りをしています。GPIOエクスパンダ側で、信号の変化を割り込み制御をする予定でしたが、WiFiのライブラリと同時使用するとファームにリセットがかかるという現象があり、イベント直前で時間がなかったためこの問題解析は保留して、割り込みなしのポーリングで、ジョグやモーターの回転を拾う処理になっています。
モーターの回転は、チューブポンプの回転部分とポンプ外装の間に隙間があるので、100円ショップのネオジウム磁石をそこに接着、ポンプ外側に設置した磁気センサから非接触で回転検出をしています。この方法では回転方向は分からないのですが、チューブポンプは負荷が非常に大きくギア比の大きなモーターが付いており、外部から強制的に回すことはほぼ不可能です。そのためポンプ回転部分はモータードライバに入れている信号の向きにしか回らないため、特に回転方向を検出する必要はありません。磁石の貼り付け位置を、チューブポンプのローラー部分にすることで、水の排出綺麗に途切れるところで正確にモーターを止められる”位置制御にも利用しています。
f:id:ymmttks:20191016150442p:plain:w320
OiCyWaterのメカ構造
チューブポンプはモーター部分が長く突き出した構造をしていて筐体へのおさまりが悪いため、ベルトとプーリーを用いてモーター部分をポンプ本体とタンデム構造にし、2つのチューブポンプを向かい合わせに対向させるメカ構成にしました。2つのチューブポンプ、2つのモーターは2mm厚のステンレス製の背骨に固定されて、チューブポンプを回す強力なモータートルクに負けない強靭な剛性を持たせました。工房のレーザーカッターでは、金属の切り出しはできないため、この背骨部分の制作のみ外注先に頼んで特急で作っていただきました。ペットボトルを下向きに指すジョイント部分については、弁のついたペットボトルキャップと交換する部分はペット用の給水器の部品を流用、刺さる側の部品は3DプリンタをつかってABS樹脂で成形しました。2Lの水の水圧がかかっても水漏れをしない構造を作るのには試作検証改良を繰り返す必要がありましたが、3Dプリンタが手元にあることは短期間での開発にとても役立ちました。

OiCyサービス対応電子レンジ

f:id:ymmttks:20191016150446j:plain:w420
OiCyサービス対応電子レンジ SIGMA
メーカー様からお叱りを受けるかもしれないのであまり大きな声では言えないのですが、市販の電子レンジを改造して、スマートフォンのアプリ上で閲覧しているレシピに書かれている 『加熱ワット数』、『加熱時間』をWiFiを通じて自動的に装置に転送されるようにしたものが、OiCyサービス対応WiFi電子レンジ(開発名:SIGMA)です。

SIGMAの構成

f:id:ymmttks:20191016150457p:plain:w420
SIGMAの構成
電子レンジは、強電系に非常に高圧な回路と大容量コンデンサを搭載しており、改造には危険を伴います。専門的な知識のない場合には絶対に真似しないようにお願いします。今回の改造は、できる限り装置の深い制御部分に手を入れず、UI部分を乗っ取る形でHackしました。こうすることで、強電系の回路に一切触れずに欲しい機能を実現することができました。
電気量販店で、改造しやすそうな電子レンジを探すところから、開発は始まります。改造用の電子レンジを選択する上でのポイントは、液晶表示やタッチパネルなどを用いてるものは、現在の状態を正確に把握するための難易度が高いため避けます。LEDのみ、物理スイッチのみでUIが構成されていて、かつスイッチに複数の機能が割り当てられていないものが好適です。
OiCy Waterと同様に、制御用のマイコンシステムにはM5Stackを使いました。この電子レンジは、UIが、LEDと2つのジョグスイッチだけで構成されていたので、これらの入出力と扉の開閉センサをロジック回路処理(時分割表示のLED信号の復調回路)を噛ませてGPIOエクスパンダに接続し、M5Stackからは全体が一つのI2Cデバイスとして見えるようにしました。 外装は、操作パネル部分のジョグやLEDをすべて外し、レーザーカッターで加工した3mm厚の乳白色のパネルで覆い、表面上からはM5Stackの表示パネルとボタンのみしか見えない構造になっています。スマホからのレシピ情報転送以外に、M5Stackのボタン操作によるレンジ設定変更が可能です。加熱のスタートやキャンセルはドアの開閉で行い、ボタン操作は不要です。

OiCyサービス対応IHプレート

f:id:ymmttks:20191016150426j:plain:w420
OiCyサービス対応IHプレート OMEGA
こちらもメーカー様からお叱りを受けるかもしれないのであまり大きな声では言えないのですが、市販のIHプレートを改造して、スマホ端末で閲覧しているレシピに書かれている『火力』、『加熱時間』をWiFiを通じて自動的に装置に転送されるようにしたものが、OiCyサービス対応WiFi IHプレート(開発名:OMEGA)です。

OMEGAの構成

f:id:ymmttks:20191016150502p:plain:w420
OMEGAの構成

改造用のIHプレートを選ぶポイントも電子レンジとほぼ同じです。リバースエンジニアリングの結果、この機器は本体部分とUI部分をクロック同期式の変則的な双方向シリアル通信で構成されていることが分かったので、UI基板を取り外し、代わりにロジック回路処理(入出力信号の分離)を噛ませてGPIOエクスパンダに接続して、M5Stackからは全体が一つのI2Cデバイスとして見えるようにしました。
外装は、UIパネル幅に対してM5Stackの方が奥行方向に長いため、張り出した顎の部分を3Dプリンタで成形して、表面処理をした上で塗装したものを取り付けてあります。パネル部分は、電子レンジと同様にレーザーカッターで加工した3mm厚の乳白色のパネルで覆って統一感を持たせてあります。

社内に工房がある強み

 製品やサービス、機能など、我々がこれから作ろうとしているものが、本当に顧客にとって価値があるのか?モノができてから実際にユーザーに提供してみたら、期待した価値がなく失敗・・・のでは時間と資本を大きくロスしてしまいます。そこで、我々は、Googleのスプリントに則って、3〜5日で課題から仮説を導きだし、ソリューションを立て、プロトタイプを作り、ターゲットユーザに当てて仮説検証を行う、という方法をよく用いています。
 ↓高速コンセプト開発メソッドについてはこちらを参照
 ・SKSJ2019 一週間で回す高速コンセプト開発メソッド教えます クックパッド 佐藤彩香
 
 スマートキッチン事業部でも、短いものでは3日程度で、ハードウェアのプロトタイプを作って、実際にユーザーに使ってもらって、顧客価値を検証しています。今回紹介した3つの家電デバイスは、各2週間程度の開発期間がかかっていますが、顧客価値検証用に現場で実際に使用し、継続的に改良が行われています。こういった機器の開発改良は、外部のリソースに頼っていてると短時間での開発は難しく、価値検証に時間がかかってしまいます。使いたいときにいつでも加工・製作に使える『場』と『機材』が社内にあることは、超高速ハードウェアプロトタイピングでは極めて重要です。そして、この『場』と『機材』を活かしきれる、メカ設計〜加工〜回路設計〜回路製作〜ファームウェア設計実装〜実機デバッグといった一連のプロトタイプ開発を一人で一貫してできる、フルスタックエンジニア人材を絶賛募集中です。

まとめ

『その程度のプロト、俺がやれば1週間でできる!』『3日でできる!』というプロトタイプエンジニアスキルをお持ちの猛者のかたは、是非我々のプロジェクトにJoinしてください。
クックパッド キャリア採用 職種:プロトタイプエンジニア(スマートキッチン)

同時に、こんなイカれたデバイスを操作するiOSアプリを書きたいという、キワモノ好きのiOSエンジニアとデバイスとアプリをユーザーとつなぐ素敵なUI/UXデザインを担当するデザイナーも絶賛募集中です。
クックパッド キャリア採用 職種:iOS エンジニア
クックパッド キャリア採用 職種:UI/UXデザイナー(スマートキッチン)

/* */ @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;*/ /*}*/