when should I be using `error()` over `throw Illeg...
# getting-started
w
when should I be using
error()
over
throw IllegalStateException
? is
error
always more idiomatic?
j
I personally use
error()
all the time. It's more idiomatic and more concise. The only reason to use
throw IllegalStateException(...)
explicitly is if you want to give it a cause, which
error()
doesn't support
👍 1
1
e
also
check(x) { msg }
instead of
if (!x) error(msg)
and
checkNotNull(x) { msg }
instead of
x ?: error(msg)
or `require`/`requireNotNull` for
IllegalArgumentException
I find it rare to need
error
or `throw IAE`/`ISE`
j
and
checkNotNull(x) { msg }
instead of
x ?: error(msg)
I agree with everything except this. When I have a chain of operations on a collection, or a sequence of function calls etc, I find it much more readable to use an elvis at the end rather than wrapping in `checkNotNull`:
Copy code
list.map { ... }.firstOrNull { ... } ?: error("...")

foo.bar?.baz()?.stuff() ?: error("...")
e
I'd tend to use
Copy code
val result = list.map { ... }.firstOrNull { ... }
return checkNotNull(result) { "..." }
or similar. whether you use
checkNotNull
or
?:
it doesn't really chain well
j
Depends on what you call chaining. To me the important aspect is that the flow goes left to right. I don't mind that
?:
is not
.
.
e
Copy code
checkNotNull(...).foo
(... ?: error()).foo
is awkward either way, if
...
is a multi-line expression
j
Ah I see what you mean. Well, usually the elvis and the
error
come last thanks to safe calls. I never nest expressions like
(... ?: error())
in a chain. If I need this kind of expressions I extract them to functions
💯 1
s
assuming
...
is a multi-line expression, I tend to use
Copy code
...?.foo ?: error("abc")
but of course you could do:
Copy code
val f = ...?.foo
checkNotNull(f)
e
sometimes that doesn't have the same result, e.g.
Copy code
checkNotNull(x.nullable1()).nullable2()
!=
Copy code
x.nullable1()?.nullable2() ?: error()
s
true, it's a pattern to assert that a non-null
f
could be aquired. which is almost always what I want.
j
sometimes that doesn't have the same result
Right, but in the case you describe, I'd probably extract the first part to a separate non-nullable extension.
e
checkNotNull acutally throws IllegalStateException and not IllegalArgumentException. You may find this article helpfull about these built in functions: https://medium.com/@elenavanengelen/kotlin-tips-and-tricks-you-may-not-know-3-built-in-assertions-d26540ccb2e0
j
Yes, the question was about throwing
IllegalStateException
here, and we compared it with
error()
, which also throws
IllegalStateException
, so all good 😉
1
e
I think check/require functions are cleaner for checking conditions than doing conditions manually and then calling error(). However in some cases error() is more approriate, for example in when statements.
here is an example
Copy code
fun processPaymentMethod(paymentMethod: String) {
    when (paymentMethod) {
        "CreditCard" -> println("Processing payment with Credit Card")
        "PayPal" -> println("Processing payment with PayPal")
        else -> error("Unsupported payment method: $paymentMethod")
    }
}
j
I don't think
error
supports lambdas, it doesn't really make sense since we're using the message 100% of the time
Ah, I realized it's an example of bad usage
e
yea i copy pasted the wrong example, i'll update that
j
I think check/require functions are cleaner for checking conditions than doing conditions manually and then calling error()
Yeah that's what we were trying to refine in the discussion above. Which cases more specifically are more suited for one or the other. As I mentioned, I like how the elvis flows with
error()
in some chained cases. For single-condition checks, the dedicated `check`/`require` functions are more appropriate indeed.
e
yes its a matter of preference , i prefer asigning the end value and then do a check... or require... . like mentioned above by ephemient
makes it more explicit + readable. also i find it more maintainable as the chain might change over time, thus it helps to separate the null check from it.