Skip to content

Instantly share code, notes, and snippets.

@programaker
Last active October 21, 2021 14:36
Show Gist options
  • Save programaker/09de2a15cfa587cdbe78fb724d33e6c2 to your computer and use it in GitHub Desktop.
Save programaker/09de2a15cfa587cdbe78fb724d33e6c2 to your computer and use it in GitHub Desktop.
Scala 3 export clauses
/*
* The good practices say we shouldn't use the same type for everything (domain, json, persistence, ...), but
* most of the time those types are very similar - if not exactly identical - creating a lot of duplication.
*
* Inheritance to the rescue? Nah... not very FP and even the OOP folks are aware that we should
* prefer composition over it. But composition has it's own challenges (Law of Demeter for instance).
*
* Let's see how the new `Export Clauses` in Scala 3 can help with that:
* https://docs.scala-lang.org/scala3/reference/other-new-features/export.html
* */
import io.circe.Encoder
import io.circe.generic.semiauto.*
import io.circe.syntax.*
import java.util.UUID
// the pure domain concept/entity
// the base data is declared here, and only here
case class Frunfles(a: String, b: Int, c: Boolean)
object Frunfles:
given Encoder[Frunfles] = deriveEncoder
// persisted entity containing an id
// no need to make the id optional
// no need to duplicate Frunfles fields
case class PersistedFrunfles(id: UUID, data: Frunfles):
export data.*
object PersistedFrunfles:
// easy to avoid exposing the id in Json
given Encoder[PersistedFrunfles] = Encoder.instance(_.data.asJson)
// type-safe operations
// explictly stating which operations require an entity with id
def insert(f: Frunfles): PersistedFrunfles = ???
def update(f: PersistedFrunfles): PersistedFrunfles = ???
def delete(f: PersistedFrunfles): Unit = ???
// composition over inheritance, more FP-ish
val f = Frunfles("Meh", 42, true)
val pf = PersistedFrunfles(id = UUID.randomUUID().nn, data = f)
// exported fields available without calling `.data`. Happy demeter!
val id = pf.id
val a2 = pf.a
val b2 = pf.b
val c2 = pf.c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment