Android+slim3(appengine)連携の冴えたやり方?
わかめの言ってること分からんって言われたのでちょっと書き直しました。
Android+appengineは、昔きょーりゅーてんていが言ってた通り、夢の組み合わせなわけですよ。
世界中で動く端末!個人が気軽に使える(気分的に)無限にスケールするサーバ!!
ただ、今まで冴えたサーバ、クライアント間連携の仕方って思いつかず、2〜3ヶ月くらいずっと悩んでました。
最近、一応現実的な解を思いついたので、ここに書いてみんなから意見を貰えたらなぁと思います
目指すこと
サーバ側とクライアント側での通信内容を解釈するためのコーディングをほぼゼロで済ませたいし、テスト可能な作りにしたい。
手作業で通信内容をパースするような処理を書くと、エンバグする可能性がある。こわい><
そのために、フォーマットを規定するPOJO自体を共有化したい。
前提
通信は基本的にJSONで行う。
JsonPullParserをガンガン使う (次バージョン(0.3?)からDeserializeだけじゃなくSerializeも出来るようになる予定)
結論
クライアント←クライアント用モデルプロジェクト→サーバUnitTest こうする。
方針
困ること
1. Slim3のアノテーションが邪魔
ただまぁ、これはSlim3の@ModelはリテンションがSOURCEでコンパイルすれば消えてしまうアノテーションであることと、@AttributeはリテンションがRUNTIMEですが、これもまぁAttributeのモックアノテーションを作ってクライアント側で利用するか、ProGuardかなんかでアノテーションを取り除いたclassを生成してやればいいのかなという気がしなくもないです(できるか知らないけど)。
2. サーバ側EntityとAndroidのモデルを共有化するとデコンパイルされてサーバ側の保持データがバレる
デコンパイルされるとかなり困る。例えば、JSONでやりとりしているデータ以外に更新日付やアクセス元IPアドレスを保持している、とか、JSONでやりとりしないデータに、サーバ側の動作制御用Entityが絡んでいて、コンパイルを通すためにはそのEntityも含めないといけないので制御用Entityの構造も一緒くたにバレる。
とかがあって、サーバ側とクライアント側のモデル(=JSON変換ライブラリ)を共有化するのは辛いよなぁ…という結論になりました。
最初は1だけしか気がついてなくてここさえクリア出来れば…!!とか思ってたんですけど、2がでた瞬間サーバ側Entity構成を全部バラさざるを得ないことが判明して挫折したわけです。
解決方法
結局、サーバ側とクライアント側のモデル共有化は諦めることにしましたorz
で、代替案としてどうすることにしたのか?
クライアント←クライアント用モデルプロジェクト→サーバUnitTest こうすることで、クライアント側とのIFの整合性が取れていることを自動的に担保するようにすればいいのではないかと思いました。
具体的には
(一)クライアント用モデルプロジェクト作成
(一)サーバから送られてくるデータにあわせてPOJOを作成
(二)JsonPullParserを適用
(二)antでコンパイルし、クライアントにjarをインポートして利用 (POJO+JsonPullParser生成物)
(三)mvnでコンパイルし、サーバ側で scope test で利用
(一)UnitTestで処理結果をクライアント側モデルに突っ込み、エラーが発生しないことを確認
ていう感じでやっていってみようかと。
今回テストしているのはサーバ→クライアント側の通信だけですが、まぁ今回はこれでいいかなと
クライアント→サーバ側通信で考えられるのは
(一)普通の?hoge=fuga&hige=nobiru
(二)JSONをPOSTで送信
の2パターンないしその組み合わせかと思います。
1についてはまぁ適当にやればいいですし、2についてはSlim3 1.0.6からSimpleControllerというInputStreamが扱えるコントローラが増えたので、それを使えば楽に検証できていいと思います。
参考リンク 404 shin1のつぶやき ないわー Not Found: #slim3 1.0.6 のSimpleControllerを使った場合のテスト方法 #appengine
問題点
クライアント側とモデル編集をする人と、サーバ側の担当者が別だと、モデル編集されてコミットされるとサーバ側のテストが壊れてHudsonさんに超絶怒られる。
→めんどくなって手動でjarを更新したものがHudsonさんにも適用されるように設定を変える→即時チェックの恩恵が薄れる→喧嘩になる
こういう未来が見える('A`)ドウシヨウ
将来的には
モデルの共有化は辛いということがわかったので、O/RマッパーならぬO/Oマッパーが必要なのかなぁ…と思ったり。あるクラスとあるクラスで、名前が同じフィールドがあったら相互変換できればいいよね的な。
Twitterでもうちょっとおはなししました。
APTについて、追加で分かってきたこと
前回記事 [id:vvakame:20101223:1293086110]
ここから、こうした方がいんじゃね?って思ったことにちょっとだけ変化が発生したので、書いておきます。
どうでもいいこと
改善点
ソース出力処理自体
前回時点
2パス処理すればいいよ!!→1パス目でエラー検出、2パス目で逐次処理的にソース出力
これは、今となっては分かりにくいなーという感じっす。
分かりにくさの理由として、ソース内の色々な場所でソース出力処理を行っているので可読性が悪く、全体を把握しないとどういうソースが出力されるか不明なためです。
まぁ、出力後ソースが手に入るので死ぬほど辛いって感じじゃないと思いますが。
今時点の認識
テンプレートエンジンを使うといいよ。ってなりました。
そのためには、2ステップ処理をするように変更して、1ステップ目でエラー検出&生成用データを保持したデータの作成、2ステップ目でテンプレートエンジンへのデータ流しこみを行っています。
https://github.com/vvakame/JsonPullParser/blob/master/jsonpullparser-apt/src/main/java/net/vvakame/util/jsonpullparser/factory/GeneratingModel.java
https://github.com/vvakame/JsonPullParser/blob/master/jsonpullparser-apt/src/main/java/net/vvakame/util/jsonpullparser/factory/JsonElement.java
JsonPullParser/JsonModelGen.java.mvel at master · vvakame/JsonPullParser · GitHub
前回発表時[twitter:@zaki50]さんに"Velocityいいよ!"って言われたんですが、制御構文とかの使いにくさとかもあって、[twitter:@esmasui]さんに教えてもらったMVELを現在は利用しています。
テンプレートエンジン自体も抽象化して差し替え可能な構造にしてます。
こーすると、Javadocを提供するのも超簡単で便利です!
デバッグで止めて、テンプレートエンジン流しこみ直前のデータを見ればどういう処理が行われるのか人目でわかりますし、利点が大きいです。
また、import文を既知のものについては使えるので、動的に差し替える部分以外はSimpleNameを利用でき可読性が一応あがっています。
ただ、空行とかがガスガス入るので、見栄えはちょっと悪くなりましたw
弱点
複数プロジェクトでPOJOを共有し、別々のプロセッサを適用したい場合にうまい解決策がない。
jar化されたclassファイルに対してプロセッサを再適用する方法とかがない。
ていうのがわかった。[id:vvakame:20110130:1296356939]で困ってるのはそれが一因かも。