kazuk は null に触れてしまった

C# / .NET 系技術ネタ縛りでお送りしております

コードは伸びるよどこまでも


寒くなってきましたねー というわけで C#たんの寒さから入る流れを踏襲してみます。

っていうのもフレームワークを使ったアプリケーション開発っていうのが今回の話題。

C#たんと学ぶ/わりと硬派なソフトウェア開発講座 第1回「C#でできること」

の2ページめ、今時のアプリケーション開発に欠かせない「フレームワーク」

 

フレームワークって便利ですよねー、本当に。 LINQ とかで簡単にデータアクセスとかして簡単にアプリケーション書けちゃいますよねー。

 

アプリケーションで顧客データを参照するなら

var blackListedCustomers = from cust in db.Customers where cust.BlackListed select cust;

でブラックリスト入りしてるお客の一覧を取得できると。

んでご会計ページとかではこれを元にブラックリスト入りしてたらなんかするって訳で、こんな事になるでしょう。

var blackListedCustomers = from cust in db.Customers where cust.BlackListed select cust;
if( blackListedCustomers.Any( c=>c.UserId == session[“UserId”] ) )
{
     Mail.Send(
        new MailMessage( config.GetAdminMailAddr(), “Blacklisted customer notice “,
            string.Format( “要注意購入者情報 {0}”, blackListedCustomers.Where( c=>c.UserId==session[“UserId”] ) ) ) );
}

これはアプリケーションコードとしては非常にまっとうなんだが、いかんせん Any と Where の2回クエリが実行されるとか起こる。

まぁね、要注意人物なんてそんなに居ないだろーという訳で最初の blackListedCustomers に ToList()って書いておけば良いよね。

 

良いのよ、前提を解っていて、それに対処するって事は。でも駄目なのよ、前提を知ってるのは、「そんなに居ないだろー」って前提は少なくとも完全に駄目。

「Any とWhereで2回実行される」のが駄目ってのも前提を知ってるって事で言えば駄目、なんでっていうと「フレームワーク」が隠ぺいしている機能についての詳細だから。

むにゃむにゃあって、フレームワークを使っても結局は漏れのある抽象化にしかならないケースが多い。中を気にするのは本来は駄目な話、フレームワークは中の事を気にせずにものごとができる様に作られなきゃいけないはずなんだが、それが実現されてるなんて「夢見てんなよ」だったりする。

夢なら夢で諦めてフレームワークの中の事をちっと気にしてプログラム書いてあげるのはやぶさかではないって事で諦めよう。

 

んな訳で、先に進む。

データを取ってキャッシュしないで済ませられるのは小学生までらしいのでキャッシュする事にしよう。

ASP.NETなんでAPIとしては System.Web.Caching あたりにある物を使おう。

ここでストレージフレームワークと、Webフレームワークの境界線のあたりの不毛地帯を通る必要がある。LINQはクエリ言語であり、その実装が「ストレージアクセスフレームワーク」で隠ぺい範囲は「ストレージアクセス」なんだから「キャッシュなんて知りません」は至極当然まっとうな結果だったりするんだが、本来簡単なはずの話がどこまで複雑になるか見てみるとげっそりする。

var blackListedCustomers = from cust in db.Customers where cust.BlackListed select cust;

の一行をちゃんとキャッシュ意識して書くとこーなるってのが以下の通り。

var cache = HttpContext.Current.Cache;
string cacheKey = “BlacklistedCustomers”;
List<Customer> blackListedCustomers;
blackListedCustomers = cache.Get(cacheKey);
if( blackListedCustomers==null )
{
    blackListedCustomers = (from cust in db.Customers where cust.BlackListed select cust).ToList();
    lock( cache )
    {
        List<Customer> ready = cache.Get(cacheKey);
        if( ready ==null )
        {
            cache.Add( cacheKey,blackListedCustomers ); 
        } 
        else
        {
            blackListedCustomers = ready;
        }
    }
}

check-lock-check (check-execute-lock-check-update) はちゃんとやらずにあちこちでロックしてるとアプリケーションがガチガチとブロッキングするのでキャッシュ制御では必須ね、この辺ちゃーんと複数スレッドでのコード実行を意識できる人でないと忘れがち。

っておい、「アプリケーションプログラマはキャッシュだけでなく並行制御もちゃんと知らなきゃ駄目なのかい?」って事になるし、本来アプリケーションでやりたいと思ってる事よりこっちの方が行数があるってのも問題で、アプリケーションコードなんてのは実際にやりたい事がまばらにあるだけで8割は色々なフレームワークが「自分の範疇じゃないし、そんな事しったこっちゃねーよ」と言った事の掃溜めと言っていいぐらいだったりするのはむしろ普通な事なんだ。(LINQ to SQL 固有の CompiledQuery にするとか、Entity Framework にも固有の事象とかその辺は今回入れてないんだよ)

 

とりあえず、以下のリンクに飛んで、スクロールバーの状態だけでも見てもらえれば、クエリの実行にまつわるどれだけの事が隠ぺいされたかは解る。

.NET アプリケーションのパフォーマンスとスケーラビリティの向上 – 第 12 章 「ADO.NET パフォーマンスの向上」

昔(2005年当時)はデータアクセスにこんだけ注意事項があった、がその辺全部をLINQとクエリプロバイダの中で解決してくれる(はず!)。(実際は LINQ to SQLのクエリ実行ではここに書かれたいくつかのパフォーマンス上のtipsは実行されていない)

しかし、アプリケーション全体ではまだまだ新しい注意事項がどんどん出てきているし、キリガ無い。その上に RIAやRESTだ。

タイトルの通り。

フレームワーク?素晴らしいものかもしれんが、まだまだ夢のような話だよねって感じであります。

コメントを残す