Skip to content

Sample code in scala, using ZIO, using the examples of the book Domain modeling made functional from Scott Wlaschin.

Notifications You must be signed in to change notification settings

routis/dmmf-scala

Repository files navigation

ddmf-scala

Scala Steward badge

Sample code in scala, using ZIO, using the examples of the book Domain modeling made functional from Scott Wlaschin.

Features

  • Scala 3
  • Hexagonal Architecture
  • ZIO 2
  • New (refined) types: Application demonstrates the use of ZIO Prelude New Types as a way to implement refined types for DDD value objects.
  • Validation: Application uses Validation[E,A] to back the validations of input models.
  • Combining non-effectful & side-effecting validations: Validation[E,A] is a datastructure representing either a sucessful validation or some errors. In the application we demonstrate a way to combine this with ZIO[R,E,A].

DDD Value objects

Project demonstrates the use of new types to enhance the type safety and clarity of simple DDD value objects. Three approaches have been used:

The DDD Value object simple or composite can be found in domain

An example of a simple DDD VO using new types

 type ZipCode       = ZipCode.Type
 object ZipCode extends Newtype[String]:
    override inline def assertion: Assertion[String] = matches("^\\d{5}$".r)

An example of a simple DDD VO that uses opaque types is the Money which is implemented using Joda Money.

import org.joda.money.Money as JodaMoney
import org.joda.money.CurrencyUnit as JodaCurrencyUnit

opaque type Money = JodaMoney
object Money:

  def apply(amount: BigDecimal): Money = JodaMoney.of(JodaCurrencyUnit.EUR, amount.bigDecimal)

  def make(amount: BigDecimal): Validation[String, Money] =
    Validation
      .fromTry(Try(Money(amount)))
      .mapError(t => s"$amount is not a valid amount. ${t.getMessage}")
      

Finally, an example that uses both methods is BillingAmount which is based on Money which is constraint to a specific max value

import zio.prelude.{ Assertion, Identity, Subtype, Validation }
import Assertion.*
import zio.prelude.newtypes.Sum

object BillingAmount extends Subtype[Money]:

  override inline def assertion: Assertion[Money] = between(Money(0), Money(10000))

  def total(prices: Iterable[Price]): Validation[String, BillingAmount] =
    make(Money.total(prices))

About

Sample code in scala, using ZIO, using the examples of the book Domain modeling made functional from Scott Wlaschin.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages