I have been developing in Dart for a few months now. To be honest at first it felt like a step backward coming from Kotlin, but I must say I am impressed with how fast the language is improving and is looking more and more modern! And I am looking forward to using null safety in production as it is the feature I miss the most in Dart for now!
But there are still a few other things I miss from Kotlin…
I am not a Dart senior developer, this is my feedback after a few months with the language. Please let me know if I am wrong about anything in this article!
1. Control flow expressions
when are expressions, meaning they return a value. In Dart they do not. So instead we have two solutions:
- Return the result from inside the
switchblock. This is not ideal as we may want to avoid multiple exit points in a function (harder to debug, spaghetti code, risk of skipping statements declared later, etc.).
- Assign an intermediate variable inside the
switchblock, and return it at the end. Again, not ideal because we are introducing a mutable state in the function. Even if in this example it is pretty simple, as a general rule we want to avoid mutable states as they can be hard to maintain, and lead to side effects and errors. This is why modern UI frameworks — like Flutter, Jetpack Compose or SwiftUI — has immutable*, declarative syntax instead of imperative syntax.
Dart comes with the ternary operator that can lead to a similar result:
However most of the time the formatter is not going to respect the above line breaks and indentation, it can lead to something quite difficult to read. Please tell me if you found a way to properly format nested ternary operators.
In Kotlin, we can build a list that does not contain any possible null element. And that is guaranteed by the compiler, so we do not need to null check after that. In Dart we must filter the list by ourself, and even then the compiler does not guarantee that the elements are not null.
However, I suspect this could change with Dart Null Safety that is about to be release, so stay tuned.
Note: Dart recently introduced collection if that has the same effect as Kotlin’s
Oh, by the way, did you notice the syntax for lambda functions? Not a big deal but in Kotlin, the implicit
it parameter and the trailing lambda outside the parentheses really helps with the readability.
3. Scope functions
Kotlin scope functions are still a source of misunderstanding and contention as they can make the code less readable if incorrectly used. But personally I love them! Dart provides the cascade operator that is similar to the
apply function, but I sometimes miss Kotlin’s
As shown in the above example, it can be a bit more verbose in Dart. With a more complex example, the best solution would probably be to move
color out of the constructor, leading to two additional variables and a more verbose code.
4. Immutable Lists
In order to respect the principle of immutability* and avoid side effects, we should avoid mutable lists. Unfortunately in Dart the collection literals create mutable collections. We have to wrap them with
List.unmodifiable but Dart does not provide immutable functions to add or remove items, so it is more cumbersome than in Kotlin.
As usual, the reason is immutability*. In order to avoid modifying a state (i.e. variables), I like to copy my objects with the updated data. As shown above, this is possible in Dart but it adds a lot of boilerplate (even if there are packages for it), while Kotlin has a native
There are plenty of other tricks I love in Kotlin, that really make the language concise and easy to read. The functional features of the language also makes it less error prone, and Dart still lacks a bit in that regard. But I feel like the Dart team is going into the right direction and I have no doubt that they will bring more and more of these features in a near future. Meanwhile I encourage you to check the Dart cheatsheet where you can find great tips about the language!
* About state and immutability
I think I made it clear that I love Kotlin for the features it provides to help maintaining immutability. Maybe some of you are wondering why it is so important to me, and how a mutable code can be so evil. Mutable means side effect, and the more side effects, the more we have to anticipate them and the more we are likely to forget they exist. If you want a quick and simple, very well explained example, I urge you to read this article: https://pasztor.at/blog/why-immutability-matters/.