トレタ開発者ブログ

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

Empty State表示共通化の事例

トレタ Advent Calendar 2018の24日目の記事です。
iOSエンジニアの@kenkenken_3が担当しております。

Empty State表示(0件表示、何もないよ状態の表示)共通化について、トレタの事例をご紹介します。

potatotips #57で発表させてもらいました。

本件はエンジニアだけでなく、デザイナー・プロダクトマネージャーと協力することによって実現したいい取り組みだったと感じています。

そして、スライドの出来栄えもいい感じではなかったでしょうか・・・?
実はこれ、トレタのデザイナーが作成したテンプレートを利用しています!
以前はスライド作成に結構時間がかかっていたのですが、今回は大幅にスライド作成時間短縮できた上にクオリティは格段にアップ!嬉しい!!

テンプレートに関してはデザイナーdate001の記事がありますのでこちらも是非ご覧ください。

note.mu

こんな感じで私としては毎日楽しんで仕事ができています。
興味を持った方がいたらお気軽にトレタに遊びに来てくださいね!

明日はトレタ Advent Calendar 2018最終日。
記事を書くのはなんとあの・・・!?
お楽しみに!!

入社2ヶ月から見たトレタについて

この記事は、トレタ Advent Calendar 2018の11日目*1です。

こんにちは、トレタ技術部バックエンドエンジニア兼マネージャーの @joy04d です。 入社2ヶ月目の新人でございます(=ω=)

さて、ここでは華々しくあれそれこういう課題があって、こういう風に解決しました!みたいな記事を書きたいところなのですが、そこは悲しいかな、新人なので特筆すべきことがありません。細かいことは色々あるのですが、大変地味な話になってしまいます。そこでこの記事では、新人であることを生かして入社2ヶ月の私の目からトレタがどういう風に見えているのかを(率直に)紹介したいと思います。

労働環境について

ということでまずは細かいところから、労働環境についてです。

自分が0歳児を抱える(予定の)子育て世代というのもあり、今回の転職ではワークライフバランスを意識していたのですが、この点トレタは素晴らしいですね。基本が

  • 11-16時をコアタイムとするフレックスタイム制
  • 毎週水曜日はリモートワーク推奨

となっており、またこれも事情に合わせてかなり柔軟に運用可能なので、大変助かっております。お互いを尊重する文化に根ざした優しい雰囲気があり、無理なく仕事と育児を両立できそうだと感じています。

また、エンジニアとして気になる開発環境についても文句のない状況です。開発マシンはPCのスペックからモニターやハブなどの周辺機器まで要求通り、気分に合わせて開発できるスペースがあったりと、ストレス無く開発できております(>∀<)

開発について

トレタではコアとなる予約・顧客台帳のバックエンドにRuby on Railsを用いています。自分がこれまでPHPPythonメイン、薄めのフレームワークを主に扱っていたため、新鮮な気持ちで開発しております。

5年の歴史があるサービスなので少し作りが苦しいところもあるのですが、その辺りの改善に前向きに無理なく取り組めている点も良いところだと思います。そのためのリソースも随時投入されており、継続可能な開発のための投資の必要性がちゃんと浸透しているのは素晴らしいですね。

また、今後の展開に向けて新規サービスに golang + k8s を用いるなどの布石も打っており、事業や時代に合わせて変化していける開発組織だと感じています( ・∀・ )

一緒に働くひとについて

全体的に和やかな雰囲気で優しい人が多いです。と言ってもただ優しいだけではなく、内にちゃんと芯があり、また相手を尊重して結果を出していける人ですね。一言で言うと大人な方が多いといったところでしょうか。

また、エンドユーザーに常に向き合い良いサービスを作るという姿勢が社風としてあり、職種問わずコミットしていく方が多い印象です。新規機能や改善案を広げる場では、色々な角度から鋭い意見が飛び交うことも多く、日々勉強させていただいてます。みんなでトレタの導入店様に食事に行った際などにも、ちらちらと(迷惑にならない範囲で)使われ方を観察したり、その場で今後の議論をしたりと、皆でサービスに向き合っている感じは素敵だと思います。
(余談ですが、トレタでは福利厚生としてトレタ30という導入店様で食事を行った際に料金の30%を会社が負担してくれるという制度があります。自分たちのサービスがどのような環境でどのように使われているか見ておいで、という意図での制度だと思いますが、これは意図通りの使われ方ではないでしょうかw

トレタの掲げるバリュー

  • Issue First
  • Respect All
  • Dive!

というものがありますが、これはトレタの文化を良く表現している言葉だと思います。自分も早く体現できるように頑張って行きたいです(=ω=)

会社組織について

こちらは事業の成長に合わせて組織も変化する良いタイミングにジョインできたなーと思っています。
(2ヶ月の新人風情が何わかったようなこと言ってるんだ、という点はスルーしてくださいw

わたくしコードを書くのも好きなのですが、組織やチームを強くすることにも面白みを感じる人ですので、ベンチャーらしく変化と勢いがあり、また自らグイグイ動くことが推奨される文化(Dive!ですね) があるトレタは大変面白い環境です。
(一方で、自分の領分をきっちり定めてそれ以外はノータッチ、という方だとストレスを感じるかもしれません)

この辺りを踏まえてなのか、一応わたくしマネージャーのロールも負わせていただいている身でもありますので、今後この辺りも熱意と仕組みの両面を持って頑張っていきたいと思います( ・∀・ )

終わりに

ということで、新人から見たトレタについて書いてみました。
さっくり書いた記事ではありますが、この記事を読んで興味出た方がいれば、ぜひトレタに遊びにきてみてくださいね(>∀<)

*1:3日ほど遅れてしまっていますが( ̄ー ̄)

トレタ初のiPhoneアプリ、トレテルをリリースしました

技術部でiOSを担当している高(@y_koh)です。

入社以来予約台帳アプリをメインに見てきたのですが、今回スポットで「トレテル」の開発に携わりました。トレタ初のiPhoneアプリになります。

f:id:y_koh:20181116120247p:plain トレテル | 飲食店のための予約トラブル防止アプリ

今回トレテルのリリースにあたり、どの様に開発していたのかをご紹介できればと思います。

飲食店さまが頭を悩ませるNo Show問題

まずその前に。

「No Show」という言葉を聞いたことがあるでしょうか。

僕はトレタに入って初めて知りました。「No Show」とは飲食業界や宿泊業界で言われる「無断キャンセル」の通称です。予約をしていたにもかかわらず当日連絡もなく現れない。見込んでいた売上が立たないだけでなく、本来受け入れることが出来たお客さまを断っているケースもあります。またそのために用意していた食材が無駄になってしまうこともあります。

売上だけでなく、心情的にもかなりのダメージがあります。

宿泊や航空券のようにシステム的に対応できていないからという問題もあります。もちろん将来的にはそうなるべきだと思うのですが、今すぐに、というのが難しいのが現状です。この様な現状があり、飲食店さまからするとかなり根深い問題になっています。

この様な状況を重く捉え、今回、経済産業省からガイドラインとして下記が発表されました。

No show(飲食店における無断キャンセル)対策レポートが発表! (METI/経済産業省)

無断キャンセル対策推進協議会にはトレタも参加しています。

さらに、トレタとして何か出来ることはないかということを考えて開発されたのが予約トラブル防止アプリ「トレテル」です。

トレテルってどんなアプリ?

f:id:y_koh:20181119150803p:plain

トレテルのコアバリューは、予約していただいたお客さまにキャンセルポリシーを伝え、お客さまの手でその内容に承諾していただくことです。今までの飲食店予約はここが曖昧になっていました。

実際に利用いただいている店舗さまにヒアリングしたところとても良いフィードバックをいただけました。正直アプリとしてはまだまだなのですが、実際にお店の課題を解決できたことはとても嬉しいことです。

f:id:y_koh:20181119151848p:plain

プロジェクトの発足(2018年1月)

さて、ここからはこのプロジェクトをどうやって進めてきたかをご紹介します。

最初にプロジェクトの話を聞いたのは今年の1月くらいです。要件も少ないし、1,2ヶ月くらいで作って出したいね、という話がありました。その時はまだ「No Show」を解決できるための何か、くらいのイメージでした。そこから色々と調整事があり、リリース時期は少し先の夏以降がターゲットとなりました。

プロトタイプでの検証(2018年3月〜4月)

f:id:y_koh:20181116120004p:plain

リリースまで少し時間が出来たので、まずプロトタイプを作って検証してみることにしました。

とはいえリソースはなかなか逼迫していたため、デザインだけ社内で行い、実装は外部の方に手伝っていただく形で進めました。このプロトタイプでの技術検証は後の本開発でとても役に立ちました。

f:id:y_koh:20181116133139p:plain
初期デザイン

プロトタイプで検証したかったことは3つあります。

  • Firebase環境
  • MVP(Minimum Viable Product)フィーチャー
  • ユーザーテスト

今回社内で初めてバックエンドにFirebase環境を使ってみることにしました。これはサーバサイドエンジニアリソースが無かったこともありますが、今回の様にわりと小さめのアプリを作るのであればサーバサイドもアプリエンジニア側で対応出来たほうが早いのではということで採用してみました。

また今後プロトタイプを実装する際に、Firebaseが使えるようになっていればアプリエンジニアだけでさくっと実装することができるのでそれに慣れておくためにも今回のプロジェクトは丁度よいなと思いました。

プロトタイプ検証の結果として、Firebaseが使えることと、MVPフィーチャーの精査はある程度出来ました。ただ、ユーザーテストは当初実際の店舗さまに使っていただこうとしていたのですが、諸般の事情により実現できず、社内だけでのテストとなりました。ここだけ少し心残りです。

この様なプロトタイプ検証を経て、実際の開発へと移りました。

本開発(2018年5月下旬〜7月)

f:id:y_koh:20181116120025p:plain

開発自体は8月頭には終わっていたのですが、リリース時期の調整等あり、しばらく寝かせていました。ちょうどXcode 10がリリースされたのでその対応と若干の調整をして11月1日にリリースとなります。

体制

  • プロダクトオーナー1名
  • iOSエンジニア1名
  • デザイナー1名
  • QA1名(テスト期間のみ)

プロトタイプ後の本開発は、この体制で約2.5ヶ月で行いました。

アプリ構成

アプリはシンプルなMVVMです。今回RxSwiftは使っていません。メインの台帳アプリのリニューアル話が進んでいたのですが、そこでRxSwift使うべきかどうかという議論をしていました。今回のアプリは規模も小さいのでRxSwift使わずにどうなるか試してみようということで使わないことにしました。

ウェブ画面

2画面だけですがウェブ画面もあります。SMSを受け取ったお客さまがキャンセルポリシーを確認して承諾する画面です。この画面はCloud functionsで実装しています。

開発で工夫したこと

アプリ開発に携わったことがあるメンバーが僕以外にいなかったため、全体的な開発プロセス周りやiOSデザインディレクション的なことをしました。

開発プロセスはまずガントチャートを作りました。これはスケジュール管理と言うよりは、見積もりのためです。新しいものを作るときにはどうしても要件が膨らみがちになります。それをちゃんと工数を見える化さするために作りました。

見える化できていると、「これやりたいんだけど…」と言われた時に「でもスケジュール的に余裕ないよね。これを外せば出来るけどどうする?」って話がしやすいです。やりたい気持ちは超わかるんですけど、ちゃんとリリースできること以上に大事なことはないので、気持ちはわかるよーと思いながらバッサバッサ切りました。

デザインに関しては、アプリとしてのコアは何なのか?ということをかなり話し合いました。プロトタイプを作ったとはいえやっぱりまだブレていたんですね。

あとは、アプリとして不自然な部分を一緒に直していきました。

例えば、最初のデザインではアプリを起動してすぐに予約を登録したいからという理由で一番左のタブに予約登録フォームが配置されていました。タブは画面遷移のボタンであると同時にそれぞれの画面の状態を持っているものです。つまり、フォームの入力中にその状態を保持したまま他のタブに遷移できてしまいます。下書きは別ですが、入力中という状態を持つ必要はないのでこれはモーダルにして入力中に他のことがしたくなった場合は、入力を完了するか破棄するかの二択にする方が自然だよ、みたいなことを一つ一つやっていきました。

Firebaseで大変だったこと

  • Cloud Firestore
  • Firebase Authentication
  • DynamicLinks
  • domain

ほとんどは初めての環境だからという部分が多かったです。とはいえ開発中に仕様が変わったものもありますし、消したいのに削除ボタン未実装なんてのもちょくちょくありました。Firebaseを実プロダクトに導入する場合は、ある程度結構余裕を持ってやるのが良さそうです。

Cloud Firestore

そもそもDB設計が久しぶりでした。その上RDBではなくNoSQLドキュメントベースDB。最初はちょっと戸惑いました。RDBで当たり前にできるようなcountやちょっと複雑なクエリも使えません。

DB設計に関してはmonoさんのこの記事がとても役に立ちました。
Cloud Firestoreの勘所 パート1 — 概要 – google-cloud-jp – Medium

ドキュメントベースではテーブル、レコードではなく、コレクションとドキュメントという考え方をします。これは呼び方が変わっただけではなく、考え方自体が変わります。RDBの場合、リレーションはありますが、基本的にすべてのテーブルは階層無くフラットな状態で考えます。

ドキュメントベースの場合はここに階層の概念が加わります。

今回のトレテルで言うと、予約のテーブルを作るのではなく、店舗ドキュメントの下に予約コレクションを持たせる形になります。こうすることでアクセス権をこの店舗の配下だけにして、店舗に必要な情報をまとめて取得することが出来るのですが、逆に予約情報を全て引っ張ってきたいときに1つのテーブルを見るということができません。

もし、調査目的で予約情報を全て見たいケースがある場合には、Cloud Functionsを使い、予約の追加をトリガーとして別の調査用コレクションにコピーするということが必要になります。

この辺はすこし考え方の変換が必要になるところです。

Firebase Authentication

Auth自体はそんなに難しいことはないです。ただ、認証に使う情報はAuthenticationとして扱うのですが、ここにメールアドレス以外のユーザー情報をもたせることが出来ません。

ユーザー情報を持たせる場合はFirestoreにusersコレクションを作って、そこに持たせることになります。ちょっと手間ですが、複数の認証プロバイダに対応したりするために切り出しているのかなと思います。

Firebase Dynamic Links

個人的に一番ハマりました。結局は完全に僕の勘違いだったのですが。

sendEmailVerificationを使ったメールアドレス確認をする際に、Dynamic Linksのドメインが必要になります。これを、Dynamic Links自体が必要と勘違いし、そのリンクURLをcontinueUrlに入れてしまっていました。

正しくは、ドメインだけあればよいのです。ドキュメントにもちゃんと書いてありました。 https://firebase.google.com/docs/auth/web/passing-state-in-email-actions?hl=ja#configuring_firebase_dynamic_links

ハマったのは、これでもなんとなく動いてたということです。ただ人によっては正常な挙動をしていなかったりして、調査した結果間違いに気づきました。

またさらに問題をややこしくしていたのが複数ドメインです。Dynamic Linksには複数ドメインを追加できるのですが、メールアドレス確認で送られてくるメールのリンクには、Dynamic Linksに登録された1番目のdomainが使われるみたいなのです。

Dynamic Linksの1番目は開発時に追加した不要なdomainで、これが使われてる理由がわからずハマりました。

Firebase所感

慣れるまで難しい部分がありましたが、総合的には良いと思います。実際にこれをFirebase無しで自分でサーバサイド組んでと考えると、、とてもじゃないですが終わらなかったと思います。

ステージングと本番環境を分けたいときにプロジェクトを完全に別にする必要があるのは少し手間です。ステージング環境で作ったものを本番環境にコピペしたいことはよくあるのですが、今の所一つ一つ手作業でコピペするしかないです。反映漏れが出てしまう可能性があるのが少し怖いですね。

またCloud FirestoreがまだBetaなのもあって自動バックアップが無いのもちょっと辛いところです。自動バックアップとBigQueryへの自動エクスポートが出来るとかなり使い勝手は良くなると思います。

終わりに

今回のプロジェクトで一番時間を取られたのはUIの部分です。正直ちょっと見積もり甘かったなと思っていてここは反省点です。プロトタイプ検証もしているし、基本的にきれいに整えていけばいいだろうと思っていたんですね。それがやっぱりこのサービスのコアって何だろうね、と考えるたびにUIも変わっていきました。

正直機能としては予約を登録して、SMSで送って、お客さまが承諾して、それを確認できるだけ、という感じでかなり絞っています。しかし、それでも考える量はこれだけ膨大なんなだというのは改めて痛感しました。特に軸となる部分が変わってしまうと全体を変える必要が出てきてしまってつらいですね。

トレタは基本的に台帳アプリを主軸にしているのでiOSのプロダクトはこれしかありませんでした。不用意にプロダクトを増やすのはメンテの観点から考えてもあまりやるべきではないと思うのですが、やっぱり新しいサービス開発は学ぶものが多いです。特にトレタアプリは10万行規模になってきていて何かをためそうにも気軽にできない状況があります。

もちろん、ビジネスに繋がらないものを出してもしょうがないのですが、こんなものがあればお客さまのこの部分は解決できるのでは?みたいなのはエンジニア側からもどんどん提案していきたいなと思っています。とりあえず今ひとつはアイディアがあって、さてこれをどうビジネスと繋げようかなというところです。

© Toreta, Inc.

Powered by Hatena Blog