dave08
01/22/2018, 8:12 AMuserRepo.getUser(userId) and it wasn't found, should it return null, throw a domain exception (NoUserFoundException) or have a sealed class with a null object? (I'm using coroutines, not Rx...)spand
01/22/2018, 8:17 AMspand
01/22/2018, 8:18 AMCzar
01/22/2018, 8:20 AMfun getUser(id: YourIdType): User? and you return null when User can't be found; if the caller can be Java, I'd go with Optional<User> return type. Throw is bad practice here, because you're forcing try/catch semantics when your caller might be okay with not finding a user.Czar
01/22/2018, 8:24 AMrequireUser/findUser or whatever you call these two methods, but this seems superfluous to me, as it just complicates the API. If you're not working in an extremely performance-constrained environment a simple null/optional check of a return value should not be an issue and simpler approach (one less method) wins in my book.spand
01/22/2018, 8:30 AMCzar
01/22/2018, 8:41 AM?: error("") is something you'll find yourself writing more often than (?.let {}), then by all means get/find (where get throws and find returns null) is indeed a better approach. I'm probably just a bit biased due to the latest project I worked on, which didn't have many ?: error("") situations, if something wasn't found it didn't mean an error has happened. đdave08
01/22/2018, 8:52 AMCzar
01/22/2018, 8:56 AMAndreas Sinz
01/22/2018, 9:25 AMAndreas Sinz
01/22/2018, 9:25 AMdave08
01/22/2018, 10:18 AMcedric
01/22/2018, 2:48 PMnull, I've seen findUser()/findUserNoThrow() or findUser()/findUserOrNull(). This is more useful in libraries where you want to give your users options.dave08
01/22/2018, 3:30 PMcedric
01/22/2018, 3:31 PMcedric
01/22/2018, 3:32 PMraulraja
01/22/2018, 8:54 PM? or Option to denote User not found if you want to remain exception free. Does it have the same semantics to not actually finding the user to say the network is down?
I'd model the exceptional known cases in an ADT and return a disjunction of a known error case or the actual value:
sealed class ApiError
object NetworkFailure: ApiError()
data class UserNotFound(val id: String): ApiError()
fun findUser(): Deferred<Either<ApiError, User>> = TODO()
You loose valuable types and semantics when modeling known cases with just ? or Option and you may need those down the road to display appropriate error messages or branch out biz logic into the unhappy path.
If you are interested in an FP approach to error handling more info here: http://arrow-kt.io/docs/patterns/error_handling/tschuchort
01/22/2018, 9:03 PMMaybe. I prefer nullable types for non-rx functions because they're nicer to use. ?. is like Maybe.flatMap anywaycedric
01/22/2018, 9:07 PMcedric
01/22/2018, 9:08 PMdave08
01/22/2018, 10:46 PMcedric
01/22/2018, 10:48 PMcedric
01/22/2018, 10:48 PMraulraja
01/22/2018, 10:54 PMwhen over a sealed class hierarchy).
An example of pure and total functions are:
fun add(a: Int, b: Int): Int = a + b
And example of an impure one:
var x: Int = 0
fun addToX(a: Int): Int = x = x + araulraja
01/22/2018, 10:56 PMvar x: Int = 0
fun addToX(a: Int): Int = x = if (a > 0) x + a else throw IllegalArgumentException("value expected to be positive")dave08
01/22/2018, 10:58 PMreturn in the middle of fun logic? Also, even exceptions can be unit tested...? @raulraja You still needed to use an external var x to make it impure, the exception didn't do it, did it?raulraja
01/22/2018, 10:58 PMraulraja
01/22/2018, 10:59 PMcedric
01/22/2018, 10:59 PMF => T, you will typically think âItâs a function that takes a parameter of type F and returns a parameter of type T. Here is the cool part: now read this from a mathematical eye and youâll read âF implies Tâ. There is actually a mathematical equivalence between these two interpretations: they are strictly equivalent according to a theorem that was proven decades ago.raulraja
01/22/2018, 10:59 PMraulraja
01/22/2018, 11:00 PMraulraja
01/22/2018, 11:00 PMdave08
01/22/2018, 11:01 PMraulraja
01/22/2018, 11:02 PMcedric
01/22/2018, 11:02 PMraulraja
01/22/2018, 11:02 PMraulraja
01/22/2018, 11:03 PMfun printLater(): () -> Unit = { println("Hello pure") }cedric
01/22/2018, 11:04 PMraulraja
01/22/2018, 11:04 PMpure because printLater performs no effects, it just returns a function that does.dave08
01/22/2018, 11:07 PMdave08
01/22/2018, 11:07 PMcedric
01/22/2018, 11:08 PMraulraja
01/22/2018, 11:13 PMcedric
01/22/2018, 11:13 PMcedric
01/22/2018, 11:14 PMcedric
01/22/2018, 11:14 PMdave08
01/22/2018, 11:15 PMfun, but rather for total fun?raulraja
01/22/2018, 11:15 PM@Throws exceptions right?cedric
01/22/2018, 11:16 PMraulraja
01/22/2018, 11:17 PMtschuchort
01/22/2018, 11:22 PMcedric
01/22/2018, 11:23 PMcedric
01/22/2018, 11:23 PMEither, the compiler will only keep you honest if quite a few conditions are met (sealed type, using when, etcâŚ). Still plenty of opportunities to ignore the error part of Either.dave08
01/22/2018, 11:24 PMcedric
01/22/2018, 11:25 PMdave08
01/22/2018, 11:27 PMraulraja
01/22/2018, 11:29 PMraulraja
01/22/2018, 11:30 PMcedric
01/22/2018, 11:30 PMcedric
01/22/2018, 11:30 PMraulraja
01/22/2018, 11:32 PMcedric
01/22/2018, 11:33 PMraulraja
01/22/2018, 11:37 PM