https://kotlinlang.org logo
#random
Title
j

Jason5lee

03/15/2022, 8:26 AM
Suppose you're writing a REST API service. You want to query a data from DB, and if no record found, you response a 404 not found. I have two possible implementations. 1.
Copy code
class SomethingNotFoundException : Exception()

// DB query side
if (result.isEmpty()) {
    throw SomethingNotFoundException()
}

// API implement
try {
    ....
} catch (e: SomethingNotFoundException) {
    return HttpResponse(404, "SOMETHING_NOT_FOUND")
}
2.
Copy code
// DB query side
if (result.isEmpty()) {
    throw HttpException(404, "SOME_THING_NOT_FOUND")
}
where
HttpException
is handled by the framework or a single
catch
that extracts the response parameter from the exception fields. The second approach is simpler, but it couples with the protocol as you involves the HTTP exception and related concept like status code. Which one would you choose?
s

Sam

03/15/2022, 8:39 AM
Using exceptions for control flow sacrifices a lot of compile-time safety. I would actually reject both options and instead have the DB layer return a sealed class with different subclasses for the possible success or failure modes.
2
r

Rob Elliot

03/15/2022, 8:50 AM
Or in this case just return null, and change that into a 404 at the http layer.
👌 3
j

Jason5lee

03/15/2022, 8:57 AM
This is just a simplified version, there might be other exceptions so null is not enough, but I get your point.
t

thanksforallthefish

03/15/2022, 9:04 AM
personally, I tried returning sealed classes/result/arrow either but compared to exception they pollute the entire trace call. maybe that highlights other design issues, as in too many layers of indirection, but it is a lot less transparent than exception. also, exceptions map into frameworks, for instance with spring we can just have a
@ControllerAdvice
and catch all exceptions that extend a generic
NotFoundException
and transform those into 404
☝️ 1
s

Sam

03/15/2022, 9:12 AM
If you can live with exceptions then go for it! My experience is that "transparent" is just another way to say "unsafe and undocumented". The "polluting" that you describe is just what happens when you make a method actually be honest to its consumers about what it can return (because exceptions are just alternate return values).
t

thanksforallthefish

03/15/2022, 9:16 AM
yep, I get it. that is why I tried it, because on paper I like it more (both aesthetically and from a “exception should not be used to model expected failures” standpoint). my reality check (but I guess mine is just one “use case”) are frameworks, which understand exceptions way better, and the fact that in a multi-layer application most of the layers don’t care about most of the expected failures, so each layer just become more complex to just pass the failure through and map the success
j

Jason5lee

03/15/2022, 9:46 AM
@thanksforallthefish My question is, if you inherit from, e.g.
NotFoundException
, you are coupling with the framework or protocol. I know it may be a widely used practice but I'm just asking.
t

thanksforallthefish

03/15/2022, 9:49 AM
it might depend on the framework, spring is totally agnostic. you can define your own exception and use that in a controller advice. then your domain remains isolated from the framework, and you have a mapping layer (the controller advice) which map from domain exception to framework, but that layer is where it needs to be
r

Rob Elliot

03/15/2022, 9:50 AM
If you're going to use exceptions there's a 3rd option - throw your own
NotFoundException
with no HTTP or framework specific coupling, and use your framework's capabilities to map that exception to an HTTP response. Then the coupling is between the framework's HTTP layer & your domain, rather than coupling the data access to HTTP and/or the framework.
Beat me to it by a second or two...
📸 1
c

christophsturm

03/15/2022, 10:14 AM
I would use null for not found, because thats not an exceptional case, and an exception when something goes wrong
t

Ties

03/15/2022, 10:25 AM
I would also go for an either, but if you do exceptions I would create my own domain exceptions and transform those to http exceptions in the controller. This way the place that throws the exceptions doesn't have to know about it being run in a http environment (so it can be more easily be reused/tested )
c

christophsturm

03/15/2022, 10:56 AM
imo sealed classes + nullable is more idiomatic kotlin than an either type. and exception for anything that can just bubble up (and result in an http error)
t

Ties

03/15/2022, 11:07 AM
How would the sealed classes + nullable look like?
c

christophsturm

03/15/2022, 11:38 AM
just using a sealed class hierarchy instead of an either, and also giving meaning to null (for example in a store interface null means not found)
but most of the time i would proably use nullable + exceptions. because null could be something i want to recover from, and all other errors will just fail the whole request. like
user = store.get(key)?: fallbackStore.get(key)
4 Views