自動テストのメモ
1.Actionクラスの自動テスト
(自社内フレームワークだが、位置づけはStrutsのActionと同じ)
org.springframework.mock.web.MockHttpServletRequest
org.springframework.mock.web.MockHttpServletResponse
org.springframework.mock.web.MockHttpSession
↑こいつら使ったら、なんのこっちゃない。
2.Excelにテストデータを記述する
InputStream is = new FileInputStream("エクセルのフルパス");
POIFSFileSystem fs = new POIFSFileSystem(is)
HSSFWorkbook = new HSSFWorkbook(fs)
・
・
↑あとは、シート取ってきて〜、値取ってきて〜、、、。Jakarta POI。
PRGパターン
別にロールプレイングゲームじゃないです。
Webアプリケーションの実装方式のお話。
例えば、
入力画面→確認画面→完了画面
って感じで画面遷移していったとして。
完了画面でF5を押したらどうなるか?
⇒データベースに更新しに行く処理が2回流れて欲しくない。
例えば、
POSTで画面遷移→ブラウザの戻るボタン
ってオペレーションしたらどうなるか?
⇒ページの有効期限切れってなって欲しくない。
んで、このPRGパターン。
1. ブラウザ→POST→サーバ
⇒ブラウザからサーバにPOSTでデータを送って、
サーバ側ではそのデータを元に処理をする。
2. サーバ→REDIRECT→ブラウザ
⇒サーバからは転送先のアドレスと、
302のレスポンスコード(転送だよってのを示す。404だとNot Found。500だとサーバーエラー)を返す。
3. ブラウザ→GET→サーバ
⇒ブラウザからは2.で指定されたアドレスにリクエストする。
で、どうなるかっていうと、、、
上の完了画面でF5を押された〜っていう場合
→3.だけが呼び出されるのでDBに更新に行くような処理(1.のような処理)が
何度も呼び出される心配がない。
上の戻るボタンが押された〜っていう場合
→GETの場合は"有効期限が切れました"ってことにはなりません。
通常GETの場合は、リクエストするURLに XXX=hoge&XXXX=hage って感じで、
リクエストされる情報がURL上に記述されている形になるため。
リクエストパラメーターってのは、、、っていう場合は、
HTTPセッションを使って、そっから取得する感じ。
この辺をフレームワークで隠蔽して、プログラマはあんまり考えなくてもいいように、、、、
うちの会社でも、どこの会社でも、たぶんそんな感じ。
なんで、こんなエントリを書いたかっていうと。
実はリダイレクトの仕掛けってよくわかってなかった。
Strutsのredirect使うと、そういう風に動くから。別に意識してなかった。
サーバー側でヨロシク処理してるのかと思ってた。
システムテストの時に、障害があって、Apacheのログ眺めてたときに。
"あっ、そういうことなんだ"って。
他にも、こういうのいっぱいあるんだろうなぁって。
フレームワークうんぬん語るのもいいけど、
こういうところをちゃんとおさえなきゃなって思います。
Teeda使ってみたいなぁ↓。
http://event.seasarfoundation.org/sc2007spring/viewAttachment.do?_pageName_=Session&_fileName_=sc2007spring_S4_Teeda.pdf
DBマガジン6月号のDeNAの記事
とにかく安いサーバーをたくさん並べて並べて〜
ってのが、大規模Webサイトのやり方だっていうのは知っていたものの。
んじゃ、それ具体的にどうやってやるんだろう?って。
いつもはなんとなく斜め読みしてしまう雑誌を、
風呂場でちゃんと読んでみた。
モバゲータウンとかモバオクとかを開発・運用してる
DeNAって会社の人(id:tokiharu)が書いている記事。
コレ、すごいガツンときたので、概要とか感想とか。
更新系と参照系でデータベースサーバー(筐体そのもの)を分ける
更新系・・・画面から入力された値などをデータベースにつっこむ
参照系・・・画面から入力された値などでデータベースから情報をとってくる
フツウに考えて(フツウにインターネットを使っていて)、参照系のアクセスが断然多い。
ちゅうことで、MySQLのレプリケーション(複製)機能を利用して、
更新系のインスタンス1つに対して、それのコピーとして参照系のインスタンスを複数用意する。
それによって、たくさんの参照系のアクセスがきても、高速にさばく、と。
(完全に更新系と参照系のデータに同期が取れているわけではないのに注意が必要)
でもって、更新系もいずれ1台では負荷が高くなってしまうので、
ゆくゆくは機能とか情報単位(会員情報とか、債権情報とか)で、
マスタを分割できるような設計にしておく(=JOINして一発でとってくるようなSQL書いちゃダメ)
更に、割り算したあまりとかうまく使って、マスターを分割したり。
(XXIDを3で割って余りが0だったら→hoge1サーバー、余りが1だったらhoge2サーバー、、とかそんなノリ)
そうやって細かくわけていくうちに、容量は数ギガっていう小さなものになるので、
そしたら、参照系のテーブルデータ(インデックスとか全部含めて)を全てメモリ上にのっけちまえ!と。
(ディスクI/Oが発生しないので、そりゃ早いわっちゅう話)
負荷分散
んじゃ、どうやって沢山ならべたサーバーにアクセスを振り分けるのよ?っていう話。
これにはDNSラウンドロビンっていうのを使う。
言葉じりは、なんかややこしそうだが、そんなことはなく、
問い合わせのたびに、沢山並んでるサーバーの中から一台を教えてくれるもの。
そんなこんなで均等に沢山並んでるサーバーにリクエストが割り振られる。
でもね、それだと、しょっぱいへっぽこなサーバーと、いかついハイスペックサーバーが
同じ感じに割り振られてしまうので、へっぽこサーバーにきたリクエストに対するレスポンスが
遅くなってしまう可能性があります。
それだけじゃなくって、逝っちゃったサーバー(ping投げても帰ってこないとか)にも
フツウにリクエストが行ってしまいます、と。
それを解決してくれるのが、MyDNSっていうオープンソースのプロダクト。
こいつを使うと、上で書いたDNSラウンドロビンの問題点が解決できる。
MyDNSは、データベースにテーブルを持って、設定値を保持することで、
それを参照しながら動くソフトウエア。
沢山並んだサーバー1台1台に対して1レコードっていう感じ。
SQL文だけでメンテできるのがウリで、サーバー再起動とかいらない。
MyDNS用テーブルのカラムに aux っていうのがあって、その設定によって優先度をわけている。
へっぽこサーバーとハイスペックサーバーの割合が設定できたり、
逝っちゃったサーバーにはリクエストしないようにしたり(auxカラムを0に設定)
だいたい、どこも、ヘルスチェックとかいって、数分に1回くらい
ping投げたり、シェルからSQL叩いてSELECT文発行したりすると思うけど、
そこで帰ってこないサーバーがいたら、auxカラムを0にUPDATEしてあげればいい。
運用的には、MyDNSを使うことで、『SELECT COUNT(*) FROM MyDNSのテーブル WHERE aux = 0』
とかやると何百台とか並んだサーバーの中で落ちてるサーバーがどれか?とか見れちゃったりとか。
その他
MySQL使った全文検索の話とか、リクエストを受け付ける際の考え方とか
非常に参考になることが書いてあります。(詳しくは買って読んで・・・)
アプリ屋として、面白そうだなと思ったのが、
アプリはperlで書いていて、ディスパッチは独自のフレームワークを使っている。
詳しくは書いてないけど、規約通りに動くようなフレームワークっぽい。
URLから、どのクラスのどのメソッドが実行されるか自動的に決まる〜みたいな。
んでもって、逆にSQLはソースにべた書き。
その方が運用的にやりやすい。既存機能の理解も早いし、機動性が上がる。
個人的にも、設定ファイルみてソースみてってあっちゃこっちゃ行くのはしんどいなと。。
つーか、記事自体は図入りでかなりわかりやすので、興味を持った人は、
是非購入することをお奨めします。
Spring勉強会に行ってきました。
SpringJDBC、SpringJPA
SpringJDBC
TemplateクラスとSupportクラスというのを使う。
Templateはデータソースをプロパティにセットしてくれて、
プログラマ的にはSupportクラスを使えば、Templateを扱うのが簡単になる。
(らしい。こればっかりはやってみないとわかりません)
トランザクションは設定ファイルのみの制御でできるし、
型のキャストもいい感じにやってくれるっぽい。
SpringがJDBCのコードをどう扱っているのかが気になりました。
フェッチのサイズ変えられるようなインタフェースがあるのか、とか。
カーソル開きっぱなしで1件1件フェッチしたりできるのか、とか。
個人的にはSQLはバンバン書きたい派なので。
こういうのもあるんだな〜といった印象。
ライトニングトークス
SpringExperienceに行ってきたよ
SpringExperienceというアメリカで開催された
Springフレームワークに関するカンファレンスに行ってきたという話。
参加者は700人くらいだったそう。
Spring単体の講演だけではなく、
Hibernateの人や、Sunの人とかの講演もあったそうだ。
世界中からいろんな人が来ていたらしい。
世界のGeekの中では、
"日本=Ruby"というイメージらしい。
海外行くときはRubyを勉強してから行くようにした方が
よいかもしれません。
Google Guice
Googleが作ったDIコンテナである、Google Guice(ジュース)の話。
とにかく型付けにこだわりがあるらしく。
全てがソースコードとアノテーションでできている。(XMLファイルはなし)
AOPアライアンスに準拠。
インジェクションする時は@injectionっていうアノテーション
バインドするときはbind(Hoge.class).to(Hage.class)って感じでHogeをHageにバインド
でもってIngector.getInstance(Hoge.class)って感じでHogeのインスタンスを取得
こんな流れみたい。
大人数で固い開発をするために、とにかくタイプセーフで。
そんなノリらしい。
SpringでDAO
SpringでS2DAOを動かす〜なんていう試み。
使ったことがないのでよくわからないが、
Hibernateよりも、S2DAOはいろんなところで
開発者に優しい工夫がされているようだ。
EasyMockを使った、実際データベースにアクセスせずに
モックを使ってDBアクセスまわりの自動テストをやろうというデモ。
大規模な開発になると、ビジネスロジックを書く人と、
データアクセスまわりを書く人がわかれるらしい。
デーアクセスまわりができてないから、
ビジネスロジックが書けませんでしたっていう、
チーム間の依存性を下げたり、
あとは、全ての自動テストを流す際に、
非常に時間がかかるので、現場でそういう工夫をしている、と。
自分が今までやってきた開発は、
機能ごとに人がアサインされていたので、あまりイメージ湧かず。
ビジネスロジックわかってないやつに、SQL書けるのか?とか。
それこそ一発のSQLで取ってこれるのに、
設計書に2回クエリ投げるって書いてあったら、
そうしなきゃイケなくなっちゃうんじゃないか?とか思ったり。
O/Rマッパーを使って、大きなテーブルから全レコードを取ってくる際に、
Finderで大きなListオブジェクトを扱うことになり、
OutOfMemoryエラーが出てしまうのを回避するために、
Iteratorというメソッドを使いましょうといったTipsの紹介も。
他には、MySQLではPreparedStatementが使用できず、
SQLインジェクションに注意が必要なんていう話もありました。
感想
すごい時代に取り残されているような感じがしました。
参加している人達が実感を持って、
質問したり、それにうなずいたりしているところに、
結構ポカーンとしてしまいました。
JNDIからデータソースひっぱってきたり、
ResultSetMetaDataを使って、
カラムの名前で取ってきたデータをコレクションにつっこんだり、
トランザクションの管理をフレームワークの中に隠蔽したり、
そういう実装を今までしたことがあるので、
どこら辺が便利で、どういう実装になっているかは大体把握できたが、
なかなか敷居は高いんじゃないかと思いました。
ゴールデンウィークあたりで1回動くもの作って、
次の勉強会も出てみたいなと思いました。