DBにエンティティを永続化するというシチュエーションを考える。
例えばPersonというエンティティとしよう。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class Person(name: String, age: Int) |
これをDBに保存するなら、PrimaryKeyが必要だ。ま、普通はIDを付けるでしょう。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class Person(id: Int, name: String, age: Int) |
さて、問題は、「ID採番前のPersonはどう表現するの?」という話。
案1. id = 0 とか、負の数を「採番前」ということにする
冗談です。
案2. idの型をOptionにする
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class Person(id: Option[Int], name: String, age: Int) |
確かに「IDの有無」を表現はできてるが、これだと例えば「これから採番するPersonのリスト」のような型が作りにくいです。
案3. オブジェクト指向っぽく行けばいいんじゃない?
いろいろ考えたんだけど落ち着いたのがここ。あんまカッコイイ答えじゃないんだけどね。
ただ、「case classにする」ってところだけは守るという制約でScalaで書こうと思うと、やっぱりちょっと考えないといけない。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sealed trait Person { | |
val name: String | |
val age: Int | |
} | |
case class IdentifiedPerson(id: Int, name: String, age: Int) extends Person | |
case class UnIdentifiedPerson(name: String, age: Int) extends Person |
で、こうなった。id以外のメンバは何回も書いてるのが正直気に入らない。でも、使うときは多分これが一番気持ちよく使えると思う。
もっと良い書き方募集。