Help us understand the problem. What is going on with this article?

ScalaでDomain層にFirst Class Collectionを作るときのテクニック(JSON)

More than 1 year has passed since last update.

悩み

Domain駆動設計を採用しており、Domain層をPOJO(ScalaだとPOSO?)に作りたいってなったら、First Class Collectionを作るにしても、なんやかんやで、mapとか使いたくなることが多い。

とはいえ、そこで、mapを使えるようにしたら、なんか負けた気がするので、ちょっとしたテクニックで回避してみた。

課題

SomethingEntity の集合を保持するFirst Class Collectionを想定する。

case class SomethingEntity(id: SomethingId)

case class SomethingEntities(value: Seq[SomethingEntity])

この SomethingEntitiesの保持しているデータを全部JSONにしたいとき、

somethingEntites.value.map { somethingEntity =>
  convertToJson(somethingEntity)
}

// convertToJsonで好きなJSONライブラリを使って変換するのを想定している

みたいな感じにしたら意味ないよねって前提。

First Class Collectionだから、そもそも、classは、

case class SomethingEntities(private val value: Seq[SomethingEntity])

って感じで、 private にする。

すると、

somethingEntites.value.map { somethingEntity =>
  convertToJson(somethingEntity)
}

のvalueが取れなくてコンパイルエラーになる。

convertToJson 部分はライブラリに依存するから、

case class SomethingEntities(private val value: Seq[SomethingEntity]) {
  def toJson: Seq[String] =
    value.map(v => convertToJson(v))
}

みたいな実装はできない。(あくまでPOSOにこだわるなら。ただし、JSONはDomainに依存させても良いじゃんって場合はぜんぜん良いと思う。)

解決策

うすいJsonWriter的なtraitを定義だけしておいて、実装はお任せ的なことにするといける。

trait SomethingEntitiesWriter[JSON] {
  def toJson(entity: SomethingEntity): JSON
}

これを宣言しておいて、

case class SomethingEntities(private val value: Seq[SomethingEntity]) {
  def toJson[JSON](implicit writer: SomethingEntitiesWriter[JSON]): Seq[JSON] =
    value.map(writer.toJson)
}

みたいな感じ。

こうしておいて、 SomethingEntitiesWriter を以下みたいに実装する。

implicit object SomethingEntitiesWriterImpl extends SomethingEntitiesWriter[String] {
  override def toJson(entity: SomethingEntity): String =
    convertToJson(entity)
}

// convertToJsonで好きなJSONライブラリを使って変換するのを想定している

この implicit object をスコープに入れておいて、

somethingEntites.toJson[String]

と呼び出せば、良い感じに中のCollectionに直接アクセスしないで全部のEntityを Seq[String] にしてくれる感じが出来る。

このテクニック使えば、大体のことはいける気がする。

以上です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした