スマートまな板による料理支援

研究開発部アルバイトの佐藤です。今日はアルバイト期間中に取り組んでいたまな板にレシピを表示する装置について紹介します。

背景

レシピ本をキッチンに持ち込む以外にも、キッチンでスマホ上から検索することによってレシピを見る機会が増えています。しかし、キッチン内でタブレット端末やスマホでレシピを見る問題点として以下が挙げられます。

  • デバイスが水や油で汚れず、レシピが見やすい位置に置きたいが、スペースの都合上難しい
  • 汚れた手で端末の画面を料理中に触って操作しなくてはならない

また、最近ではAmazon EchoやGoogle HomeなどのスマートスピーカーでCookpadのレシピを検索し、タブレット端末やスマホでレシピを保存することができます。その発展として、レシピの読み上げやEcho Showなどの端末を用いたレシピ表示なども考えられますが、端末と同様に映像などの表示位置が固定されてしまうという問題が挙げられます。また、音声での入力の他にジェスチャなどもとりいれることができればより視覚的な操作も可能ではないかと考えられます。

このような問題に対して取り組んでいるプロジェクトはいくつかあります。例として2つのプロジェクトを紹介します。

こちらのプロジェクトではユーザーの動作やキッチン台の上のものを認識して、端末に現在の動作に合わせた作業内容を表示します。切り方の動画の再生なども端末上で行っていますが、再生するには端末を操作する必要があります。また、この装置では切っている食材を認識するためにまな板自身にセンサなどを取り付ける必要があります。

こちらの論文ではカメラ・プロジェクタ・対話ロボットを連携させた調理支援システムが提案されていますが、対話ロボット1台、カメラ2台、プロジェクタ3台とかなり大掛かりなシステムとなっています。

スマートまな板

f:id:sss3p:20180720111838p:plain

そこで図のように天井に装置を設置することによりキッチン用品には非接触のスマートまな板を開発しました。このまな板の特徴はまな板には何も手を加えないことです(つまり、正確にはスマートまな板でなく、レシピプロジェクターです)。具体的には次のことを目標に開発しました。

  • プロジェクターでレシピや操作画面をまな板に投影し、視線の移動の少ない情報提供
  • 作業台の上に装置を置かないことによる広い作業スペースの提供
  • webカメラとRaspberry Piによる画像処理で人の手を検知し、画面に触らない操作

今回の対象者

以下のような問題に困っている料理初心者を対象ユーザとしました。

  • にんじん、たまねぎ、じゃがいもの剥き方・切り方がわからない
  • だしのとり方がわからない
  • ケーキをどのようにデコレーションすれば良いかわからない

今回実装した機能

上記の様な料理初心者に対して、にんじん、たまねぎ、じゃがいも、だしが材料にすべて入っている肉じゃがの調理とケーキのデコレーションを支援するような機能を実装しました。 料理初心者への支援としてまな板に映像の投影を行い、次のようなものを視覚的に提供しました。

  • にんじん、たまねぎ、じゃがいもの剥き方・切り方の手順動画:文字だけでは中々習得の難しい包丁の具体的な使い方を、まな板の左上に動画を流すことで視覚的に伝える
  • 材料と調味料のチェックボックス:何が準備できていて次に何を準備すべきか判断しやすいようにする
  • 手順表示:一文ずつ手順を表示していく。また、時間が手順に書いてあった場合はタイマーを起動する
  • デコレーションケーキの下書き:デコレーションケーキの下書きを投影し、デコレーションの位置ガイドとして使えるようにする

実装方法

webカメラ・小型プロジェクター・Raspberry Piを用いて実装を行いました。 開発言語はPython3、使用ライブラリはtkinter、opencv2です。 詳細は以下のようになっています。

使用物名 型名など
webカメラ Logicool HD720p
小型プロジェクター iOCHOW iO4 ミニ プロジェクター
Raspberry Pi Raspberry Pi 3, raspbian gnu/linux 9
Python3 Python 3.5.3
tkinter version 8.6
opencv2 version 3.4.1

手の認識

簡易的なデモ機の実装としてカラートラッキングを用いました。具体的には手の肌色をトラッキングすることで手の位置を捉えて、画面操作ができるように実装しました。

デモ

デモ中の写真をいくつか紹介します。

  • スタート画面 f:id:sss3p:20180720111936j:plain
  • メニュー選択 f:id:sss3p:20180720112025j:plain f:id:sss3p:20180720112045j:plain
  • 材料一覧表示 f:id:sss3p:20180720112117j:plain
  • 手順表示 f:id:sss3p:20180720112244j:plain

気づき

実装したスマートまな板では視線の移動の少ない情報提供、広い作業スペースの提供、画面に触らない操作を実現することができました。 実際に実装してみて気づいたことは以下です。

  • 視線の移動の少ない情報提供:
    • 切り方動画をまな板の左上に表示することによって、動画を確認しながら作業することができた
    • 作業によってはまな板に投影するよりもキッチンの壁に投影したほうが良い場合もある(まな板に投影したほうが良い場合は食材を切るときの動画での切り方確認で、キッチンの壁に投影したほうが良い場合はレシピ表示とタイマー)
  • 広い作業スペースの提供:
    • スマホやタブレット端末を作業台の上に置く必要がないため、広い作業スペースを確保できた
  • 画面に触らない操作:
    • 今までレシピを確認するために画面操作する度に手を拭いたり洗ったりしていたことがなくなった

デモ

実際にスマートまな板を数人に体験していただきました。体験後、頂いた意見をいくつか紹介します。

  • 材料チェックリストがまな板の上で操作できるのは便利
  • まな板の上で切り方動画を見られるのは面白い
  • 実用化するんだったら、スマートスピーカーと組み合わせて提供する情報や選択肢によって音声か映像か使い分けたほうがよさそう

また、いくつかの改善点や追加機能がみつかりました。

  • ユーザーの動作によって投影位置を変える機能(ユーザーの作業している場所を検知して、作業の邪魔にならないようなスペースへ画面を移動・縮小させる)
  • まな板の上に置かれた材料を認識したレシピ検索
  • まな板の上に置かれた材料の重さを概算し、レシピで指定されている重さによって切り方を投影する機能
  • 自動でデコレーションの下書きを拡大縮小したり移動したりしてケーキに下書きを合わせてくれる機能

現在の実装では以下の問題が発生しています。

  • 肌色の位置を手の位置と認識しているため、色の似ている木のまな板などを誤認識
  • 指先や指を認識していないため手首などを誤認識するなど認識精度が低い そのため、手の認識専用デバイスを利用しない場合はニューラルネットワークを用いて手を手としてラベル付したり、手の形を認識するなどの実装に変更することが考えられます。 また、Leap Motionなどの外部デバイスを用いて手の認識を行うということも考えられます。

まとめ

キッチンでレシピを確認するときに、視線の移動の少ない情報提供、広い作業スペースの提供、画面に触らない操作を実現できるスマートまな板の開発に取り組みました。

実際に実装することによって、提案の有用性や改善点を見つけることができました。

今後の展開としてはスマートまな板を用いたアプリの開発などが考えられます。具体的には切り方動画をまな板で再生できることや材料・手順のまな板への投影を用いて、子供・初心者向け料理学習アプリなどを実装することにより、より料理初心者への支援ができると考えられます。

新規決済手段導入に際し、なるべく丁寧にテストケースを作成した話

会員事業部の日高尚美(@natan3)です。 半年前になりますが、クックパッドでは Android ユーザ向けにプレミアムサービスの決済手段の一つとして Google Play 決済を導入しました。

ユーザに新たな機能を提供する前には、何らかの形で開発者側での検証が必要です。

Google Play 決済導入バージョンのリリースは、ユーザのお金を扱うこともあり、不具合が起きた際にサービス全体の信用に関わる、非常にリスクの高いリリースでした。 それに伴い、検証もできる限り万全に行わなければなりません。

そのため、なるべく丁寧にテストケースを作成し、それをもとに検証を実施することで新機能が期待通りに実装されていることを担保しました。 丁寧にテストケースを作成したから、というだけではもちろんありませんが、リリースから半年経った今でも Google Play 決済周りの目立った不具合はまだ見つかっておりません。

今回作成したテストケースの紹介

今回作成したテストケースの一部をご紹介します。 実際に利用したものと表現を変えてはいますが、雰囲気は伝わるかなと思います。

f:id:nano-041214:20180718194510p:plain

含まれている項目は以下のとおりです。

  • 各画面で起こりうる状況の組み合わせ(上図で言うところの前提条件)
  • 前提条件を再現するシナリオ
  • シナリオを達成するための手順
  • 手順に対応した期待する振る舞い
  • 期待する振る舞いが得られたかどうかのチェック欄

これを元に動作を確認しました。

それぞれのケースにて、想定した通りの画面が表示されていれば問題ありません。 しかし、実装によっては、期待する振る舞いが得られない場合も出てきます。

テストケースにて期待する振る舞いが本来あるべき姿なので、その場合には実装に手を入れる必要があります。 すべての操作に対して期待する振る舞いが得られる状態にすることが、テストケース作成の目的であり、検証のゴールとなります。

Google Play 決済のテストケース作成までの流れ

なにもないところからいきなりテストケースを作成することは難しいため、 画面遷移図とそれらの分岐条件、各 API の返す異常系一覧をもとに、テストケースを作成しました。

テストケースを作成する流れは以下のようになります。

  1. 各画面で起こりうる状況を整理する
  2. 前提条件を再現するシナリオを作成する
  3. そのシナリオをなぞるための手順を埋める
  4. その手順を行うことで期待されるアプリの振る舞いを埋める

以降の文章で、各項目について解説します。

各画面で起こりうる状況を整理する

テストケースにおいて重要なのは 網羅性 です。

そのため、画面遷移図の各分岐である API 接続箇所や画面遷移時にて起こりうるユーザ状態など、前提条件を構成する各状況を洗い出します。

実際の遷移図ではありませんが以降の理解のために Google Play 決済導入時の画面遷移のイメージ図を添えておきます。

f:id:nano-041214:20180718194451j:plain

Google Play 決済導入プロジェクト初期リリースではクックパッドにログイン済みの無料ユーザのみを対象としていたため *1、 各分岐において以下のような状況の組み合わせを、検証すべき条件として考えました。

  • ユーザの状態がどうか
    • ログイン済みユーザ or ゲストユーザ
    • プレミアムサービス会員ユーザ or 無料ユーザ
  • Android のクックパッドアプリのバージョンが決済対応バージョン以降かどうか
  • 決済可能端末かどうか
    • クックパッドがプリインストールされているらくらくフォンなどの場合、Google Play ストアアプリがないため Google Play 決済も利用できない
  • 異常な操作をした場合でも、何らかの方法で本来あるべき状態に復帰可能かどうか
    • この画面を表示している状態で Web からクックパッドのユーザ登録を解除してみる
    • この画面を表示している状態で Web からクレジットカード決済でプレミアムサービスになってみる
    • ここでフライトモードにしてみる

もちろん全ての組み合わせが成立するわけではありません。 例えば決済可能端末かどうかについては、決済不可能端末を伝える画面にて遷移がストップするため、以降の画面については考えない、といった具合です。

前提条件を再現するシナリオを作成する

それぞれの状況が洗い出せると、それらを組み合わせることでユーザが何をしようとしたかのシナリオが書き出せます。

状況の羅列にはなりますが、シナリオを作成しておくことで見通しが良くなり、仕様の考慮漏れについて気づきやすくなります。

例えば、

「ログイン済みユーザが Google Play 決済用画面を開いた状態で Web からクレジットカード決済でプレミアムサービスになった場合、
 Google Play で決済するボタンを押すと既に課金済みであることを示すダイアログが表示される」

といったものです。

そのシナリオをなぞるための手順を埋める

シナリオまで埋め終わると安心してしまいがちですが、書き手以外が再現可能なレベルで手順を埋めるまでがテストケース作成です。

テストケースは、一度作成すると、製作者本人が望もうが望まなかろうが再利用される可能性が高いです。 現にクックパッドでは、作成されたテストケースは今後のテストケース作成の参考にできるよう、社内で共有されています。

コードや文章に限らず、テストケースも、書いた本人ですら暫く経つと書いた内容やなぜこう書いたかを忘れがちです。 テストケースが雑に書かれていた場合には、この記述が当時何のために書かれていたのかを考古学する必要が出てきます。

そのため、なるべく丁寧に書きましょう。

先程の

「ログイン済みユーザが Google Play 決済用画面を開いた状態で Web からクレジットカード決済でプレミアムサービスになった場合、
 Google Play で決済するボタンを押すと既に課金済みであることを示すダイアログが表示される」

というシナリオの例に対しての手順を具体的に書くと、

  1. 無料ユーザでログインした状態でアプリのトップページを開く
  2. サイドメニューのプレミアムサービス会員登録導線をタップする
  3. Google Play 決済を利用するボタンを押す
  4. ブラウザアプリを起動し Web からクックパッドのトップページにアクセスする
  5. Web から先ほどと同一のユーザでログインする
  6. Web のトップページのプレミアムサービス会員登録導線を開く
  7. Web の登録ページからクレジットカード決済を利用してプレミアムサービスに登録する
  8. アプリの画面に戻り、プレミアムサービスに Google Play で決済するボタンを押す

といったものになります。

その手順を行うことで期待されるアプリの振る舞いを埋める

こちらも先程の手順同様、丁寧に書く必要があります。

先程の手順の例に対応するアプリの振る舞いとしては以下のようになります。

  1. 無料ユーザ向けのトップページが表示される
  2. プレミアムサービスを訴求する画面が表示される
  3. Google Play 決済用の画面が表示される
  4. Web 版のクックパッドのゲスト向けページが表示される
  5. 先ほどと同一ユーザでログインしたトップページが表示される
  6. Web のプレミアムサービスを訴求する画面が表示される
  7. プレミアムサービス登録完了ページが表示される
  8. 既にプレミアムサービス登録済みであることを伝えるダイアログが表示される

異常系であれば、どのような操作をすれば正常系に復帰できるかを伝える画面が出ていることを期待します。 そのため、ある操作の流れで何らかの異常を伝える画面を見たユーザが、その内容を読んだ際に混乱しないかについても確認ができます。

テストケースを作成して得られた良い副作用

テストケースを作成して得られる一番の良い副作用は、仕様の考慮漏れに気づけることです。

テストケース作成前は、Google Play ストアによる決済用システムダイアログが出ているときにブラウザアプリから別な決済手段にてプレミアムサービスを登録したらどうなるのか? というケースについて考えられていませんでした。

Google Play ストアの決済用システムダイアログが出てから決済処理完了までは、クックパッドではその経過状況を知ることが不可能です。 そのため、残念ながら決済完了時に Google Play の購読情報をクックパッドに送る際に二重課金が起きていることを伝えることになります。 幸いにも既に別で考慮していたケースと同様にユーザに重複課金を伝え、問い合わせを促す画面を表示できるような実装になっておりました。

また、テストケースを作成することで、検証の手順の理解や進捗が属人化しなくなるため検証を分担したりダブルチェックしたりできます。

加えて、きちんとやったから大丈夫、という安心感がえられます。

もちろんリリースして運用に入るまで何が起こるかはわからないですが、 最大限やることはやった!という安心感を持ってリリースできるので精神衛生上良いです。

テストケース作成期間について

テストケース作成に着手してから、検証し、修正完了するまでに 1ヶ月ほどかかりました。 開発期間全体のおよそ 1/3 もかかってしまった理由は、テストケース作成と並行して API 実装を始めとした他の作業などもやっていたためです。

しかし、効率的な開発を目指す上で、必ずしもテストケース作成期間を短くする必要はないと考えています。

というのも、仕様を煮詰めながらテストケースも整理していくことで、結果的に考慮漏れによる実装の手戻りを減らすことができるからです。 仕様を煮詰めている段階でテストケースも同時に作成していくことは、回り回って効率的に開発を進めることができると感じました。

最後に

検証を怠ることは、ユーザに検証をさせることと同義です。

もちろんすべてのケースを想定したテストケースを作成するのは不可能です。 しかし、ユーザにサービスを提供する以上、リリースまでに最善をつくすことに価値があると考えております。

テストケースは技術部品質向上グループチーム(以下 QIT: Quality Improvement Team)と密に協力して作成しました。 QIT はクックパッドのアプリを利用したユーザが技術的な問題で残念な思いをする体験を減らすための専門家集団です。

このように、クックパッドでは新機能リリースプロジェクトのために様々な分野のエンジニアが一丸となって取り組みます。

そのため、クックパッドではアプリケーションの品質向上に興味のあるエンジニアや、企画から、実装、テストケース作成までを一貫して行うエンジニアリングに興味のあるエンジニアを募集中です。 興味がある方は採用ページまで!

*1:現在はクックパッドに会員登録、もしくはログインしていないユーザでも Google Play 決済を利用してプレミアムサービスを利用できます

Firebaseを活用したiOSアプリ開発事例

こんにちは。新規サービス開発部の中村です。

最近Komercoで販売されている鉄のフライパンが欲しいです。クリエイターさんたちの作品は見ているだけで本当に楽しいですね。

そんなKomercoはバックエンドにFirebaseを活用していますが、実は弊社からKomercoの他にもFirebaseを活用したサービス「Cookin'」をリリースしています。

本稿ではCookin'のFirebaseを活用した事例についてご紹介します。

Cookin'とは

Cookin'は料理動画撮影アプリです。手順ごとに3秒間取るだけで1本の料理動画が投稿できるサービスとして、2017年12月にiOSアプリとしてリリースしています。

このサービスの特徴は、簡単に料理動画が作成できるほかに、投稿から斬新なアイデアを得られたり、コメント欄から料理のコツやポイントを気軽に質問できるところです。

料理をしながら動画撮影するのは難しいですが、慣れると楽しいです。

App Store リンク

誠に勝手ではございますが、Cookin’は提供サービスの見直しにともない、2018年7月末をもちまして、提供を終了いたします。ご利用のお客様には、ご迷惑をおかけいたしますことを深くお詫び申し上げます。サービス終了に関するご案内はこちらをご覧ください。

FIrebaseの活用事例

先ほど述べた通り、Cookin'のバックエンドはFirebaseを活用しています。Firebaseには様々なプロダクトが用意されていますが、Cookin'では以下のプロダクトを活用しています。

アプリの開発とテスト ユーザー層の拡大と利用促進
Authentication Cloud Messaging
Cloud FIrestore Google Analytics for Firebase
Cloud Storage
Cloud Functions

以降ではこれらの概要と活用事例をご紹介します。

Authentication

Authenticationは安全な認証システムを提供しています。メールアドレスとパスワードの組み合わせ、電話番号認証、匿名認証、Google、Twitter、Facebook、Githubのログイン等をサポートしています。

活用事例

ユーザーの認証に匿名認証を活用しています。これにより、データベースやストレージのセキュリティーを堅牢にしつつ、初回起動時のアカウント作成プロセスを省略することでユーザーの離脱を防いでいます。

匿名ユーザーは必要に応じてメールアドレスとパスワードでの認証に切り替えることも可能です。

匿名ユーザーのアカウントを停止したい場合は一手間必要になります。詳細はこちらのブログ記事をご覧ください。

Cloud Firestore

Cloud FirestoreはNoSQLドキュメントデータベースです。オフラインの場合でもデータにアクセスして変更を加えることができ、オンラインに復帰すると自動的に変更したデータを同期します。スケーリングは自動的に行われ、セキュリティールールを書くことでセキュリティーを堅牢にできます。

活用事例

  • 投稿情報、コメント、ユーザー情報等を保存しています。
  • 投稿画面に閲覧しているユーザーのアイコンをリアルタイムで表示しています。このようなリアルタイム機能を素早く実装できることも大きな特徴です。

    閲覧ユーザーアイコンのキャプチャ

  • ユーザーページの投稿一覧は、クエリ機能を利用して全体の投稿から特定のユーザーの投稿を取得して表示しています。また、クエリを利用してソートやページングを実装しています。

    全体の投稿から特定のユーザーの投稿を取得するクエリの例

    postsRef.whereField("authorID", isEqualTo: user.id)

    ユーザーページのキャプチャ

現時点ではCloud Firestoreにバックアップ機能が提供されていないため、バックアップする場合は自前で行う必要があります。

Cloud Storage

Cloud Storageは写真や動画等の容量が大きなファイルを保存できます。Cloud Firestoreと同様オフラインサポートと高いスケーラビリティを備え、セキュリティールールを書くことでセキュリティーを堅牢にできます。

活用事例

  • 動画やサムネイル画像を保存しています。

  • セキュリティールールの例を上げると、Cloud Storageにアップロードされる動画のファイルサイズを1MB以下に制限するために、下記のセキュリティールールを書いています。

セキュリティールールの例

service firebase.storage {
  match /b/{bucket}/o {
    match /version/1 {
      match /video/{videoID}/file/{file} {
      
        // 認証済みユーザーのみ動画ファイルの読み込みが可能
        allow read: if request.auth != null;
        
        // 動画ファイルが書き込まれる際の条件
        allow write: if (request.auth != null && request.resource == null)
                     || (request.auth != null &&
                     // 1MB 以上の動画ファイルは許可しない
                     request.resource.size < 1 * 1024 * 1024 &&
                     request.resource.contentType.matches('video/.*'));
      }
    }
  }
}

Cloud Functions

Cloud FunctionsはCloud FirestoreやCloud Storageへのデータの追加や変更、またはHTTPSリクエストによりトリガーされたイベントに応じてバックエンドコードを自動的に実行できます。

活用事例

  • プッシュ通知やSlackへのメッセージ送信に活用しています。例えば、ある投稿に新しいコメントが書き込まれたときに、投稿者にコメントが書き込まれたことをプッシュ通知で知らせたり、アプリから不適切な投稿が報告されたときにSlackにその報告を流しています。

    Cloud Functionは1つのイベントを元に複数回トリガーされることがあるため、関数は何回実行されても問題ないように実装しておく必要があります。詳細はこちらのブログ記事をご覧ください。

  • 関数のディレクトリ構造・命名は以下のようにしています。これにより、コードを修正をするときにどのイベントから実行される関数なのか把握しやすくしています。

それぞれのイベントから実行される関数が明確になります。

├── functions
│   ├── auth
│   ├── db
│   │   ├── comment
│   │   │   └── onCreate.ts
│   │   ├── feedback
│   │   │   └── onCreate.ts
│   │   ├── post
│   │   │   └── onCreate.ts
│   │   └── report
│   │       └── onCreate.ts
│   └── storage
├── index.ts
├── test

どのイベントから実行される関数なのかファイルの中を確認しないと分からないため把握しにくいです。

├── functions
│   ├── notifyPost.ts
│   ├── notifyComment.ts
│   ├── notifyReport.ts
├── index.ts
├── test

関数のテスト

テストフレームワークはJestを利用しています。

テスト方法はオフラインモードとオンラインモードの2種類あり、オフラインモードで行う場合、データベースの書き込みを全てスタブしなければならないため、オンラインモードで行っています。

オンラインモードではデータベースへの書き込みやユーザーの作成などが実際に行われ、テストコードがその結果を検査できるように、テスト専用のFirebaseプロジェクトとやり取りするテストを作成します。

注意点として、Firebase Test SDKのfirebase-functions-testnpmモジュールをテスト専用のFirebaseプロジェクトの構成値で初期化した後、メイン関数ファイルをモジュールとしてインポートしなければなりません。

この順序を守らないと予期しないFirebaseプロジェクトとやり取り(書き込み・読み込み)が行われてしまうことがありました。

防止策として、JestのsetupFilesのタイミングでfirebase-functions-testnpmモジュールを初期化するようにしています。

Cloud Messaging

Cloud Messagingは、iOS、Android、ウェブ(JavaScript)クライアントアプリに通知メッセージを送信することができます。

活用事例

Cloud FunctionsからAdmin FCM APIを利用してプッシュ通知を送信しています。

ユーザーが料理を始めたことを知らせる通知自分の投稿にコメントが届いたことを知らせる通知の2種類を送信しています。

Google Analytics for Firebase

Google Analytics for Firebaseは、最大で500種類のイベントに関するレポートを無料で無制限に生成できます。Firebaseのコンソールからダッシュボードを見ることができます。

活用事例

ユーザーの動画閲覧から動画投稿までのファネルを作成して活用しています。

その他のライブラリ

以降はFirebaseの他に活用しているライブラリの一部をご紹介します。

Pring

データの読み込み・書き込みにPringを活用しています。

PringはCloud FirestoreとCloud StorageのO/Rマッパーで、Cloud FirestoreとCloud StorageのAPIを意識せずにデータの読み込み・書き込みができます。

Pringを活用すると開発スピードを加速させることができます。

FilterCam

iOS SDKのCore Image FIlterを適用した動画を簡単に作成することができます。

撮影した料理がより魅力的になるように彩度と中間色の明るさをやや上げたフィルターをFilterCamに適用して活用しています。

適用前(左) 適用後(右)

まとめ

本稿を通してiOSアプリのバックエンドにFirebaseを活用した事例をご紹介しました。

Firebaseは開発が活発で新しい機能が追加され続けているので、今後もより使いやすくなることが期待できます。プロダクトの性質に合わせて、うまく活用できれば大きなメリットが得られるのではないでしょうか。

最後になりましたが、冒頭に記載しました通り、Cookin'は7月末をもちまして提供を終了いたします。これまでCookin'を支えてくれた皆さまに感謝申し上げます。ありがとうございました。

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