Coding Style
Our project follows the standard Kotlin coding conventions with the following changes
-
We allow up to 120 characters per line, please use all of the available space.
-
Only capitalize the first letter of words/acronyms/abbreviations/initialisms when using CamelCasing for example it's
UiTest, notUITest,IsoMdocType, notISOMDocType, and so on.
Exception Handling
-
Never catch
Throwable:Throwableis the root of the hierarchy and includes fatal system errors (likeOutOfMemoryError). Catching it prevents the environment from terminating when it absolutely needs to, leading to corrupted state and unpredictable behavior. -
Don't throw
Error: Thejava.lang.Error(orkotlin.Errorwhich is type-aliased for when running on the JVM) class represents serious, unrecoverable problems that an application should generally not attempt to catch. Unlike standard exceptions, these typically indicate failures at the Java Virtual Machine (JVM) level or catastrophic system conditions. UseIllegalStateExceptionor similar instead. -
Avoid catching generic
Exception: Catching all exceptions acts as a black hole for standard developer bugs (likeNullPointerExceptionorIllegalArgumentException). This makes debugging extremely difficult because the application fails silently. -
Catch specific exceptions: Scope your
try-catchblocks tightly and only catch the exact exceptions you anticipate and know how to recover from (e.g.,IOExceptionfor network calls, orJsExceptionfor JavaScript interop boundaries). -
Protect Coroutine Cancellation: If you absolutely must catch a broad
Exception(e.g., at a top-level boundary to prevent a crash), you must explicitly rethrowCancellationException. Failing to do so intercepts coroutine cancellation, breaking structured concurrency and causing memory leaks.catch (e: Exception) {
if (e is CancellationException) throw e
// Handle other exceptions safely
}
-
Avoid standard
runCatchingwith Coroutines: Kotlin's built-inrunCatching {}block catchesThrowableunder the hood. Do not use it around suspending functions unless you are using a custom wrapper that explicitly handlesCancellationException. -
Wrap
suspendcalls infinallyblocks: When a coroutine is cancelled, it throws aCancellationException. If you need to execute suspending cleanup code (like closing a connection or releasing a lock) inside afinallyblock, the coroutine is already in a cancelled state, and any standardsuspendcall will immediately fail. You must wrap the cleanup code inwithContext(NonCancellable).finally {
withContext(NonCancellable) {
// Suspending cleanup code goes here
}
} -
Document exceptions in KDoc: Every function or method must explicitly document the exceptions it throws using the
@throws(or@exception) tag in its KDoc. This ensures that contributors and consumers of the Multipaz library know exactly what edge cases they are expected to handle.