what is a good way to share code between catch blo...
# codereview
c
what is a good way to share code between catch blocks? here is the code with the duplicated code:
Copy code
val TOTAL_TRIES = 3
            val triedPorts = ArrayList<Int>(TOTAL_TRIES)
            while (true) {
                val realPort = port ?: findFreePort()
                triedPorts.add(realPort)
                val undertow: Undertow = buildUndertow(rootHandlers, defaultHandler, realPort, host)
                try {
                    undertow.start()
                } catch (e: RuntimeException) {
                    // it seems that undertow sometimes wraps the bind exception in a runtime exception
                    if (e.cause is BindException) {
                        if (port != null)
                            throw RestaurantException("could not start server on port $port")
                        if (triedPorts.size == TOTAL_TRIES)
                            throw RestaurantException("could not start restaurant after trying $TOTAL_TRIES times." +
                                    " ports tried: $triedPorts")
                        continue
                    }
                } catch (e: BindException) {
                    // if no port was specified, we retry
                    if (port != null)
                        throw RestaurantException("could not start server on port $port")
                    if (triedPorts.size == TOTAL_TRIES)
                        throw RestaurantException("could not start restaurant after trying $TOTAL_TRIES times." +
                                " ports tried: $triedPorts")
                    continue
                }
all strategies that i tried just made it more confusing imo.
k
Unlike Java, Kotlin currently doesn't support multi-catch blocks. There is a feature request KT-7128 open for it, but don't hold your breath. In the meantime, you can do something like this:
Copy code
try {
                    undertow.start()
                } catch (e: Exception) {
                    val realException = if (e is RuntimeException && e.cause is BindException) e.cause else e
                    when (realException) {
                        is BindException -> {
                            // if no port was specified, we retry
                            if (port != null)
                                throw RestaurantException("could not start server on port $port")
                            if (triedPorts.size == TOTAL_TRIES)
                                throw RestaurantException("could not start restaurant after trying $TOTAL_TRIES times." +
                                        " ports tried: $triedPorts")
                            continue
                        }
                    }
                }
Unfortunately this gives your exception-handling code two more levels of indentation.
j
Why not use functions?
1
c
Why not use functions?
i tried extracting a function and it looked more complex to me than the duplicated version
In the meantime, you can do something like this:
catching
Exception
is something i did not think about I will try that. btw in your code example you need to rethrow the exception when it is unknown. thats probably an indication that the catch
Exception
pattern is error prone.
1