If I had a nickel for every time I got excited about something with experimental multiplatform support...
The Kotlin platform looks good and I've kept an eye on it, but the problem is, if I have to start working on an app now, it's still kind of scary, as you're basically just placing a bet on a horse race of which one will mature the fastest down the road.
At a previous job, I decided to adopt React Native in its early stages for a project. By some miracle (and with a lot of rolling-our-own) it managed to not hold us back and seemed to mature about as fast as we needed it to, but boy, even then it was still stressful, and I feel like we got a little lucky. (Just to be clear, I also knew this going into it and the choice was mine, I may just have a deathwish)
Take a look at skip.tools. It's pure SwiftUI on iOS and Jetpack Compose on Android, with the tool automatically handling the translation from Swift to Kotlin as part of the Xcode build process.
We had a Kotlin app written with view bindings and the various other bits and pieces of Android app stack “no now this thing” detritus over the years. I hated it. I cut my teeth on 20 years of smalltalk, so it wasn’t even the “let’s hate on OO now” thing. It was just so much unfinished/inconstant things.
We have been porting to Jetpack Compose, and I really like it. It’s still got some growing pains. We don’t use ViewModels, hardly any Flow stuff, just mutable states and render trees and I’ve been pretty pleased. What makes me happiest is that it’s much more consistent. I don’t feel like I’m in a line at the DMV anymore; “oh you need that, go stand in that line and learn that stack, then come back”.
Like you, I’m extremely skeptical about the multiplatform siren. We tried it in Smalltalk land. The Java guys tried it and failed. I tried Flutter for a couple of apps, early testing iOS users were totally turned off (so fine for internal simple utility apps only). I would love it if someone really succeeded. We have 2 Swift UIKit apps I’ll have to convert to SwiftUI someday. So I will wish all that try well, but I’m not holding my breath at all.
Having a “write once run everywhere” pitch is about the same as politicians who run on “change”. It always sells; it never really delivers.
The first two paragraphs has been my experience on Android too. Android Framework is an incredibly disjointed mess that leaves you neck-deep in half-baked APIs.
Compose is better for sure. I’m still figuring it all out but it’s a marked improvement.
Kotlin is probably the most similar in syntax to Swift out of the languages I’ve written, but it’s somewhat quirky and opinionated and I’m not sure I agree with its opinions (lack of guard statement, no ternary ifs, etc). Also it involves Java ecosystem stuff like Gradle which can drive a person mad sometimes.
My dealbreaker for kotlin is that it’s possible to call a throwing function with no indication it will throw. In swift, the compiler forces every throwing function do be inside a try/catch block or be called by another throwing function.
I also am extremely unhappy that those functions can be 16 layers deep somewhere in a lib and cause your app to blowup.
Yep, this is a problem I’ve encountered several times. Even if none of your own code has unhandled throws, you’ll inevitably get crash reports coming in from fooLib throwing an exception somewhere because the moon was in the wrong phase.
There are entire languages built with unchecked exceptions, Python, Ruby, Nodejs and most recent ones. Even with checked exceptions you can write code and miss to throw or declare an exception somewhere so ultimately the developer has to deal with exceptions somehow.
>Also it involves Java ecosystem stuff like Gradle which can drive a person mad sometimes.
Interesting. Why is that? I've been out of the Java loop for some years (although I did a fair amount of work with it earlier), so not up to date with this stuff.
I will never pass up an opportunity to heap scorn on Gradle. I agree with everything said so far, except I would argue Ant was easier to use.
Every single Gradle build system I have encountered in the wilds of GitHub has been broken on Fedora. I eventually realised it works if I run it in an Ubuntu container (using "toolbox"). So it's only portable if you bundle up the OS with your build system.
Now it should be portable. It's written in a JVM language and every Gradle project I have seen commits a copy of the Gradle JAR to its GitHub repo, which gives me those arbitrary code execution heebie-jeebies.
1. Every single gradle script is a unique snowflake of mishmashed plugins and custom functions
2. Gradle likes to pretend it is declarative, but as people very quickly learn it really isn't.
3. The one thing a build system is expected to do is be reliable in face of changing platform version, libraries and plugins. But gradle, being built on top a language on top of JDK itself has a Compatibility Matrix[0] that one has to be aware of. Often when upgrading a project you have to update JDK and gradle in explicit order, sometimes multiple times.
4. Speaking of which, did you know that gradle, being designed to build java projects does not even manage multiple JDK versions?!
5. untyped groovy means you're forever left wondering whether what you wrote is actually correct until you run it, at which point it fails with excellent errors that tell you nothing. Granted, this situation has improved in recent days, but a jump from 90th floor compared to 100th is still painful.
6. Every single fkin thing that gradle offers can be done in half dozen ways and nothing tells you which way is better or why. Ex.A: is it providedCompile or implementation? Yes, one is intended to be a replacement for another, and no, they are /not/ same.
7. The 'One Nice Thing' gradle had going for is that it bootstraps itself. But look, if want to add gradle to a 'new' project, you have to install it to your system first and use it to add the wrapper. But after that, you are expected to use the wrapper. Nobody tells you that, you just have to figure it out. Oh and when it comes time to upgrade the wrapper version, you're to use the wrapper itself, not the system gradle, again mentioned nowhere, and if you try updating the wrapper using system gradle, the error helps exactly not.
8. Gradle takes free reign in breaking APIs /between minor versions/. WTF!
9. gradle starts a daemon to cache stuff, which is nice I guess. Except when you don't want it to run a daemon, so you tell it with `--no-daemon`. Do you know what that does? It starts a daemon, runs the build and shuts it down. This may not sound like a big deal, but it is just cherry on top of this shitcacke that tells you just how thoughtfully and well designed gradle is. /s
Http4k, a http library for Kotlin, has an, in my opinion, great way of generating documentation for you [0]. They explain it in more detail in their talk [1] and also have an example repository [2], if you favor to look at code.
I'm doing exactly the same. Another added benefit of that is that you save some length in the test name, which can be quite helpful in certain scenarios.