Hi all!
I’m here to write some feedback about using Kotlin with coroutines in production and also share some general thoughts about Kotlin.
First of all, coroutines are awesome. I haven’t encountered this feature in mainstream languages before, and seeing it implemented in Kotlin, implemented so well at that, is very exciting. I spent the last month working on two projects where I decided to introduce coroutines. One was a Vert.x-based server, used for webservices. The other was an Android project. (I can’t disclose more details of the projects at this time.) Having coroutines around really changed the way I write code, and I think that’s the best compliment I can pay it. I was even able to make it work like charm for a person with little Java - let alone Kotlin - knowledge, and she commented she liked working with Kotlin and coroutines a lot.
I did encounter some issues on the way with the most recent version of Kotlin, Coroutines, IntelliJ and Android Studio. Here’s hoping they can be resolved in future.
- IDE problems:
a) from time to time updates I made to the code in IntelliJ were not picked up and I had to perform a full rebuild
b) Noticed a lot of problems in the debugger and with stack traces. Sometimes the reported line is beyond the end of the file. There were times when the debugger continued running when I told it to step over, and I had to place a breakpoint on the next line. - Compiler problems: I had two separate issues with the Android project. Once, a VerifierError was thrown (even after rebuild), saying the verifier rejected a file. Thankfully, I changed the code structure a bit, and the error was gone. The other time, the code failed at runtime with some cryptic error mentioning some kind of invalid state. It started happening after I changed async{} into async{}.await(), so I rolled back that change, and it was gone. Fortunately, I didn’t really need await on that occurrence, but the issue does worry me quite a bit. I had the presense of mind to save a stack trace. Both times the issue kept reoccurring after a full rebuild.
- I’m being bombarded non-stop by all kinds of IDE errors, the red indicator won’t stop blinking. Sometimes the IDE brings up a pop-up dialog, asking me whether I want to disable the Kotlin plugin. Quite annoying.
- The code is significantly harder to debug because stack traces don’t show the full logical flow, they start somewhere very close to the point you’re looking at.
- I found it challenging to catch all errors. In Android, any exception that reaches the event loop (or looper, or whatever they call it in Android) crashes the app. So you really don’t want that to happen. And one problem with coroutines is that they make the number of such entry points that need to be protected with a catch-all clause much greater. Every time you launch() a coroutine (at least on the UI thread) or async() without await() or join(), you need to catch its exceptions.
- I often found myself trying to call a suspend function and failing because I wasn’t currently in couroutine context. In Android it was particularly bad, because there is so much inconsistency. Even inside Anko, which I was using for onClick, etc, there is a large discrepancy - it doesn’t consistently provide you with onXYZ for all XYZ, some events are only available in non-suspend variant, and so it’s harder to use them with coroutines. I know I can always start a new coroutine context, but, as explained above, I’d rather not do it without a good reason.
- Yeah, and I had to disable Instant Run for Android. Not sure it’s related to coroutines, but there are not many hits on Google with the symptoms, which are: the build process attempts to do partial APK uploads and fails. If I run the same command that uploads the APK part, it fails again, so it must be the partial APK is compiled incorrectly.
Other than that, it works great! I will definitely keep using coroutines in my future projects even despite these issues.
Finally, since I’m not likely to write another post for a while, I’d like to also bring to attention one other thing I’ve been thinking about for a while. There are two great languages I happen to follow right now: Kotlin and Rust. And comparing the two, I can’t help wondering how come Rust has such a great, active community, while Kotlin seems to be entirely JetBrains-driven? This isn’t right. Kotlin can be as exciting for an aspiring compiler developer as Rust. So I guess it has something to do with the maintainer’s policies. Mozilla welcomes all external participation and works hard specifically to reach out to everyone interested. The entire development process is completely open to anyone who cares. JetBrains… I don’t even know. Is there anything going on other than official presentations? And it’s not like external participation isn’t needed. I see a lot of great initiative from JetBrains in all directions at the same time. Do you really have the human power and money to do all that? My impression is that actually many of these projects (like Anko) are understaffed and release slowly and without ambition. My 2 cents.