miau's blog?

ASP.NET その2

続き。
今回はプロジェクトで目の当たりにした問題点とか。




今回 ASP.NET の経験が積めたかというと、それほどいい経験ができているわけもなく。
設計した人が ASP.NET のフレームワークを使いこなせてないらしく、色々ダメな点がありました。
プロジェクトメンバーもヘルプで一時的に入る人が多いせいで、ASP.NET に詳しい人はごく一握りだし。
私も初めそれを参考にプログラム組んでたから、かなり無駄な手間を掛けてた気がします。

そんな、失敗談たち。


■プロジェクト構成

VS.NET で開発する場合、最上位にソリューションがあって、その下にプロジェクトが複数ぶら下がるような構成になります。今回のプロジェクトでは Web アプリケーションの機能(会員登録、情報検索とか)ごとにプロジェクトが切られてました。これは、ダメです。(本来プロジェクトってのはウェブサイトに当たる概念。)

何が問題かというと、Web.config が各プロジェクトに必要になるから定数を集中管理できないし。
今回登録や個人情報の照会を行うページでは認証機能が使われていたんですが、プロジェクトが違うとセッションも別管理になるようで、各プロジェクトでログイン情報を共有できません。
後者の問題に関しては、

How to Share Session/Application State Across Different ASP.NET Web Applications

こんな方法もあるんですが、手間がかかるし結構危険だし、ということで結局使ってない気がします。
そんなわけで、なんかここでは書けないような脆弱な状態になっていたりするような・・・。


■ページ遷移

下手に Web 開発の経験がある人が作ってるもんだから、PostBack を全然使ってなかったりとか。
(ボタンクリックする度に Response.Redirect() したりとか。)
そのフレームワークを活かした造りにしないと色々勿体ないですね。

どうでもいいけど、ページの遷移はには何を使うのがいいのか、結構悩んだりもした。

@IT:連載:プログラミングASP.NET 第16回 ASP.NETにおけるページの遷移

PostBack な情報別ページにそのまま渡したい場合は Server.Transfer() がいいですよ、と。
(ASP.NET 2.0 だとそんな必要も無さそうだけど)

Clarifications on when to use Response.Redirect vs. Response.Execute/Transfer

外部サイトだったら Response.Redirect() ってのはまぁそうだろうけど。
URL を残したい場合とそうでない場合で適宜使い分けるのがいい、と。


■Validator

Validator も使わずにエラーチェックしてて、そのせいでやたらバグとか発生してたみたい。
最後のほうで入力系の画面作ったので、Validator 使ってみたんですけど・・・クライアントサイドのチェックが入るからユーザビリティも優れてるし、作るの楽だしでいいことづくめです。フレームワークをちゃんと知らないのは罪ですね。


■CSRF

小規模サイトなんで、CSRF 対策とか実質必要ないんだけど。
一応やっておこうかなとか思って、

高木浩光@自宅の日記 - クロスサイトリクエストフォージェリ(CSRF)の正しい対策方法

を眺めつつ、適当に実装したりしました。

' 遷移元での処理
If Not IsPostBack Then
' CSRF 対策用に独自の SessionID を発行
Dim tmpSession As String

tmpSession = System.Guid.NewGuid().ToString

txtTmpSession.Text = tmpSession ' hidden 項目
Session.Add("tmpSession", tmpSession) ' Session
End If

' 遷移先での処理
Dim tmpSessionA
Dim tmpSessionB

tmpSessionA = txtTmpSession.Text ' hidden 項目
tmpSessionB = Session.Item("tmpSession") ' Session

If tmpSessionA Is Nothing Or _
tmpSessionB Is Nothing Or _
tmpSessionA <> tmpSessionB Then
' ***** Error *****
Exit Sub
End If

でもよく考えたら、ちゃんと PostBack で実装されてればそんな対策必要ないことに気づいた。
無駄足。


■DB アクセスクラス

プロジェクトで DB アクセスを簡略化するためのクラスがあったんだけど、これが結構問題で。

DB アクセスを抽象化するクラスっていうのは他システムでもよく見かけるんだけど、いい設計になっているのは見たことがない。「標準的なやり方だとクラスを 2〜3 個使わないとダメだけど、このクラスを使えば SQL を渡すだけで結果を返してくれるよ」みたいなのが多い。
でもそれって結局パラメタライズドクエリが使えなくなったり、複雑なこと(今回で言うと DataSet.Relations とか)がやりにくかったりであまりいいこと無いような。

DB 接続のクラスを作るのであれば、「標準的な接続クラスを継承して ConnectionString を設定ファイルから勝手に読んでくれる」くらいの作り方にしてくれると助かる。
まぁオブジェクト指向的には、各オブジェクト(Employee クラスとか)が中で勝手に DB アクセスする、という抽象化が正しいんだろうだけど。そうすれば mock object とか使えるからテストとか楽だろうし。


■Web.config アクセスクラス

同じく Web.config からのデータ取得を行うクラスも用意されてました。

Imports System.Configuration

Hoge As String = ConfigurationSettings.AppSettings("Hoge")

と書くところを

Hoge As String = MyConfig.Hoge

みたいに書けるというもの。これは、

・柔軟な拡張(アプリケーション固有の方法権限をチェックしたり)が可能
・コード補完が利くから便利
・キー名を間違えた場合、コンパイラにチェックされるので信頼性が上がる
・たぶん mock object とかを適用することも可能

という利点はあるんだけど、

・そのクラスの仕組みを知らない人には読みにくい
・定数が増える度に、そのクラスにプロパティを追加する必要がある

という欠点もあって、ちょっと面倒だなと思ったり。プロパティ追加用のマクロとか用意しておいてくれれば良かったんだけど。

個人的な考えですが、こういう定数管理みたいな部分は言語やフレームワークで備えた機能を素直に使って欲しいところ。
というのも、例えば「ConfigurationSettings.AppSettings("Hoge") を選択して Ctrl+Shift+G を押すと、その宣言部を開いてくれる」みたいなプラグインが開発された場合。独自クラスを使っていたらこのプラグインの恩恵は受けられませんよね。
# 実際本職の方でそういう苦労を味わってたりします。
# 素直に use constant HOGE; としてれば ctags で宣言部に飛べるのに、変なクラス使ってるもんで定数の内容を調べるのがやたら大変なのですよ。

そういう抽象化クラスを使うにしても、自分で実装してしまうのではなく Patterns & Practices に載ってるようなものを使ったほうが、まだ他の人が使いやすいかなー・・・と思ったけど、それっぽいやつの評価、あんま高くないですね。

patterns & practices: Web Applications: Configuration Application Block

うーん・・・。
posted at 23:08:33 on 2005-12-17 by miau - Category: Work No Trackbacks - Permalink

TrackBack

このエントリにトラックバックはありません
現在トラックバックは受け付けていません。

Comments

No comments yet

Add Comments

現在コメントは受け付けていません。
お手数ですが、 こちら のコメント欄にでも記載していただければと思います。