2012年7月24日火曜日

永続化の前後をクラスで表現する

※本エントリの内容は「たぶんコレでいいんじゃない?むしろ違ったら教えて下さい」的な内容です。

DBにエンティティを永続化するというシチュエーションを考える。
例えばPersonというエンティティとしよう。



これをDBに保存するなら、PrimaryKeyが必要だ。ま、普通はIDを付けるでしょう。





さて、問題は、「ID採番前のPersonはどう表現するの?」という話。

案1. id = 0 とか、負の数を「採番前」ということにする

冗談です。

案2. idの型をOptionにする



確かに「IDの有無」を表現はできてるが、これだと例えば「これから採番するPersonのリスト」のような型が作りにくいです。

案3. オブジェクト指向っぽく行けばいいんじゃない?

いろいろ考えたんだけど落ち着いたのがここ。あんまカッコイイ答えじゃないんだけどね。
ただ、「case classにする」ってところだけは守るという制約でScalaで書こうと思うと、やっぱりちょっと考えないといけない。



で、こうなった。id以外のメンバは何回も書いてるのが正直気に入らない。でも、使うときは多分これが一番気持ちよく使えると思う。

もっと良い書き方募集。

2012年7月17日火曜日

Windowsガジェット環境でのsubstr

Windowsガジェット(最初はVistaサイドバーガジェットとか呼ばれてたもの)って、もはや生みの親であるMicrosoftからも「Windows8が出たら要らないよね」って言われちゃったかわいそうな子だけれども、でもなんだかんだ言ってもWindows7使ってるうちは何かと便利なツールなわけで、結構馬鹿にできないと思うんです。

というわけで、to-banからJSON引っ張って今日の"当番"をWindowsガジェットに表示させておくと捗るぞ、と思って手を出した。

が、すっげーアホくさいところでハマったので、記録しておく。

それがString.substr関数。

これ、第一引数に負の数を渡すと、現在の標準では文字列の後ろから数えてくれるんだけど、Windowsガジェット環境(や超古いブラウザ)では負の数を渡すと何もしてくれなくなる。



厄介なのは、IE9が入ってるWindows環境でも、ガジェット上ではガジェット環境での挙動を示すということ。「IEで動けばガジェットでも大体動くだろー」とタカをくくってるとハマる(体験談)

2012年7月16日月曜日

PlayでurlFormEncodedなデータを受け取る

Playでformからの入力を受け取る場合は、ファイルアップロードが必要な場合を除けば、大抵の場合はurlFormEncodedを通してデータを受け取る事になると思う(Ajaxとかいう解はとりあえず考えない)。例えば以下の様なコードになる。



言うまでもなく、Requestからデータを取り出す部分が無駄に長い。
これは、urlFormEncodedのbodyの型がMap[String, Seq[String]]だから。もちろんプロトコル上はこの型が妥当なのだが、大抵の場合はValueは1つだけ値があれば十分なので、Seqから1個取り出すのが冗長に感じられるわけだ。

じゃあ、ということで、以下の様な関数を作ってやればとりあえず短くはなる。



短くはなるんだけど、ただ単純に処理を切り出しただけ。使ってみるとわかるけど、あんまりScalaっぽくない。
せっかくScala使ってるんだから、型クラス使いたいよね!

というわけで、こうなった。



paramOpt関数がControllerから呼び出す関数。
こいつはimplicit parameterでExtractor[T]を受け取っていて、そのExtractorのextract関数を利用してデータ抽出を行う。
paramOpt関数自信も型パラメータを持っていて、そこに指定された型に合ったExtractorが選択されて使われるわけだ。
extractorByみたいな関数も用意しておけば、IntExtractorの様に、既存のExtractorと型変換用関数を組み合わせて新たなExtractorを構成するのも簡単だ。

Extractor[T]を使って最初のPersonの例を書きなおすとこうなる。



スッキリ!



追記:

extractorByの中身、何をやってるかって言うと、A => Option[B] と B => Option[C] を組み合わせて A => Option[C] を作ってるんだよね。で、


って呟いたら、反応されてた。



やっべ、kleisliわかんねぇ。勉強します。。。