2018年3月18日日曜日

グルグル回転している長方形(Rectangle)と線(Ray)の当たり判定

3Dで回転しているキューブとRayの当たり判定の背後にある数式がいまいちよく分からなかったのでJavaScriptのCanvasを使って図解してみた。2Dも3Dもテストする軸(Axis)の数が変わるだけで内容は一緒。コードは以下より取得してもらいたい。
JSFiddle
GitHub(上に同じ)

数式の背後にある考えは以下。
Ray Box Intersection

以下図解。
右下のRay OriginがRayの起点になっている。directionでRayの方向を指定している。
const rayCast = new Ray(origin=new Vector(400, 400), direction=new Vector(-0.8, convertYUp(1)));

左上のオレンジと黄色の線で囲われている領域がくるくる回転しているRectangleとなる。
const obb = new RotatingRectangle(pos=new Vector(150, 200), size=new Vector(80, 50));

右下のRay Originから左上のRectangleに伸びている線(Vector)はRayとRectangleの距離を算出するためのものなので、投げかけているRayとは別物なので注意してほしい。
const vectorFromOriginOfRayToCenterOfRect = obb.pos.subtract(rayCast.origin);

当たっているとき(左下に「YES!」と出る)


当たっていないとき(左下に「NO Intersection」と出る)


この数式の肝はSlab(オレンジと黄色の線)とRayがいつ(Time)交わるかなので、Timeを算出しないといけない。Timeを求める式は以下。
Time = (Axis上に投影されたRay OriginとRectangle間の距離 +/- Rectangleのサイズ) / Axis上に投影されたRay Directionの長さ
const t1 = (lengthBetweenOriginOfRayAndCenterOfRectProjectedOnXAxis + obb.size.x) / lengthOfDirectionOfRayProjectedOnXAxis;
const t2 = (lengthBetweenOriginOfRayAndCenterOfRectProjectedOnXAxis - obb.size.x) / lengthOfDirectionOfRayProjectedOnXAxis;
const t3 = (lengthBetweenOriginOfRayAndCenterOfRectProjectedOnYAxis + obb.size.y) / lengthOfDirectionOfRayProjectedOnYAxis;
const t4 = (lengthBetweenOriginOfRayAndCenterOfRectProjectedOnYAxis - obb.size.y) / lengthOfDirectionOfRayProjectedOnYAxis;

Timeを求める元々の式は以下。
+/- Rectangleのサイズ = Axis上に投影されたRay OriginとRectangle間の距離 + Time * Axis上に投影されたRay Directionの長さ
Slabの位置を求める式からTimeを求める式に変換すれば前述の式になる。

Dot Product
投影されたほにゃららの長さを求めるにはDot Productを使用すればよい。


~まとめ~
同一軸上に投影すれば後は単純な長さの比較になるのでTimeが求まると理解するまで悶々と苦しんだけど、今はスッキリ。こんな投げやりな解説で伝わるかははなはだ心もとないけれど、誰かの理解の一助になれば幸い。分からないことありましたらコメントください。

2018年2月18日日曜日

ホームページを開設するには 前段

引き続き相談シリーズで行きます。相談シリーズの概要は以下をご参照ください。


今回から数回に分けて、巷にはあふれかえっていますが実際に自分でやるにはなかなか敷居の高いホームページの開設について説明していきたいと思います。

今回は前段としてなんのためにホームページを開設するのか、ホームページを開設することによって何が得られるのかという利点の面と、ホームページ開設につきまとう難点の面を説明します。

と言いますのも、後述する難点の面と重複するのですが、ホームページはしっかりしたものを作ろうとするとお金も時間もかかりますので、ホームページでなくても良いのであればなんらかの代替手段、たとえばFacebookであったり、Twitterであったり、食べログなどを利用するほうが格段に効果的だと考えられます。そのためにもホームページの価値を利点難点含めて正しく理解していただけたらと思います。

ホームページ開設によって得られる利点

ホームページの開設によって得られる利点としては以下の2点があげられます。
  • 情報発信が可能
  • イメージの確立

情報発信が可能

ホームページ開設による最大の利点は情報の発信をいつでも自由に、またどのような形でも表現できることにあります。インターネットが世間一般に広がる以前(ブロードバンドのインターネット環境が当たり前になったあたりで情報発信ツールとしてのホームページも様変わりし始めたので、ここでは2000年に入る前ぐらいでしょうか)でしたら広告という形でテレビや、新聞、雑誌に載せるかチラシを配る、または書籍を出版することぐらいでしか広く情報発信は行えませんでしたが、今やホームページさえあれば誰に気兼ねすることなく自由な形で世界に向けて情報発信が可能になりました。

飲食店であれば営業時間はもちろん、メニューやおすすめの品など、工務店であれば施工事例やおすすめリフォーム特集など、とにかく自分の望む情報を発信可能なのです。

さらにその情報の表現の仕方には制限がありません。

おすすめのメニューに画像をつけて理解の助けにしても良いですし、逆に文字だけにして硬派な印象にしてみたり、動画をつけて詳細に解説してみたり、と何をしても良いのです。

インターネット以前の情報発信と比較するために広告を例にとると、テレビCMであれば15秒なり30秒の枠を購入しその時間内で視聴者に情報を伝えることが求められました。雑誌であれば一枚のページ、または見開きページなどの枠組み、新聞であれば一面広告や、紙面の一部などの枠組み、とこのようにすでに決められた枠内での表現しか行えませんでした。

しかしホームページであればそのような制限がなく、あなたの望む100%の形で情報発信可能なのです。

イメージの確立

ここでいうイメージとはあなたの顧客があなたの発する情報・商品に対して抱くイメージです。ホームページであれば情報の表現方法を自由に決められますし24時間公開されていますので、イメージを確立するのにとても有用です。

イメージを確立する一例をあげてみましょう。ここではホームページではなく実店舗を例とします。あなたは中華料理屋を営みたいとします。その中華料理屋の店構えを誰が見ても「あ、中華料理屋がある」と一目瞭然で認識させたいならば、どうされますか?私であれば店構えの基調色を赤にし、龍をあしらった文様を端々につけるでしょうか。加えて金字で何かしらの漢字がのれんに書いてあれば遠目から見ても中華料理屋と簡単に認識されるでしょう。ユニークでもなんでもありませんが、これで中華料理屋があるという主張したいことが人に伝わりやすくなりました

では女性向けのファッションサイトを作る場合はどうでしょうか。ファッションを扱うので女性モデルの切り抜き画像を多用してみましょう。そのサイトがティーン向けであれば明るい色調とかわいいフォントにしてみるのも良いでしょう。そうではなく年配の女性向けであれば落ち着いた色調とシックなフォントにすると良さそうです。と、このようにターゲットに合わせた表現にすることで主張を明確にしイメージの確立を目指します。こういったことはチラシであれ雑誌の広告であれ日常的にデザインとして行われていることですが、ホームページにはさらに進んだ表現の自由があります。

雑誌、新聞、チラシであれば紙面に印刷しているので動きのない静的なものになりますが、ホームページであれば動画を流すことによって動的なものにできますし、さらにはユーザーに合わせた内容を動的に表示するといったことも可能なのです。またユーザーの操作に合わせて表示を変えたり、動きを加えたりといったインタラクティブ(双方向)な表現方法もあります。

このようにホームページ上での情報の表現方法はアイディア次第で大きな広がりを見せます。これらの特性を活かせば宣伝したいものや情報のイメージの確立はほかの媒体よりも容易に行えるのです。

ここで3例ほど2018年のホームページのトレンドを紹介しましょう。どのような表現がホームページ上で行えるか参考にしてください。Webデザイン、これからどうなる?すぐに使えるアイデア見本集58選を参照しました。

  • Happier Village Toshiba
    上下方向にスクロールすることによって表示が変わっていきます。レトロでポップな感じのデザインです。
  • Buddha Pizza
    ユニークなアイコンも目を引きますが構成がスッキリとしていてとても見やすいです。
  • Loyal Coffee
    コーヒーショップのホームページです。ホームページ上ではスペースを贅沢に使うことでゆったりした感じが演出されています。

ホームページ開設の難点

ここからはホームページを開設するにあたっての難点を説明します。
  • おしゃれなホームページを作るのは大変
  • ホームページを作っても単体での広告効果は少ない
  • 維持費がかかる

おしゃれなホームページを作るのは大変

ホームページを作るのは至極簡単です。最寄りの書店で「HTMLとCSSでホームページを作る」といった感じのタイトルの書籍から適当に一冊選び、それを見ながらポチポチと打ち込めば基本的なホームページは作成可能です。実はホームページの基本となる骨子は至極単純なのです。ただ、それとあなたが目指している「あなたの発信する情報のイメージ確立」を助けてくれるホームページはまったくもって違うものなのです。

イメージの確立を行うにはデザインのいろはを知らなければなりません。またIT全般に言えることですが、ホームページの世界も日進月歩で、前述したホームーページのトレンドで紹介されているホームページは最新技術を駆使して実現されています。

ホームページの基本は簡素なのですが、デザインしたものを最新技術を駆使してホームページに落とし込むのは非常に高度な技術が必要になります。そのため自作するにはハードルが高いですし、外注するにしてもゼロからの作成ですと数十万円の費用は必要になるかと思われます。

ただWiXテンプレートモンスターのような出来合いのホームページのテンプレートを基に作るのであれば、数万円から制作依頼を受けている会社もありますので自分のイメージと合致するものが見つかったのであればそういったものを活用するのも一つの手だとは思います。

ホームページを作っても単体での広告効果は少ない

ホームページをただ作って開設しただけではそのホームページのURLを知っている人しかアクセスできません。そのためGoogleやBingなどの検索エンジンに登録し、検索によって人が訪れるようにする必要があります。しかし、検索エンジンに登録したからと言って多くの人眼に触れるとは限りませんし、むしろほぼゼロに近いというのが実情です。

そのため検索エンジンの検索結果の上位に表示されるように対応する(世間一般ではそれをSEOと呼びます)のですが、近年は扱っている情報そのものの価値を検索エンジンが正しく認識しそれによって検索結果の並び順が決定するようになってきたので、以前のように検索エンジンを騙すような手法で検索結果の上位に表示するのは難しくなっていますし、逆にペナルティを受けて検索結果から除外されたりもするようです。そのため扱う情報の価値と一意性(ユニークさ)がとても重要になってきます。

例としてレストランをあげましょう。あなたは「ボンジョールノ」というイタリアンレストランを東京都渋谷区の渋谷駅、宮益坂周辺で経営しているとします。そのレストランのホームページをつい最近開設したとしましょう。そのホームページがどのように検索結果に表れるか見てみましょう。

ユーザーが「東京 レストラン」と検索したとします。仮に都内の飲食店、レストラン形式の店舗が2万店あったとしたら、あなたのホームページは最後尾のあたりの2万番目で表示されるのが予想されます。これは「東京 レストラン」という枠組みの中ではつい最近開設されたばかりのホームページの情報価値は非常に低いからです。

次いでユーザーが「渋谷 イタリアンレストラン」で検索したとします。渋谷は飲食店がとても多いですし、イタリアンレストランの数も多いのでここでも最後尾あたりで表示されるのが予想されます。先ほどと同様にこれは「渋谷 イタリアンレストラン」という枠組みの中での情報価値が低いからです。

次いでユーザーが「渋谷 宮益坂 イタリアンレストラン」と検索したとします。ここで初めてあなたのホームページの情報価値が高く評価されます。とても特定的な情報である「宮益坂にあるイタリアンレストラン」に合致する店舗はそこまで多くないので、つい最近開設されたばかりにも関わらずあなたのホームページは検索結果の上位に表示されることが予想されます。

最後にユーザーが「宮益坂 ボンジョールノ イタリアンレストラン」と検索したとします。ここまで特定してやっと検索結果の最上位、もしくは10件以内に表示されることが予想されます。なぜ必ずしも最上位ではないかというと、食べログなどの情報集約型のホームページ(一般的にはこのようなものはWebサイトと呼びますがこのブログ記事ではホームページ呼称で統一しましょう)の方が高く評価されることがままあるからです。

と、このようにホームページ単体の広告効果は高くはないのでホームページを開設したとしても「これで日本中から予約の連絡が来る!」というようなことは起こりえません。ホームページは任意の情報を発信できますが、情報発信可能なのと、その発信した情報が誰かに伝わることとはまったくもって違うのだということは正しく認識しておかなければなりません。

維持費がかかる

外注するのであればホームページの作成にも費用はかかりますが、ホームページを開設・公開し続けるのにも費用がかかります。サーバー費用とドメイン費用になります。

サーバー費用
ホームページを公開するには24時間稼働し続けているサーバーにホームページを設置する必要があります。グローバルIPさえあれば個人宅でもサーバーを設置、ホームページを公開することは可能ですが、電気代やPC機器の故障などを考えると下記のようなレンタルサーバーが一番現実的かと思われます。
アマゾンの方はデータの転送量などによって値段が変わるのですが、開設初期の人気のないホームページであれば最低価格で事足りるでしょうから年額120円ほどかと思われます。またさくらインターネットのほうも最低価格の設定では年額1500円ぐらいのプランがあります。

ドメイン費用
ドメインというのは先ほど出てきたグローバルIPにつく名称のようなものです。マツオソフトウェアのグローバルIPは157.7.128.94ですがドメインはmatsuo-software.comになります。IPアドレス(157.7.128.94のような数字の羅列です)を覚えるは難しいですが、yahoo.co.jpだったりamazon.co.jpを覚えるのは難しくないかと思います。ドメインというのはヒューマンフレンドリーな別称と言えます。先ほどのレストランの例でしたらbuongiorno-miyamasu.co.jpなどのドメインがふさわしいかと考えられます。

ドメインの価格はco.jpやnetなどのドメインの種類にもよるのですがおおむね年額数百円から数千円かかります。


まとめ

ホームページ公開の利点、難点を説明しました。ホームページを意味あるものにするのはなかなかに難しいということが伝わったらと思います。ただ単に情報発信場所とするのであれば、FacebookやTwitterを組み合わせれば事足りると思いますのでそちらでも良いかもしれません。飲食店などであれば食べログ、ぐるなびなどの利用を検討されるのも良いでしょう(掲載料などはよく検討されたほうが良いとは思いますが)。

しかし、イメージの確立、ひいてはブランディングまでも行うのでしたらホームページというのは非常に良い場所になりますので費用と時間、労力をかける価値はあると考えられます。

2018年2月2日金曜日

ITに関すること何でもご相談ください

先日、レストランでオーナーシェフをしている友人より「ホームページを作りたいんだけどどうしたら良いかな?」という相談を受けました。

友人曰く「ぐるなびとかでもいいんだけどちゃんとしようとするとお金結構かかるみたいなんだよね」という話でした。私も寡聞にして食べログやぐるなびの料金がどうなっているか知らなかったので色々と友人に尋ねたところ、友人も詳細は知らないらしく伝聞情報で大体の費用を推測するしかそのときはありませんでした。ただ自分でホームページを作るにしても、まずホームページを作る時点で何かしらの費用は発生する(何らかの作成サービスを利用する、または制作会社に依頼するなど)し、作成されたホームページを設置、公開し続けるために毎月いくばくかの固定費が発生すると伝えたところ、ぐるなびなどを使用せずに自分でホームページを作って宣伝するのはなかなかに難しいということが理解できたようでした。

また次のような相談を受けたこともあります。

伯母の勤めている職場で従業員の情報を管理するソフトウェアがあるそうなのですが、そのソフトウェアはかなりの年代物らしく、また保守管理していた従業員の定年退職が近くなり、代替手段を探しているという話でした。伯母の職場は従業員も少ないですし、代替手段に潤沢な費用をかけられる状況でもありませんでした。詳しい状況がわからないとなかなか効果的なアドバイスもできませんのでそのソフトウェアで何を行っているのかを詳しく聞いてみたところ、どうやら専用のソフトウェアで行う必要もなさそうな内容で、エクセルなどでも代替できそうでした。ただエクセルでは誤ってデータを削除してしまったり、意図せぬ編集なども起こりえるので単純に置き換えるのではなく自動バックアップなどの仕組みを構築したほうが良いと伝えました。伯母が私の伝えた内容を職場に持ち帰ったところ私にまた話が戻ってきまして、担当の方と詳細に話したところ初期のアドバイスとは違う形ですが誰でも保守管理できる形に移行できました。

こういった相談が友人・知人からあると再認識するのが、ITというのは今も昔も馴染みのない方々には変わらず敷居が高いのだということです。

一つ目のホームページの件などは、少しITスキルの高い方であればGoogleなどのサーチエンジンを使って情報を集めることができるでしょうし、二つ目のソフトウェアの件などもPCに詳しい方であれば同じような解決策に思い至れたかもしれません。ただ、ITスキルも乏しい、資金も潤沢ではない場合はなかなか思うような結果を得られず、困った・不便な状況を強いられていることが多いのではと推察されました。

そこで、ITに関することを何でも気軽にきける存在として私がお役に立てればなと思い立ちましてこのような場を設けることにいたしました。
  • 業務をシステム化することによって効率化を図りたいけどいくらかかるのか
  • 楽天にお店を出店したいけどやり方がわからない
  • アマゾンストアに出店するにはどうすればよいのか
  • ECサイトを作りたい
  • ホームページを公開したい
  • 保守する人員のいない小規模システムをどうすればよいか
  • スマホアプリを作りたい
などなど、上記の内容に限らずなんでも良いのでITに関することで窓口がどこか分からない方がいらしたら下記までお気軽にご連絡・ご相談いただけたらと存じます。



2017年12月19日火曜日

今年読んだ本 2017

2017年に読んで良い、またはまぁまぁ良いと思った本。順不同。ここ最近はコンピューターグラフィックスに興味が強く湧いていたので3D関連の本ばかり。洋書多数。


WebGLをいじるのにシェーダーの解説付きのサンプルが見たかったので購入。ただ「おー、すげーいいじゃん」と思う機能のほとんどがOpenGL4.0からのサポートでWebGL2.0では使えないのが多数なのでなんだかなぁと言った感じ。現状のOpenGLで何ができるかをざっと見るには良いと思う。


3Dの当たり判定を自前の計算で行えるようになる。簡潔でいて分かりやすい。物理演算とか実際にどんな風にやっているか興味のある人にはとても良いと思う。


Three.jsの機能をざっと知りたかったので購入。よくまとまっていると思う。けど、ほとんどの内容はThree.jsのサイトみたら全部分かると思う。深い内容はとくになかった。


今年読んだ本で一番。dot product, cross productのような知識がなくても一から丁寧に説明してくれるので良く分かる。個人的にすごくよかったのは本書に出てくるほとんどすべての数式について実際にはそれがどういう現象を表しているのか詳説してくれているところ。理解がはかどった。


読書途中だけど良い。全体的にわかりやすい。込み入った説明になってくると難しくなってくるけどGeometryで問題になることがよくカバーされているので知識欲が刺激される。pseudocodeもあるのでこれをもとにプログラミングするときにも一助になりそう。ただpseudocodeはかなり文章よりだけどね。


ゲーム作るときの参考になるかなと思って購入。色々な撮影テクニックが簡潔に説明されていてわかりやすいし面白い。


遠近法を勉強するのに。ざっと読んだだけだけど良い。あとは実践あるのみなんだけどその時間がなかなかとれない。

2017年12月9日土曜日

VirtualBox上のUbuntuで起動時にブラックスクリーンから進まなくなった場合の対処

久方ぶりにVirtualBox上でUbuntuを起動したところセキュリティアップデートがこんもり溜まっていたり、UbuntuのLTSが16.04まであがっていたり、またVirtualBox自体も5.2.2にあがっていたりしたので数時間かけてまとめて更新していったところ無事に本記事タイトルの状況になったのでその際の対処法を記しておく。

状況としてはVirtualBoxでUbuntuを起動してもブラックスクリーンが表示され、そのまま何も起こらない、になる。

そこで「VirtualBox Ubuntu black screen」でGoogleするとフォーラムやらで質問している結果が出るわ出るわ。みなさん、同じ状況に陥っているらしくこれは解決は早いかなと思ったところ、ほとんどの提案は何の効果もない。ただ3d accelerationを無効にすると起動できるという提案だけは効果があったけれど、Ubuntuは3d accelerationがないと玉音放送をもってしても耐えがたいほどに遅く使い物にNothing。

というわけでトライアンドエラーを盲目的に繰り返すことしばし、なんの光明も見いだせないので、こりゃログでも見るしかないかなとVirtualBoxのログを見てみたところ何やら怪しい文言を発見。
※ログの表示はVirtualBox Managerの対象のゲストOSを右クリックして「Show Log」を選べば表示できる

「OpenGL Info: Host does not support OpenGL extension(s):」

・・・、これじゃねーの?という勘に従いGoogleしたところドンピシャの質問を発見。
[Solved] 3d acceleration not working since 5.1.28 ?

上記のフォーラムによると、「OpenGL Info: Host does not support OpenGL extension(s):」ではなくもっと下の方にある「VERR_CR_PKCS7_KEY_USAGE_MISMATCH」が問題らしくそれのせいで「supR3HardenedErrorV」が発生している模様。自分のログを確認すると確かに似た内容の文言が吐かれているので勧めに従いグラボのドライバを最新に更新し、さらに管理者権限で開いたコマンドプロンプトで「sfc /scannow」を実行し、念のため再起動してからVirtualBoxからUbuntuさんを起動したところ、先ほどまで死亡遊ばされていたUbuntuさんがついに3dブーストとともに正常起動。

今回の教訓はログはすぐにチェックしろ、です。

2016年11月9日水曜日

async、await、CancellationTokenについて

職場でasync、await、CancellationTokenの実装方法についてまとめたので同じ内容をまとめておく。
※サンプルコードはWeb API 2を想定している。またDBアクセス部分はDapperを使用している。

この記事は下記リンクの要約なのでasync, awaitについての詳細は下記のリンクを参照してもらいたい。日本語翻訳されていないので英語。
Asynchronous Programming with async and await (C#)

使うべき場所
下記のような状況ではWebサーバのパフォーマンス向上が見込めるので積極的に使ったほうが良い。
  • DBでの処理(問い合わせ、実行など)
  • DB接続のオープン処理
  • ファイルIOなど
async, awaitの非同期処理で知っておくべきことは「awaitされている処理も呼び出し元のThreadと同一のThreadで処理される」ということにある。なぜならasync, awaitキーワードは呼び出されたメソッドを呼び出し元のThread上で必要に応じて適時処理するだけであり、新規にThreadを作成するわけではないからだ。
Threads(詳細説明)

つまりDBやファイルIOなどの別プロセスの結果待ちが発生する処理などでは非常に有用ではあるけれど、非同期処理になることを期待して単純に処理を二分しても実際には同一のThread上で二つの処理が適時行われるだけなので意味がないということ。ところでWebサーバのCPUリソースを多量に必要とするような処理の場合はasync, awaitとTask.Runを組み合わせると良い。Task.RunはThreadpoolへ処理を投げるのでパフォーマンス向上が見込める。

async, awaitのWeb APIサンプル
// TestController.cs
public async Task<TestDto> GetTest(int id, CancellationToken cancellationToken){ // A
    var dto = new TestDto();
    var data = TestDataFacade.GetDataAsync(id, cancellationToken);               // B
    dto.Salary = CalculateSalary();                                              // C
    dto.Data = await data;                                                       // D
    return dto;
}
  • A、リクエストのキャンセルを考慮してCancellationTokenを最終パラメータに指定する
    時間のかかる処理などはリクエストがキャンセルされた場合に処理を中止できるのが望ましいのでCancellationTokenを実装すると良い
  • B、非同期処理の開始
    AsyncのSuffixは非同期処理のネーミングコンベンションなので関数名につけるようしたほうが良い
  • C、Bが非同期処理されている間にCalculateSalaryが実行される
  • D、Bの非同期処理の結果待ち
// TestDataFacade.cs
public async Task<IEnumerable<TestItem>> GetDataAsync(int id, CancellationToken cancellationToken){
    using (var con = _connectionProvider.GetEditableConnection()){
        await con.OpenAsync(cancellationToken);                  // A
        return await con.QueryAsync<TestItem>(                   // B
            new CommandDefinition(                               // C
                "select * from Tests where id=@id", new { id }, cancellationToken: cancellationToken));
    }
}
  • A、DB接続のオープンを非同期で行う
  • B、Dapperで非同期問い合わせを行う
  • C、cancellationTokenを渡すためにCommandDefinitionが必要
async, awaitの動作解説図
下記リンク先にある解説図を見ると一連の動きが良く分かるので是非参照してもらいたい。
What Happens in an Async Method(詳細説明)

まとめ1
ここまででasync, awaitキーワードの使い方が動作原理を含めて理解できたと思う。使い方を誤らなければ簡易な記述で容易にパフォーマンス向上が見込めるので使える状況では積極的に使っていくべきだとは思うけれど、ともすると処理フローは複雑化しやすく、関連する箇所全体で非同期処理を念頭に置いた実装にしなければならないので使いどころは慎重に見極めないといけない。


非同期リクエストのクライアントからのキャンセル方法
こここらは非同期リクエストをクライアントからキャンセルする方法を解説する。
var currentXHR = $.ajax({
    url: "/api/Test/GetTest/1",
    type: "GET"
});

currentXHR.done(function (data) {
    // 取得したデータで何かする
}).fail(function (jqXHR, textStatus, errorThrown) {
    if (errorThrown === "abort") {
        alert('処理を中断しました。');
    } else {
        alert('処理中にエラーが発生しました。エラー内容:' + errorThrown);
    }
}).always(function () {
    currentXHR = null;
});

// MEMO : 非同期処理中にページ遷移した場合はリクエストをキャンセルする
$(window).unload(function() {
    if (currentXHR) {
        currentXHR.abort();
    }
});

// MEMO : 非同期処理中にキャンセルボタンを押下した場合はリクエストをキャンセルする
$('button.cancel').click(function() {
    if (currentXHR) {
        currentXHR.abort();
    }
});
ページ遷移時に非同期リクエストが処理されている場合は明示的にリクエストをabortしないとキャンセルされない。また重たい処理などを実行する場合はキャンセル処理を実装しておくと不要な処理の実行を防ぐことによってパフォーマンス向上が見込めるので(エンドユーザがレスポンスを待たずにページ遷移してしまったとき用などに)積極的にキャンセル処理は実装したほうが良いだろう。

Web API 2のバグ対応
Web API 2のバグで非同期処理中にAbortするとOperationCanceledExceptionが発生するのでそれを抑制する必要がある。下記コードをGlobal.asax.csに追加してほしい。
class CancelledTaskBugWorkaroundMessageHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
        // キャンセルされた場合はエラー内容を空っぽにして送り返す
        if (cancellationToken.IsCancellationRequested)
        {
            return new HttpResponseMessage(HttpStatusCode.InternalServerError);
        }
        return response;
    }
}

protected void Application_Start(object sender, EventArgs e) {
    GlobalConfiguration.Configure(config => {
        // ...省略...

        // abort処理で発生する例外出力を抑制するための処理
        config.MessageHandlers.Add(new CancelledTaskBugWorkaroundMessageHandler());
    });
}

まとめ2
Single Page Appなどで多量のAjaxリクエストを行っている最中にエンドユーザがページを離れてしまうとサーバサイドで行っている処理はすべて無意味になってしまうので、そのようなときのためにもキャンセル処理を組み込んでおくと良いだろう。

2016年9月15日木曜日

ユニットテストでlog4netのログを出力する方法

いまさらな内容だけど備忘録としてユニットテストでlog4netのログを出力する方法を記しておく。

static constructorで下記設定を行っておけばユニットテストの結果Windowの下にログが出力される。

[Subject("Test")]
public class TestSpec
{
        static TestSpec()
        {
                // MEMO : ユニットテストでlog4netを使用するための設定
                var consoleAppender = new log4net.Appender.ConsoleAppender { Layout = new SimpleLayout() };
                BasicConfigurator.Configure(consoleAppender);
        }

        // 以下省略
}