Skip to content

Instantly share code, notes, and snippets.

@jonatbergn
Last active January 3, 2023 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonatbergn/365a1f7831642f709724cd09d1dfb301 to your computer and use it in GitHub Desktop.
Save jonatbergn/365a1f7831642f709724cd09d1dfb301 to your computer and use it in GitHub Desktop.
class Milk
class Beans
class Powder
class Water
class Coffee(water: Water, powder: Powder)
sealed interface BrewResult {
class Success(val coffee: Coffee) : BrewResult
sealed interface Failure : BrewResult {
object InsufficientPowder : Failure
object InsufficientWater : Failure
object BrewerBroken : Failure
}
}
sealed interface GetMilkResult {
class Success(val milk: Milk) : GetMilkResult // don't expose success result
sealed interface Failure : GetMilkResult, BrewResult {
object Expired : Failure
object Empty : Failure
}
}
sealed interface GetBeansResult {
class Success(val beans: Beans) : GetBeansResult // don't expose success result
object Empty : GetBeansResult, BrewResult
}
sealed interface GrindBeansResult {
class Success(val powder: Powder) : GrindBeansResult // don't expose success result
sealed interface Failure : GrindBeansResult, BrewResult {
object GrinderBroken : Failure
object InsufficientBeans : Failure
}
}
interface Service {
fun getMilk(): GetMilkResult
fun getBeans(): GetBeansResult
fun grindBeans(beans: Beans): GrindBeansResult
fun brew(powder: Powder, water: Water, milk: Milk): BrewResult
}
interface CoffeeMachine {
fun brew(): BrewResult
}
class CoffeeMachineImpl(
private val service: Service,
) : CoffeeMachine {
override fun brew(): BrewResult {
val milk = when (val getMilkResult = service.getMilk()) {
is GetMilkResult.Success -> getMilkResult.milk
is GetMilkResult.Failure -> return getMilkResult
}
val beans = when (val getBeansResult = service.getBeans()) {
is GetBeansResult.Success -> getBeansResult.beans
is GetBeansResult.Empty -> return getBeansResult
}
val powder = when (val grindBeansResult = service.grindBeans(beans)) {
is GrindBeansResult.Success -> grindBeansResult.powder
is GrindBeansResult.Failure -> return grindBeansResult
}
return service.brew(powder, Water(), milk)
}
}
fun main(coffeeMachine: CoffeeMachine) {
when (val brewResult = coffeeMachine.brew()) {
is BrewResult.Success -> println("Enjoy your ${brewResult.coffee}")
BrewResult.Failure.BrewerBroken -> println("Brewer is broken")
BrewResult.Failure.InsufficientPowder -> println("You did not use enough powder")
BrewResult.Failure.InsufficientWater -> println("You did not use enough water")
GetBeansResult.Empty -> println("Please buy more beans first")
GetMilkResult.Failure.Empty -> println("Sorry, we're out of mild")
GetMilkResult.Failure.Expired -> println("Sorry, the milk is stale")
GrindBeansResult.Failure.GrinderBroken -> println("Sorry, your grinder seems to be broken")
GrindBeansResult.Failure.InsufficientBeans -> println("Sorry, you did not use enough beans to create powder")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment