Code

2015年3月29日日曜日

モバイル Click イベント遅延

 今週、開発したプロジェクトのリリースがありました。その中の一つの改善ポイントはモバイルでの Click を早くすることです。モバイルなら、Touch イベントが追加されて、指をタッチパネルに触れた瞬間 TouchStart が発生します。そのあと、 TouchMove と TouchEnd, 次に Mouse から継承された MouseMove などが発生して、さらに、そのあと Click が発生します。主に、ダブルタッチを検知するために Click を遅らせたことです。一般的にこの遅延は 300 milliseconds と言われています。自分で試したところ、320-350 ぐらいでした。
 これを解決するためには、TouchEnd の後に、すぐ自分で Click イベントをトリッガーすればいいです。ただし、そのあとシステムの Click を抑制する必要があります。これをプロダクトで使えるライブラリは幾つかあります。今回ちょっと修正して、使ったのは fastclick です。基本的には機能が十分ですが、少しコードを参考にして、うちのサイトにあった軽量のライブラリを作りました。
 実際その 300 milliseconds を感じるサンプルも提供されています。
http://ftlabs.github.io/fastclick/examples/layer.html

 Android Chrome ブラウザーの一部がすでに改良されて、viewport を探知したら、Click イベントは早めにトリッガーする仕組みがすでにありましたので、fastclick ではそれをチェックして、もしすでにあったら、何もしないことになります。
 iOS で開くと、改良版とnative の click を使ったバージョンの区別がすぐわかります。ぜひ上記のリンクを iPhone などで開いて、クリックしてみてください。
 他には hammer.js と polymer gesture があります。ploymer gesture は ploymer のライブラリですが、基本的に stand along で使えるものです。
 
 将来 Windows Phone がもう少し普及したら、Xmarine や HTML5 Web App がさらに有利になりますので、Native なみの User Experience を実現するには、この遅延をなくすことは大事です。
 それでは。

2015年3月11日水曜日

ASP.NET Lib Practice

 最近、つい完全に Back End 開発者になりました。毎日 C# コードだけを書いて、なんだか JavaScript が使い易いなと思いました。同じ機能だったら、JavaScript のほうが少ない行数でできるはずです。将来は Node.js かな?でも、Strongly Typed 言語はやはり錯誤が少なくなります。ちょっと面倒くさいですけど。
 最近面白そうな ASP.NET のライブラリをリストしよう(まぁ、幾つかの機能は Java なら Spring だけで全部できてしまいますけど。。。):

 まず、Hangfire です。これは ASP.NET MVC と並行して、Background でタスクを実行するライブラリです。例えば、ユーザーが登録したら、email を出すと。現在一般的には1日終わる時点で、バッチタスクで新規登録したユーザーにメールを出します。Hangfire には fire-forget Job Queue がありますので、しかも別スレッドで実行してます。Controller 関数の最後に BackgroudJob.Enqueue を実行すれば、関数がすぐ返しますが、Email が別 job で送られます。しかも、遅延とか循環 job も作れますので、使い易いです。まぁ、個人的には Redis を使う意味があまりないと思うので、フリーバーションで十分だと思います。

 次、Autofac です。DI Container なら、Ninject とか Unity とかもありますが、Autofac の機能とSyntax は使い易いと思います。ILifeTimeScope も inject できますので、Life time scope を使いたいとき、または使ったほうがいい時、すぐ使えるので。例えば、DBContext は Thread Safe ではないため、一つのスレッドに一つ定義したほうがいいでしょう。MVC になると、一つの Request に合わせて、一つの DBContext を定義するなら、.AsPerRequest() 関数が提供されてますので、すぐできてしまいます。

 あと、Coypu です。これは Protractor や、Capybara みたいに、Selenium Server を使って、自動テストを C# コードで実現するライブラリです。個人的には AngularJS の Protractor のほうが AngularJS にあってるので、でも C# でテストケースをかけるなら、結構な人数の Backend 開発者も End 2 End テストができます。

 他に CacheCow 自動的に ETag を追加して、in memery cache のライブラリです。CacheCow-Server と HttpClient 対象の CacheCow-Client があります。

 Unit test 用の FluentAssertions, Object 属性をマップする Auto Mapper, OR Map の Dapper.NET、Validation 用の FluentValidation, Moq 以外 NSubstitute なども使い易いです。次のプロジェクトにいろいろ使ってみよう。

 でも、こちらのライブラリは、SignalR と Socket.io 比べるように、やっぱり JavaScript のほうが面白いな〜

 それでは。

2015年2月28日土曜日

URL absolute path and relative path

 昨日 AngularJS の $http を使って、AJAX でデータをロードするウェブページをデプロイしたら、ページロードが失敗して、web inspector で見てみたら、xxxx/xxxx url がアクセスできないエラーでした。
 実際見てみたら、別に $location などは使ってないし、なんでロードが失敗しただろうと思って、少し調べてみました。それで、$http を呼ぶとき、"/xxxxx" ような URL を使っていました。これは root の後ろにつく absolute path になるので、ウェブページはサーバーの一フォルダに置いたので、当然アクセスできませんね。
 <a> タグの href 属性と同じように、URL を使うところもし "/xxxxx" で始まると、同じドメインのリソースになります。例えば、ウェブページの url は http://www.abc.com 場合、<a href="/def"></a> をクリックすると http://www.abc.com/def になります。これは絶対パスと言います。
 もし <a href="def"></a> の場合、もしウェブページは前と同じなら http://www.abc.com/def になりますが、もしウェブページが http://www.abc.com/pages にある場合、a タグが http://www.abc.com/pages/def の方に飛びます。これは相対パスです。
 基本的には前に "/" があるかどうかで全て分けます。相対バスの場合、単純に "def" を指定するか、"../def" のようにカレントウェブページをベースに、親フォルダの def に指すような書き方があります。
 もし static ファイルとウェブページが同じドメインにある場合、良く script タグの src を ../../Scripts/js/jQuery.js を指定したりしました。(今はロードスピードを早くするために、すべての static ファイル - images, css, js - を別ドメインに置いてます。)
 まぁ、個人的にはあまり絶対パスを使わないほうがいいと思っています。それを使うと、どこに行くかちょっとややこしくなります。もし使いたい場合、全部の http url を書いた方がいいと思います。場合にもよりますが。

 ちなみに、http を書かなくて、 //www.abc.com/def の場合、アクセスするウェブページの URL から protocol をとって、アクセスします。例えば、ウェブページが https を使ってる場合、https://www.abc.com/def になります。

 今 RESTful API を書いてますので、タグの src とか href とかとあまり関係ないが、パスが http cache とも関係があって、気をつけないといけないですね。今は CacheCow を使って、ETag を自動的に生成するライブラリを使ってますけど。後日また詳細を追加します。C# の HttpClient とか。

 今日はここまで。それでは。

2015年2月22日日曜日

C# ASP.NET Web RESTful API と Front End

 最近、仕事が Back End の方にシフトしました。以前も C# ASP.NET を使ってましたが、あまり印象が良くなかった。ただ、今回 MVC4 を使ってて、なんかコンセプトなどは Ruby on Rails に似てるなと思いました。でもやはり JavaScript の方が使い易いです。
 今作ってるのは UI いわゆる View のない API のみになります。すべてのリソースを操作できる HTTP Method を使って、RESTful です。ASP.NET Web API を使うと、結構簡単にできます。しかも Autofac を使って DI も実現できるし、あまり他の言語のフレームワークと変わらないなと思いました。
 そうすると Front End はもう最初からデータをロードするではなくて、スタティックのリソースだけロードすることになります。ページが早くロードできる利点もあるし、そのあと API を呼び出す事で、どのように表示するかも簡単に変更できます。
 さらに、Task<IHttpActionResult> の戻り値のようにマルチスレッドのコントローラーもサポートしているので、Node.js みたいに他のリソースを要求して、処理が終わったら、HttpResponseMessage などを返すようないわゆる Event Driven のスタイルもできます。このスレッドは ApplicationPool ではなく、他の pool を使うので、いつでも Request が受け付けるようになります。
 あと、NSubstitute を使ったり、Moq を使うことで、Unit Test も簡単にかけるから、全体的にいい感じです。
 
 今回もプロジェクト全体が Mobile First を利用するので、まず iOS と Android Smartphone を対象に、リリースする予定です。今までは、ほとんど Hybrid の App を作ってきたので、今回もそれになりそうですね。
 
 それでは。

2015年2月10日火曜日

AngularJS パフォーマンスは良くない?ー>いいえ、使い方次第です。

 アップデート 2016/05/01:AngularJS 1.0 に比べて、React.js のほうが良いです。AngularJS の bi-direction binding、ng-repeat などは使い易いですが、DOM 操作が多くて、重いです。React.js も同じ機能が簡単に作れます。さらに、AngularJS 1.0 の Learning Curve が高いから、習うにはなかなか時間がかかります。React.js を使うと、どんどん Component が作れて、ますます開発効率が上がります。

 追加 2016/03/07:最近、React.js を使うたびに、AngularJS は難しいなと感じ始めています。1.0 では概念が多くてなかなか使いにくいですね。React.js の場合、概念も簡単だし、Flux を使うと、アプリの構造はかなり簡単になります。また速いです。まぁ、速くするためには、shouldComponentUpdate 関数を細かく実装すればいいので、はっきりしています。今後続けて React.js を使おうと思います。新規プロジェクトの場合、AngularJS 2.0 を待ったほうがいいです。でも、古いバージョンのブラウザをサポートするためには、React.js のうほうがよさそうです。時間があれば、また http://aurelia.io/ を見てみようかと。Polymer はどうやら、遅いようなきがしています。。。後日、ちゃんと勉強してみよう。

 最近、隣のグループは react.js に転向したので、再び AngularJS のパフォーマンス問題が提起されました。実際はどうですかね。。。
 まぁ、個人的な感じでは、JavaScript 根本的にパフォーマンスが良くないです。AngularJS は良く重いと言われてます。特に Dirty Check の実行サイクルが考えば考えるほど重いと思われています。でも、どんなフレームワークでも、react.js、ember.js でも、そういう長いループが存在しています。だから、Dirty Check はそんなに大きいな問題でもないと思います。
 問題は利用者側にあると思います。なぜなら、たぶん結構な数の開発者は $timeout や, $http の中に $rootscope.$apply 関数が呼ばれてると知らないです。それで、無意味に $timeout を呼んだり、自分でその中に $apply を使ったりしています。そうすると、AngularJS は2回 Dirty Check をやるので、重いですね。
 つまり、フレームワークとして、AngularJS はあまり複雑で、なかなか全部理解するには時間がかかります。そのあと、チューニングとかもしないから、問題を発見して、解決するプロセスが欠けてます。
 じゃ、どうしたら AngularJS のパフォーマンスが向上できますかね?
 まず、$apply 関数を理解しましょう。$apply 関数は $digest 関数を読んで、もしエラーとか、Exception が発生したら、ちゃんとエラースタックをリストできます。(中に try-catch があるので)。$digest  は登録した expression を実行して、過去の値と現在の値を比較して、変更があったら、変更の Handler 関数を呼びます。Handler 関数の中にもし何か値変更があったら、また $digest が実行されます、変更がないまで、実行し続けます。それで、$digest が10回まで繰り返し呼ばれます。10回以上の場合、Exception が Throw されます。
 それで、もし登録した expression の数が最小限に抑えるなら、そのサイクルが短くなります。AngularJS 1.3 から {{::express}} が導入されました。もし expression が最初の一回のみ値を設定する必要があるなら、:: で一回のみ binding されます。これも bind-once という関数があります。また bindonce という別のライブラリもあります。
 あと、すべての HTML 要素を ng-app 範囲にする必要がないので、例えば ng-non-bindable を使ったりして、directive の parse 範囲を小さくすることができます。以前も書いたように、jQuery UI を使うと、かなりの量の HTML 要素が作られます。それを parse するあまり必要ないし、"IE FIX" コメントも追加されますので、たまに Widget を壊します。だから、必要のない部分はもう non-bind して、apply directive 過程を止めます。
 次、1ページはすべて AngularJS の ng-app 範囲にすると、かなりの expression 量が増えますので、controller を親子にしないで、独立のスコープなら、もうそのスコープの $digest 関数を呼ぶとか、Dirty Check の量を減らせます。
 
 まぁ、よほど大きい web app じゃない限り、AngularJS のパフォーマンスは悪いと言えないと思います。すべて使い方次第ですね。
 どんなフレームワークを使うと、必ず overhead が発生しますので、良くデザインして、必要な部分と必要ない部分をちゃんと分けて、パフォーマンスは良くなります。

 #余談ですが、jQuery のパフォーマンスはかなり悪いです。通常の Vanilla JS を使うと、同じ関数が jsperf.com でテストすると、なん百倍の差が出ます。なぜなら、ライブラリだから、エラーチェックや、browser の違いを綺麗にカバしたいからです。以前 iOS の WebView も jQuery を使うと重く感じましたので、jQuery Lite を作って、パフォーマンス向上できました。使い方次第ですね。

2015年1月25日日曜日

RESTful API のデザイン

 先日から、新しいプロジェクトが始まりました。いろいろデザインとか、ポソナーとか紹介されて、面白そうです。今回は旧システムの改造も、 UI の改善も、モバイルファーストでする予定です。
 バックエンドは完全に書き換えるではなくて、API を追加して、フロントエンドをサポートする形になります。だいぶのロジックはフロントエンドでやる予定です。それで、フロントエンドもっと自由にデータを操作できるのように、データも RESTful API に合うように、少し改造する予定です。
 RESTful API はリソースの C(reate)R(ead)U(pdate)D(elete) を Post, Get, Put, Delete HTTP Request にマップする技術で、今は結構使われています。MongoDB なども RESTful API を提供するモジュールもあったり、CouchDB は完全に内部サポートしています。Oracle の最近の Non-SQL DB もサポートしています。
 実際作るとき、例えば、ツイターのフォロー関係も一つのリソースと考えていいです。メンバーが 登録される後、他の人をフォローすると、このような関係を DB に入れる時、実体はないけどれ、 実存しています。
 今は AJAX を使って、HTTP の Method を指定することで、Delete など直接サーバーに送ることができます。もし、JavaScript が使えない場合、現在のフレームワークは Hidden フィールドを使って、そのままサーバーで、API にマップすることもできます。

 来週から、もう完全に API チームに配属されますので、しばらくは JavaScript 触れないが、最近出てくる新しいものがあまりないし、AngularJS 2.0 も開発中ですので、ちょっと待ちましょう。:)

それでは。

2014年12月31日水曜日

擬似要素 (pseudo element) の取得

 IE 8 から、擬似要素がサポートされて、現在すべてのブラウザーがサポートされるようになりました。:before や, :after を使えば、DOM Tree は時に綺麗になることがあります。例えば、アイコンをある要素の前に挿入した場合、通常 <i> 要素を入れるか、background-image を使って、padding を追加する方法がありますが、擬似要素の :before の content に url(xxxx) を入れると、background-image と同じ効果になります。そうすると、余計なことをしなくて、単純にそのアイコンを操作することができます。
 昨日、サイトに :before 要素を javascript で取得して、操作しようとのケースがありました。擬似要素をどのように javascript で取得するかを調べてみました。メモしておきます。
    window.getComputedStyle(element, ':before')
 content attribute を取得する場合、上記で取得したスタイルの後ろに .content を追加すれば、取得できます。
 また擬似要素の content に複数文字列を表示したい場合、単純に
  el:before {
        content: "Num" counter(item) "."
    }
 のようにリストすればいいです。

 CSS にこのような擬似要素を使えば、いろんな面白い効果ができます。例えば:
 CSS icons
 また、今流行っている font graphic を使えば、例えば、
 Font Awesome
 このように、フォントを使えば、font-size を使えば、大きさも調整できるし、Retina の hi-res のスクリーンも難なく対応できます。SVG より、こっちのほうが使い易いと思います。
 それでは。