※本エントリの内容は「たぶんコレでいいんじゃない?むしろ違ったら教えて下さい」的な内容です。
DBにエンティティを永続化するというシチュエーションを考える。
例えばPersonというエンティティとしよう。
これをDBに保存するなら、PrimaryKeyが必要だ。ま、普通はIDを付けるでしょう。
さて、問題は、「ID採番前のPersonはどう表現するの?」という話。
案1. id = 0 とか、負の数を「採番前」ということにする
冗談です。
案2. idの型をOptionにする
確かに「IDの有無」を表現はできてるが、これだと例えば「これから採番するPersonのリスト」のような型が作りにくいです。
案3. オブジェクト指向っぽく行けばいいんじゃない?
いろいろ考えたんだけど落ち着いたのがここ。あんまカッコイイ答えじゃないんだけどね。
ただ、「case classにする」ってところだけは守るという制約でScalaで書こうと思うと、やっぱりちょっと考えないといけない。
で、こうなった。id以外のメンバは何回も書いてるのが正直気に入らない。でも、使うときは多分これが一番気持ちよく使えると思う。
もっと良い書き方募集。
2012年7月24日火曜日
2012年7月17日火曜日
Windowsガジェット環境でのsubstr
Windowsガジェット(最初はVistaサイドバーガジェットとか呼ばれてたもの)って、もはや生みの親であるMicrosoftからも「Windows8が出たら要らないよね」って言われちゃったかわいそうな子だけれども、でもなんだかんだ言ってもWindows7使ってるうちは何かと便利なツールなわけで、結構馬鹿にできないと思うんです。
というわけで、to-banからJSON引っ張って今日の"当番"をWindowsガジェットに表示させておくと捗るぞ、と思って手を出した。
が、すっげーアホくさいところでハマったので、記録しておく。
それがString.substr関数。
これ、第一引数に負の数を渡すと、現在の標準では文字列の後ろから数えてくれるんだけど、Windowsガジェット環境(や超古いブラウザ)では負の数を渡すと何もしてくれなくなる。
厄介なのは、IE9が入ってるWindows環境でも、ガジェット上ではガジェット環境での挙動を示すということ。「IEで動けばガジェットでも大体動くだろー」とタカをくくってるとハマる(体験談)
というわけで、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わかんねぇ。勉強します。。。
言うまでもなく、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] を作ってるんだよね。で、
A => Option[B] と B => Option[C] を組み合わせて A => Option[C] を作るのって、scalaz的にはどうやるのが一番カッコイイですか・・・?
— Hirokazu NISHIOKAさん (@nisshieeorg) 7月 16, 2012
って呟いたら、反応されてた。
(無駄に?) kleisli 使って☆(f) >=> ☆(g) apply _とか?( scalaz6 )twitter.com/nisshieeorg/st…twitter.com/nisshieeorg/st…
— Kenji Yoshidaさん (@xuwei_k) 7月 16, 2012
やっべ、kleisliわかんねぇ。勉強します。。。
登録:
投稿 (Atom)