8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-04-15

悩み

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] にしてくれる感じが出来る。

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

以上です。

8
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?