parseでちゃんとアプリを作るコツ
TRANSCRIPT
Parseでちゃんとアプリを作るコツ
~サーバー運用をしないアプリ開発の時代へ~
Indie Inc. Co-Founder & CTO Takuya Tejima
自己紹介
• Takuya Tejima (@tejitak)
• IBM -> LINE -> Indie Inc
※ DevMorningという朝活を毎週やってます
Parseとは
• https://parse.com/
• 2013年にFacebookが買収したMBaaS(Mobile Backend as a Service)
2015/12現在 IoTなどに力を入れている模様 (AppleTV / AppleWatch向けSDK公開)
ReactベースのDashboardに書き換えられた
日本だと、CyberAgent, mixi, Wantedly, Tokyo OtakuModeなどが大きなユーザー
Parseの特長• バックエンド実装のサービス化
• Data Store
• インデックス自動生成&勝手にスケールしてくれる!!
• ユーザー管理 (Auth / Role)
• プラットフォーム対応
• SDK for Desktop + Web / Mobile / Embedded + IoT
• File / Code Hosting
• Mobile Push配信
• App Monitor / Analytics
Pricing
• https://parse.com/pricing
Data Store
30req/sec
Data/File 20GB / Transfer 2TB
までFree
Push
100万通知/月までFree
Analytics
Free
実際BaaSってどうなの?• 複雑な処理やクラス構造に対応できるの?
• -> できる
• パフォーマンスは?
• -> 自前でチューニングした方が速いかもしれないが、Facebookが作ってるし大丈夫かと
• 学習コストは?
• -> 2, 3日ドキュメント読めば大体わかるかと
• 将来replaceできるの?
• -> Parse上で定義したAPIと同じものであれば容易に移行できるはず
個人的な結論
使うかどうかは結局費用対効果の問題。例えばサーバーの運用をするメンバーがいない場合は、積極的に使う価値がある
ちゃんとアプリを開発するためのParseの機能紹介
• SDK
• Data Store
• Class定義
• GeoPoint
• File
• relationship (Pointer / Relation)
• 認証 / SNS連携
• Role / ACL
• API Console
• Cloud Code
SDK
• 豊富な種類のSDKが用意されている
• https://parse.com/docs
まずはREST APIのDocumentを読むことがオススメ(他のSDKはREST APIをWrapしている)
https://parse.com/docs/rest/guide
SDK• オブジェクトを新規保存するコード例 (JS)
var GameScore = Parse.Object.extend("GameScore"); var gameScore = new GameScore(); gameScore.set("score", 1337); gameScore.set("playerName", "Sean Plott"); gameScore.save(null, { success: function(gameScore) { alert('New object created with objectId: ' + gameScore.id); }, error: function(gameScore, error) { } });
• オブジェクトを読み出すコード例 (JS)var GameScore = Parse.Object.extend("GameScore"); var query = new Parse.Query(GameScore); query.get("xWMyZ4YEGZ", { success: function(gameScore) { // The object was retrieved successfully. }, error: function(object, error) { } });
https://parse.com/docs/js/guide (JS SDKはbackbone.jsベースで作られている)
クラス定義• Data Browserで直接データの管理ができる
• クラス定義
• データセットの雛型をクラスとして定義できる
• 自由にカラムを追加できる(後から柔軟にスキーマの変更が可能)
• カラム(クラスのフィールド)ごとに型の定義が可能
• 選択可能な型指定: Boolean, String, Number, Date, Object, Array, GeoPoint, File, Pointer, Relation
• 型はJSON形式で“__type”プロパティとして格納される (e.g. __type: ’Pointer’)
• 全てREST APIで操作が可能
/1/classes/<className> POST Creating Objects
/1/classes/<className>/<objectId> GET Retrieving Objects
/1/classes/<className>/<objectId> PUT Updating Objects
/1/classes/<className> GET Queries
/1/classes/<className>/<objectId> DELETE Deleting Objects
REST API
File• S3みたいなもの
• APIでPOST
• http://files.parsetfss.com/bc9f32df-2957-4bb1-93c9-ec47d9870a05/tfss-db295fb2-8a8b-49f3-aad3-dd911142f64f-hello.txt
• Objectの任意のpropertyに関連付け可能
• File自体のDELETEにはMaster Keyが必要
{ "name": "Andrew", "picture": { "name": "...profile.png", "__type": "File" } }
GeoPoint
• GeoPointクラスを使用すると位置情報のクエリを簡単に実現できる
• __type=“GeoPoint”でlatitude /longitudeプロパティを持つ
• GeoQuery
• 与えた位置情報の近くを検索: $nearSphere
• 指定した2地点を橋とする四角形内で検索: $winthin.$box
Relationship (Pointer vs Relation)
• 参照・関係を表現する型としてPointerとRelationが使用できるPointer 参照オブジェクトを格納するもの。Pointerを保有クラスへの1回のクエリとして展開して含めることができる
Relation 関連を定義し、関連アイテムの追加・削除が可能。Relationを保有するクラスへの1回のクエリでは取得できない
• 関連ごとに幾つかのアプローチが可能
• Pointer (one-to-one、one-to-manyリレーション向け) • Pointer Arrays (one-to-many、many-to-manyリレーション向け) • Parse Relations (many-to-manyリレーション向け) • Join Tables (many-to-manyリレーション向け)
• ArraysとRelationsの使い分けは?-> 一回で取得したい場合、そして数が少量(約100以下)ならArray
• Join Tabelsは?
• ケース1 参照関係を双方向から同レベルで解決したい時にArraysやRelationを双方向に持つより有効 (e.g. この写真にいいねをした人のリストが欲しい / この人がいいねをした写真のリストが欲しい) relationを双方に持たなくても逆のクエリは発行できるが、queryが非効率だったりする
• ケース2 “関係”そのものにメタデータが必要な時有効(e.g. 関係の作られた日時など)
認証・SNS連携• 認証
• Pre-definedなUser / Sessionクラスが用意されている
• 各SDKに用意されているloginメソッドを使用するだけで、ユーザーデータの更新とセッションの管理をしてくれる
• SDKを使用しない場合は自前でsession tokenを保持する必要あり(Webならcookieなどに保持してX-Parse-Session-Tokenをhttp headerに付与)
• sessionのvalidationするには https://api.parse.com/1/users/me or https://api.parse.com/1/sessions/me
• Facebook / Twitter OAuth認証はParseの設定画面でAppIDなどをセットしておけばSDKによってコードレスで実現可能
Role / ACL
• UserにAssignできるRoleを定義できる
• 例: Admin roleの定義など
• 各Role / UserごとにACLを設定できる
• 例: Publicにはread only, adminと特定ユーザーだけwriteも許可
API Console
• Debug用に便利なAPI Consoleが提供されている
• Demo
Likeの実装例• クラス構成のアプローチ
• 1 Pointer Arrayを使う
• 2 Relationを使う
• 3 Join Tableを使う
• HashDishでは将来の拡張性を考慮してActivityというクラスをJoin Tableとして使っている
• 適切なACLの設定
• ACLの付与はRow単位。Columnごとに設定できないので、一つのクラスに編集させたくないデータとユーザが変種可能なデータは基本的に混在してはいけない (-> 後述のCloud Codeをすることで実装することは可能)
Cloud Code
• Trigger: コードをParseにhostして、データ変更をhookすることができる
• beforeSave, afterSave, beforeDelete, afterDelete
• 追加処理 (e.g. likeされたら別クラスにlike countをincrement)
• validation (e.g. すでに同じユーザーがlikeしているかどうかcheck)
• Function:
• JSのコードで独自のAPIを実装できる
• session tokenがvalidなリクエストの場合User情報を利用できる
• リクエストをまとめたい時に便利
• debugは少し大変
• debugger + node-inspectorでなんとかなる
• https://github.com/mariusciocan/parse-cloud-debugger
• JSのコードをホスティングして、API hookや独自のAPIを定義することができる強力な仕組み
Cloud Code Triggerの例• likeした時にadmin roleとそのユーザー自身のみwrite可のACLを付与するhookを追加する例
var Activity = Parse.Object.extend("Activity");
var createMyACL = function(userId) { var acl = {}; acl["*"] = {"read": true}; acl["role:admin"] = {"read": true, "write": true}; acl[userId] = {"read": true, "write": true}; return acl; };
var assignACLTrigger = function(request, response) { // allow master if (request.master) { return response.success(); } // user must be authenticated if (request.user) { // Request to update existing row. Let it proceed. // The PUT request will cause error by ACL if the user is invalid if (!request.object.isNew()) { return response.success(); } // set ACL for POST request request.object.set('ACL', createMyACL(request.user.id)); response.success(); } else { return response.error("Not logged in."); } }
// modify POST request with ACL Parse.Cloud.beforeSave(Activity, assignACLTrigger);
Parseを活用するためのコツ
• クラスの定義はPointer / Relation / JoinTableを場合に応じて利用する
• ACLの設定はきちんとする(デフォルトでpublic read/writeになってたら誰でもデータ消せちゃうよ)
• Cloud Codeの活用
• 適切な追加処理の実装
• ACLの付与やvalidationなど各プラットフォームのクライアントでの冗長な実装の防止。
• リクエストの効率化
• 完全にRESTfulだと初期ページに3 requestsくらい必要だったりする -> cloud codeで一つにまとめる
他にも色々な機能がある• サーバーテンプレートのホスティング (cloud codeでexpressが動くらしい)
• Jobs
• Schedule可能なbatch処理の実行
• Push
• ユーザーグループを作って配信するだけ
• schedulingもdashboardから可能
• localize
• 100万件/月 配信まで無料
• Analytics
Thank you