追加:下記は React.js 実際使う前の書き込みです。こちらも:
React.js Vs AngularJS、どっちがいい その2
React.js Vs AngularJS、どっちがいい その3 - React.js 速い!
最近、隣のチームのプロジェクトでは AngularJS がヘビーだから、 React.js にしたと聞きました。最初、そのチームは AngularJS を使って、Demo を作りました。モバイルでテストすると、何かウェブサイトがすこし応答が遅いと思ったそうです。でも、それは AngularJS の問題ではないと思います。実際向こうのデモサイトを見てみたら、$timeout() がいっぱいあったりして、Directive もいっぱい作って、本来計算が終わったら、$apply を使うべきところを全部 $timeout を使ったりしていました。Angular の使い方としては間違ってると思います。Dirty Check はただ Model 変化をチェックする方法の一つです。Getter Setter の中にいろいろ判断するより、Dirty Check は理解しやすいし、重い処理は Framework に譲れたと思われています。
まぁ、そのチームが React.js に乗り換えったら、Flux を使って、プログラム全体の構造は3年前 Backbone.js を使った時とほぼ同じになりました。実際デモサイトと比べると、それほど速いと思われてないし、勉強とか、Cross Browser の対応とか、またいろいろ苦労したそうです。最初デモサイトがモバイルでは重いと思われたことは 300ms Click との関係もなくはないと思います。
しかも、React.js を使ったら、プログラム全体がわかりづらくなりました。Flux の Dispatcher を理解しない限り、どこで、何が更新されたかさっぱりわかりません。。。
逆に AngularJS だったら、Controller, Service とかすぐ見つかるし、Back end の開発者もある程度見ればわかります。
多分、区別はそこだと思います。React.js は Framework というより、ライブラリだと思います。つまり、アプリとみなすには、Flux などイベント Dispatcher、Model などをまた作らなければなりません。それを考えてみると、Polymer のほうが使い易いと思いますし、速度的には React.js の Virtual DOM より、それほど遅くないと思います、どうせメモリ上の比べだから、Dirty Check でも。
将来 AngularJS 2.0 をかなり期待できると思います。Polymer とのシームレスとか、遅延ロードとか、Framework としてはかなりいいフィーチャーになります。
まぁ、まだ React.js を詳しくみてないから、こう思ってますが、実際 React.js を View にして、AngularJS の Framework に組み込んだら、面白いかもしれません。
今のプロジェクト一段落したら、また React.js を使ってみて、AngularJS と比べたいと思います。
それでは。今現在の考えで。
Code
2015年7月30日木曜日
2015年7月5日日曜日
Youtube ビデオを responsive にする方法
先週、モバイルの WebView を使って、文章を表示する機能をアプリに追加されました。エディターから一つの要求は youtube のビデオを表示したいです。基本的に文章は Responsive をしているので、コンテンツは問題なく各種のモバイルスクリーンサイズが適応できますが、youtube ビデオは iframe の中にあるし、youtube の JavaScript ライブラリで作成されますので、responsive にするには with と height を 16:9 で固定する必要があります。ただ、iframe のサイズを変更するには JavaScript 以外だったら、すこし難しいです。特に、JavaScript を web page に使いたくない時があります。
調べて見たら、css- trick からcss だけで youtube ビデオを responsive にする方法がありました。まず、ifarme にラッパーに置きます。html は以下の通り:
<div class="video-wrapper">
<iframe width="480" height="270" src="http://www.youtube.com/embed/{youtube-video-id}?rel=0&hd=1" frameborder="0" allowfullscreen></iframe>
</div>
そのあと、css:
.video-wrapper {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
padding-top: 25px;
height: 0;
}
.video-wrapper iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
調べて見たら、css- trick からcss だけで youtube ビデオを responsive にする方法がありました。まず、ifarme にラッパーに置きます。html は以下の通り:
<div class="video-wrapper">
<iframe width="480" height="270" src="http://www.youtube.com/embed/{youtube-video-id}?rel=0&hd=1" frameborder="0" allowfullscreen></iframe>
</div>
そのあと、css:
.video-wrapper {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
padding-top: 25px;
height: 0;
}
.video-wrapper iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
ここのトリックは padding-bottom です。パーセンテージにすると、width の長さになります。ここ 56.25% を設定すると、width とのアスペクト比は 16:9 になります。
次、iframe を 100%, 100%, position を absolute に設定したら、親要素の中にフル表示されます。
参考にしたページは
css でいろいろできるなと。例えば、これ:
それでは。
2015年6月28日日曜日
RESTful API データが見つからない場合の処理
今 RESTful API をベースに iOS や Android のアプリにデータを提供するシステムを作っています。基本的になんでも json を返します。それで、HTTP メッソードを使ったり、 HTTP Response コードを使って、フロントエンドとやりとりをしています。
HTTP メッソードの方は特に決まってるので、Read (Get), Create (Post), Update (Put または Patch), Delete (Delete)特に問題が起きてませんでした。まぁ、たまに Read を Post メッソードを使う API もありますけど。(GET には HTTP body がルールとして使わないので、複雑なオブジェクトをバックエンドに送る時、例えば、複数検索条件とか、Post も使ったりします。)
戻り値は HTTP Response コードなので、200 OK, 201 Created, 202 Accepted とかは理解しやすいです:Get (200 OK), Post (201 Created), Put/Patch (200 OK), Delete (200 OK) 一見ですぐわかりますので、唯一考えるべきコードは 404 Not Found ですね。
私見ですが、データが見つかってない場合、404 ではなくで、空の データ body を返すべきです。なぜなら、404 には url が存在しない場合もサーバーから返すので、意味が紛れ易いです。
一般的に JSON を扱うライブラリでは空の配列や []、オブジェクト {} など空のデータに deserialize しますが、空の body の場合、null に deserialize します。それで、Front End が null かどうかチェックすればいいのです。
404 が返す場合、これは HTTP Request がエラーになったと同じ意味なので、違うルートになります。だからコードには
if (response.StatusCode == 404) {...}
みたいなコードがあっちこっち出てくるかもしれません。そうすると、全体的にエラーの扱いが難しくなります。
データはデータなので、見つからない場合は、200 OK, null body を返したら Front end もすぐわかります。
もう一つは Java, Objective-C, C# などは全て Strongly typed 言語なので、JSON を deserialize する場合、一般的に一つの Class を定義しますが、データの角度から見ると、処理に合わせて、たまに Dictionary<string, object> にしたほうがやりやすい場合もあります。
例えば、JSON オブジェクトの中に、どのプロパティの値が null かをチェックする場合、Reflection を使うより、直接 Key-Value pair にしたらい、Iteration メッソードを使えば、速いし、その後の処理も楽になるはずです。
それでは。ここまで。
HTTP メッソードの方は特に決まってるので、Read (Get), Create (Post), Update (Put または Patch), Delete (Delete)特に問題が起きてませんでした。まぁ、たまに Read を Post メッソードを使う API もありますけど。(GET には HTTP body がルールとして使わないので、複雑なオブジェクトをバックエンドに送る時、例えば、複数検索条件とか、Post も使ったりします。)
戻り値は HTTP Response コードなので、200 OK, 201 Created, 202 Accepted とかは理解しやすいです:Get (200 OK), Post (201 Created), Put/Patch (200 OK), Delete (200 OK) 一見ですぐわかりますので、唯一考えるべきコードは 404 Not Found ですね。
私見ですが、データが見つかってない場合、404 ではなくで、空の データ body を返すべきです。なぜなら、404 には url が存在しない場合もサーバーから返すので、意味が紛れ易いです。
一般的に JSON を扱うライブラリでは空の配列や []、オブジェクト {} など空のデータに deserialize しますが、空の body の場合、null に deserialize します。それで、Front End が null かどうかチェックすればいいのです。
404 が返す場合、これは HTTP Request がエラーになったと同じ意味なので、違うルートになります。だからコードには
if (response.StatusCode == 404) {...}
みたいなコードがあっちこっち出てくるかもしれません。そうすると、全体的にエラーの扱いが難しくなります。
データはデータなので、見つからない場合は、200 OK, null body を返したら Front end もすぐわかります。
もう一つは Java, Objective-C, C# などは全て Strongly typed 言語なので、JSON を deserialize する場合、一般的に一つの Class を定義しますが、データの角度から見ると、処理に合わせて、たまに Dictionary<string, object> にしたほうがやりやすい場合もあります。
例えば、JSON オブジェクトの中に、どのプロパティの値が null かをチェックする場合、Reflection を使うより、直接 Key-Value pair にしたらい、Iteration メッソードを使えば、速いし、その後の処理も楽になるはずです。
それでは。ここまで。
2015年6月14日日曜日
祝 Polymer が 1.0 になりました
先日、つい Polymer JS が Product Ready (1.0) になりました。
https://www.polymer-project.org/1.0/
これは Web の Future と言って、なかり使いやすいです。
また、将来 AngularJS 2.0 ではシムレスに Polymer の要素を Directive と使えることができます。
PS: React.js はどう見ても、FaceBook など表示に重点をおいたサイトでは使いやすいかもしれませんが、Interactive の重いアプリではやはり AngularJS のほうがいいと思います。
後日また。
https://www.polymer-project.org/1.0/
これは Web の Future と言って、なかり使いやすいです。
また、将来 AngularJS 2.0 ではシムレスに Polymer の要素を Directive と使えることができます。
PS: React.js はどう見ても、FaceBook など表示に重点をおいたサイトでは使いやすいかもしれませんが、Interactive の重いアプリではやはり AngularJS のほうがいいと思います。
後日また。
なぜ RESTful API になったのか
おととい、チームの iOS Dev といろいろディスカッションしました。彼はまだ古い API のイメージ持っておらず、なんでもサーバー側でやると考えているようです。それで、現在の API は iOS だけではなく、Android, Web などいろんなチャンネルで共通で使う物だと、RESTful API だから、リソースを操作すると考えようといろいろ話しましたが、まだまだ受け入れてなかったそうです。
以前、3 年前ぐらいまで、iOS デバイスなど、JavaScript の性能がボットルネックだった時代では、サーバー側で計算したり、ソートするなどをやらなければならなかった。当時の Front End はそれほど遅くなかったと言っても、パフォーマンスにいろいろ真剣に取り組まないと、すぐ遅いと感じてしまいました。それで、自分たちのラブラリを作ったり、速く見せるため、ユーザーの動作を予測して、先にデータをロードするなど、工夫していました。
今 RESTful API になってから、抽象したデータなどをリソースと考えて、HTTP Method をマップして、CRUD -> Get, Post, Put (Patch), Delete を使って、Front end から直接操作できるようなイマージにしないといけないと思います。だから、API はデータを提供するだけ、データの操作はデバイスか Web Site で処理します。
前では URI や Controller の名前は RegisterDevice など、動詞+名詞でしたが、RESTful API になると/devices と名詞のみなりました。それで、HTTP Get で全部のデバイスを取得したり、 HTTP Post でデバイスを作ったりします。
GET /devices?pageNo=0&pageSize=20 -> 全部のデバイスの配列を取得
GET /devices/{deviceId} -> 一つのデバイスを取得
POST /devices -> デバイスを作る。データは HTTP Request Body から
PATCH /devices/{deviceId} -> デバイスを更新
Delete /devices/{deviceId} -> デバイスを削除
また戻りますが、Front End は一回要求するデータはそれほど多くないので、ソートも時間のかかる処理ではなくなりました。Http Request の時間はまだ考えなければなりませんが。
結論としては、もう新しい時代ですので、表示ロジックを Front End であるべきです。
それでは。
2015年5月31日日曜日
Task.Run と Autofac データベース Connection 問題から、サーバー側マルチスレッドの検討
今開発しているシステムは HTTP を使って、RESTful API です。Front end は iOS から、Android、WebSite 全部サポートしています。デバイスの 3G 回線でも、できるだけ速くロードするために、いろいろ工夫しました。例えば、一つ目のレスポンスに各リソースをリクエストする URL を入れて、実際の作成は後回しして、マルチスレッドを使います。さらに、Task.Run を使って、できるだけ時間のかかる処理を別のスレッドで行うようにします。一方、Oracle DB Connection などは Autofac を使って、 DI の .InstancePerRequest() で各スレッドに配っています。そうすると、Task.Run は Thread Pool に新しいスレッドを申請してので、そのスレッドでは前の Request のスレッドのリソースが使えなくなりました。。。"Invalid operation on a closed object" みたいなエラーが発生したりしています。毎回ではないですが、かなりの確率で発生しています。
解決の方法としては、Task.Run を使ってるスレッドの中に、自分で Autofac の LifetimeScope コントロールすることです。 まず、LifetimeScope の Provider を作って、RequestLifetimeScopeTag を ILifetimeScope の作成関数に設定することで、この ILifetimeScope は Request Scope として指定できます。ただ、自分で ILifetimeScope を作ったから、Scope の Dispose() 関数を自分で呼び出す必要になります。後日まだどうするかのコードを貼り付けます。
ここでまず話したいことは Task.Run を使う場合、スレッドの切り替え処理もありますので、一般的に 50 ms 以下のタスクでは別スレッドを使う必要がないのです。
Task.Run は Back End でファイルを書く場合や、HttpClient を使って、他のスステムに Http Request を発行する場合使ったほうがいいです。一般的な DB アクセスには速度がかなり早いので、20ms ぐらいと言われているので、必要がないと思われています。
もし Loop を使って、DB 更新を行う場合や、複数のテーブルを更新するが更新結果は Front end に返すする必要がない場合、できるだけ小回りにして、複数回で更新したほうがいいです。この処理は Task.Run を使うより、Hangfire などの Background タスク Runner を使ったほうがいいです。Hangfire は DB を使っているので、Retry 処理もあるし、Task.Run より安全です。
Front end から見ると、Http API を呼ぶとき、レスポンスが戻ってきたら、 Callback 関数が呼ばれるので、一回の Http Request より、複数の Request を発行して、各 Callback 関数を呼び出して、UI をアップデートしたほうが速いです。Http Request 自体がマルチスレッドでサーバー側で処理するので、それを最大限に使わないと。
それでは。
解決の方法としては、Task.Run を使ってるスレッドの中に、自分で Autofac の LifetimeScope コントロールすることです。 まず、LifetimeScope の Provider を作って、RequestLifetimeScopeTag を ILifetimeScope の作成関数に設定することで、この ILifetimeScope は Request Scope として指定できます。ただ、自分で ILifetimeScope を作ったから、Scope の Dispose() 関数を自分で呼び出す必要になります。後日まだどうするかのコードを貼り付けます。
ここでまず話したいことは Task.Run を使う場合、スレッドの切り替え処理もありますので、一般的に 50 ms 以下のタスクでは別スレッドを使う必要がないのです。
Task.Run は Back End でファイルを書く場合や、HttpClient を使って、他のスステムに Http Request を発行する場合使ったほうがいいです。一般的な DB アクセスには速度がかなり早いので、20ms ぐらいと言われているので、必要がないと思われています。
もし Loop を使って、DB 更新を行う場合や、複数のテーブルを更新するが更新結果は Front end に返すする必要がない場合、できるだけ小回りにして、複数回で更新したほうがいいです。この処理は Task.Run を使うより、Hangfire などの Background タスク Runner を使ったほうがいいです。Hangfire は DB を使っているので、Retry 処理もあるし、Task.Run より安全です。
Front end から見ると、Http API を呼ぶとき、レスポンスが戻ってきたら、 Callback 関数が呼ばれるので、一回の Http Request より、複数の Request を発行して、各 Callback 関数を呼び出して、UI をアップデートしたほうが速いです。Http Request 自体がマルチスレッドでサーバー側で処理するので、それを最大限に使わないと。
それでは。
2015年5月16日土曜日
iOS ユニバーサルデザイン実践:イメージのセンター揃い
この Sprint では、チームの iOS Dev が休暇で一ヶ月ほど離れることになりました。あまり Native サイドのコードを触りたくないですが、急いで実現したい機能があったので、一週間ほど Objective-C を使って、 開発をしました。
まだ iOS の開発では Nib をベースにしていますが、xib フィアルの代わりに StoryBoard が使われるようになりました。さらに、違うサイズのデバイスを対応するために、ユニバーサルデザインという概念が導入されました。これは前と違って、 絶対位置を指定するより、Constraint を使って、相対位置とサイズを指定することで、大きい iPhone 6 plus から、細長い iPhone 5 まで、全てのスクリーンサイズを対応できる layout nib になります。
さらに、Segue という概念が導入されて、前のように ViewController を push するコードより、もっと具体化になるものです。Ctrl を押しながら、ドラッグして、次画面はどこに遷移するかを指定します。これも面白いです。
今回の機能は幾つかのイメージをスクリーンの真ん中に表示することです。前なら、イメージビューをプログラムで作成して、addSubView を読んで、画面に追加します。そのあと、Frame を取得して、計算後、位置を指定します。少しは面倒くさいデスけど。
ただ、ユニバーサルデザインでは、これは変なコードになるので、どうするかを少し調べたら、一番いい方法が見つかりました。
具体的に、parent view を作って、centre align の Constraint を指定します。同時にこの Constraint をoutlet で view に追加します。Constraint の Constant などのパラメーターが取得できるようになります。
次、イメージを parent に追加したら、parent view の width を取得して、先ほどの centre constraint に設定します。これで、どうなスクリーンサイズでも、parent view がセンターになります。
Constraint は iOS が各ビューの位置や、サイズを決めるために使ったものなので、さらに面白い使い方がありますね。さらに、こちらの値もアニメーションで使えるので、前のように origin.y を使ったりすることなくても、 view を動かしたりすることもできます。
それでは。
まだ iOS の開発では Nib をベースにしていますが、xib フィアルの代わりに StoryBoard が使われるようになりました。さらに、違うサイズのデバイスを対応するために、ユニバーサルデザインという概念が導入されました。これは前と違って、 絶対位置を指定するより、Constraint を使って、相対位置とサイズを指定することで、大きい iPhone 6 plus から、細長い iPhone 5 まで、全てのスクリーンサイズを対応できる layout nib になります。
さらに、Segue という概念が導入されて、前のように ViewController を push するコードより、もっと具体化になるものです。Ctrl を押しながら、ドラッグして、次画面はどこに遷移するかを指定します。これも面白いです。
今回の機能は幾つかのイメージをスクリーンの真ん中に表示することです。前なら、イメージビューをプログラムで作成して、addSubView を読んで、画面に追加します。そのあと、Frame を取得して、計算後、位置を指定します。少しは面倒くさいデスけど。
ただ、ユニバーサルデザインでは、これは変なコードになるので、どうするかを少し調べたら、一番いい方法が見つかりました。
具体的に、parent view を作って、centre align の Constraint を指定します。同時にこの Constraint をoutlet で view に追加します。Constraint の Constant などのパラメーターが取得できるようになります。
次、イメージを parent に追加したら、parent view の width を取得して、先ほどの centre constraint に設定します。これで、どうなスクリーンサイズでも、parent view がセンターになります。
Constraint は iOS が各ビューの位置や、サイズを決めるために使ったものなので、さらに面白い使い方がありますね。さらに、こちらの値もアニメーションで使えるので、前のように origin.y を使ったりすることなくても、 view を動かしたりすることもできます。
それでは。
登録:
投稿 (Atom)