Rails勉強会用ポジションペーパー

【名前】
 篠原 英治


【年齢】
 27歳


【仕事】
 今月いっぱいでSI会社を辞めて、来月からネットサービス会社で働きます。
 転職先(10月から)でRails使うカモ、、ということで、今回で3回目の参加になります。
 前回はソースコードをたくさん読めて非常に参考になりました。
 今回もソースコードを読みたいです。

Rails勉強会用のポジションペーパー

【名前】
 篠原 英治


【性別】
 男


【年齢】
 27歳


【仕事】
 SIerで割と大きめな開発をしてます。
 技術的にはJavaとかSQLとかで、
 Webアプリとかバッチアプリとか。


【勉強会参加の理由】
 6年目になったけどJavaしか馴染みがないのはちょっと寂しい。
 転職先(10月から)でRails使うカモ。
 なんかもっと、こう、ブワーっと開発したい。

自動テストのメモ

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はバンバン書きたい派なので。
こういうのもあるんだな〜といった印象。

SpringJPA

JPA自体はJavaEEの標準仕様。
EJB3.0の一部だが、コンテナがなくてもJPAは動かせる、
っていうので勉強しようかなと思ってたもの。
(2年目の頃やってた案件で、コンテナにデプロイする時は、
近所のカフェにお茶しに行ったりしてました。。)


扱うものは基本的に以下の3つ。
・永続化対象オブジェクト(Entity)
・↑を管理するクラス(EntityManager)
・↑の動きを定義する(persistence.xml)


JPAもそれをそのまま使うのではなく、
Springがいい感じに吸収してくれて。
これもTemplateとSupportクラスを使う感じ。

その他

1対Nがどうたらこうたらでレイジーロードが〜っていうのがよくわからず。
話についていけなかった。何やら画面に表示する際に、
ServletのFilterを使ってあーだこーだっていう話らしい。
そういえば前にS2のカンファレンスに行った時もそんな話題が出てた。

ライトニングトーク

SpringExperienceに行ってきたよ

SpringExperienceというアメリカで開催された
Springフレームワークに関するカンファレンスに行ってきたという話。


参加者は700人くらいだったそう。
Spring単体の講演だけではなく、
Hibernateの人や、Sunの人とかの講演もあったそうだ。
世界中からいろんな人が来ていたらしい。


世界のGeekの中では、
"日本=Ruby"というイメージらしい。


海外行くときはRubyを勉強してから行くようにした方が
よいかもしれません。


JDBCのコードを新人に教えるより、
iBATISを教えた方がいいんじゃないか?
なんていう小話も。

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回動くもの作って、
次の勉強会も出てみたいなと思いました。

正規表現(そろそろやんなきゃ・・・)

社会人6年目になりました。
未だにガッツリ正規表現を使いこなせません。
えっちらおっちらやってます。


そりゃさすがにいかんでしょう。
ということで↓こんなん作ってみました。

re = Regexp.new(ARGV[0])

if re =~ ARGV[1]
    p "true"
    p $1
else
    p "false"
end


↓こんなノリです。

C:\ruby_study>ruby regexp_study.rb "(A..D)" "ABCDE"
"true"
"ABCD"


さて、バンバンぶっ叩いて覚えるか。


あ、正規表現のオプションを設定できるようにしなきゃ。。