I keep reading a lot of posts about what features need to be added to the language to make it better and I feel a bit of an odd man out. I find Kotlin has plenty of features already that make it better and I love writing Kotlin code but lately find myself avoiding writing new code in Kotlin and it has nothing to do with the language.
It is a palpable psychological resistance. Yet every time I work with existing Kotlin code, of which I have tons, I keep telling myself that I should use it more. It is just beautifully elegant and expressive. This schism has bothered me for a while.
Today I am spending hours working on Kotlin code and I figured out why I don’t want to write more Kotlin, especially new code.
Kotlin support in IDEA lags far behind Java when it comes to refactoring, formatting and other creature comforts.
I find myself constantly deleting extra blank lines because Kotlin does not have code style options to remove blank lines before } or limit number of blank lines in the code.
That may seem like not much but when writing new code it is a constant distraction. Enough for me to consider adding these features to the Kotlin plugin myself.
Kotlin refactoring is lagging quite behind Java. When writing new code it is a factor because refactoring saves a lot of time massaging new code into maturity. It is understandable that Java has a lot more resources tasked to its support but the difference is enough to tip the scales when writing a lot of new code that will be refactored many times before stabilizing.
Kotlin has some asymmetric refactoring features, you can split ifs but not merge ifs, for example. This too is an annoyance because suddenly you have to “get out and walk instead of fly”.
Last and most significant is the debugging idiosyncrasies and what looks like bugs:
On many occasions break points inside Kotlin lambdas are ignored unless you single step into them. The only way to get around it is to put the code of the lambda into a method and set the break point in the method. This means passing all the local context as arguments, a real PITA issue.
Sometimes the debugger cannot find local variables when evaluating expressions. They show up in the variables pane but trying to use it in expression evaluation gives an error that local variable is not found.
Smart casts are not taken into account from the execution point in the code when evaluating variables. If it is only nullability then !! can be used but if it is a class smart cast then you have to write the cast again. You also have to figure out why the expression is invalid, that too is not obvious because you take smart casts for granted in your code. A perfect example of a beautiful feature of Kotlin messed up by lack of support in the IDE.
The language is highly efficient and elegant but working with it while creating new code is less than enjoyable because of all the hiccups and glitches in the IDE.
At least now I know why I hesitate to write new code in Kotlin: refactoring is not as smooth, formatting is lacking, debugging is a pain. All small annoyances but as you start turning compilable code into working code they quickly wither away what you gained using a more elegant and expressive Kotlin language.
Thanks for your feedback! Could you please file specific issues for the missing features in refactorings and intentions that you encounter? We’re constantly extending the functionality, but without specific feedback it’s impossible to know whether we’re addressing your pain points or working on something unrelated.
@yole, what you are saying makes perfect sense and in theory it is a good approach but it takes a long time and significant effort to report every issue and write up feature requests, time and effort which are not always available.
I can only justify it in cases where I am reasonably sure that there is a point at which it will result in a solution. Otherwise, it is a waste of my time writing it and the support team reading it.
Sometimes it is more efficient to find a workaround or just convert the problem implementation back to Java to get the job done. Which I have done on a few occasions.
I will make a list as I work with Kotlin of refactoring features that are a staple in Java but missing in Kotlin.
I will try to find a minimal case where the debugger refuses to stop on a break point set in a lambda body. I had that happen enough times that as soon as I encounter it now, I just rewrite the lambda as a method call so I can continue debugging. I never had this happen in Java lambdas.
I think that evolving Kotlin as a language is a good thing but Kotlin’s real competitor is Java, with full frontal support of IDEA Ultimate. Not Scala nor F# nor any of the other languages mentioned by dreamers and wishful thinkers, nor lack of any language feature. At this point Kotlin already beats Java in this category, with both hands tied behind its back.
If working with Java mitigated by IDEA makes Java more efficient, as crude as its syntax and bloated with boiler plate constructs as it is, then Kotlin will remain a beautifully elegant and expressive language that is better than Java. That and a $1 will get us a cup of coffee.
I hope to see Kotlin get over the growing pains. I really love reading and writing Kotlin and would love to feel justified in and excited about developing new code with it once again.
I also find running in compiler bugs frustrating. I recently ran into these two:
It does not happen often as I tend to use very simple code for the bulk of the application logic, but it really does break the flow you are in. I can imagine that other users who regularly push Kotlin to its limits, will get very frustrated.
I think that most of the current Kotlin users are willing to put of with the quirks, but for @vladimir_schneider it has already proven to be too much of a burden. For Kotlin to become a mainstream language, you have to be able to rely on it. Organizations with larger teams are usually very wary of platforms with over 1,800 open bugs: https://youtrack.jetbrains.com/issues/KT?p=1800&q=type:%20bug%20state:%20Open&f=false
I do not believe that freezing all new development around Kotlin until its IntelliJ IDEA plugin reaches feature parity with IntelliJ IDEA’s Java support (which would be required to match the definition of “working perfectly”) would be in the best interests of the Kotlin user community, and it would definitely not be in the best interests of JetBrains. As every large project, Kotlin has bugs, and as every team working on such a project, we’re balancing our priorities between bugfixing and new development. If you look at the release notes of each 1.0.x build, you’ll see that we’re releasing a steady flow of bugfixes to all areas of our toolchain, including the compiler, the IDE and all other areas, and we plan to continue doing so in the future.
Kotlin Native is a separate effort led by a separate team, which JetBrains has made a business decision to invest in. Asking us to move those developers over to work on the compiler bugfixes makes little more sense than asking us to move the developers of the Scala plugin or ReSharper to help out with Kotlin.
And of course, pointing to a list of open bugs across lots of different areas of a product doesn’t say much about anything. Scala’s issue tracker has 1937 open issues right now, and this number doesn’t include the IDE plugins, Gradle/Maven integration or any other non-compiler subsystems tracked in the Kotlin issue tracker. Does that mean that people should be more way of Scala than of Kotlin? Of course not.
I might have exaggerated a bit when using working perfectly
JetBrains has better insight into what is wanted by the Kotlin community than I do, so I understand that their interests can conflict with mine. I only hope that sharing our experiences and frustrations here gives JetBrains even more insight into what is happening around Kotlin.
Remember that we do this not to criticize your great work, but to help you understand our concerns. We are enthusiasts that really want Kotlin to succeed. There are many other languages out there, and people tend to switch quickly once they become dissatisfied. And most of them switch without providing this kind of feedback.
Indeed, a more in-depth look at a bug list is needed to understand the actual state of things. How many people do you know that take the time to do that? I haven’t. It is already hard for people to introduce Kotlin to their teams. A long list of open bugs can easily be used to dismiss a switch to Kotlin.
We really appreciate sharing your concerns and letting us know specific problems that affect you when you use Kotlin. This helps us prioritize our work.
We’re monitoring the discussions where people share their opinions why they don’t or can’t switch to Kotlin, and so far we haven’t seen the number of open bugs in our tracker mentioned as a major concern. There are specific areas, primarily related to the Android toolchain integration, which are causing people pain, and we’re trying to address them as quickly as we can, but this is not directly related to the number of open bugs in the tracker.
@vladimir_schneider - One of the reasons cited for doing Kotlin is to have a language that is also as quick to parse and develop with as Java (the language wrt IDE features should not be significantly slower than Java). I am referring specially here to the speed at which the IDE is able to parse, process and do its “intellisense”/suggestions. I definitely - with the naked eye (with Kotlin being slower) can see differences between the Java speed in the IDE and Kotlin using the same general settings. (I recall this directive very clearly - but did not make a copy of the statement)
If you do Scala within the IntelliJ idea one can understand the JetBrains guys’ motivation as Scala with its implicits and 10000 traits can be hectic - but why Kotlin feels slower with less functionality over Java is mystery to me - just to add to your point.
In JetBrains’ defense - with every new version of the plugin many a Java feature (that one is so used to that you forgot you were using it) is ported to Kotlin. So I guess it is a question of time more than anything else.
Agree with topicstarter. The most annoying thing for me when migrating from java to kotlin is lacking of features like this https://youtrack.jetbrains.com/issue/KT-9220
There is also inconvenience in class renaming refactoring. For example when you rename class A to class B, it only renames file name, but class still named as A, so i must to rename it manually.
If you have a file that contains a single class, then renaming the file will rename the class as well. If there are other declarations in the file, or multiple classes, then renaming the file will not rename the class. This behavior is by design.
Dmitry, sorry, my previous claim was slightly incorrect. The problem happens only when i copy&paste file with single class inside of it. For Example file A.kt contains A class. ctrl+c, ctrl+v on that file. Choose new name, for example B.kt, the resulting file will contain A class. Should i file a bug?
@yole, this is exactly what I was trying to point out. There are many non-glamorous features that affect productivity and your response confirms what I said about filing issues.
First, I would like to point out that there is another case Kotlin does not handle as smoothly as Java and it is copying a file by drag and drop. The file copy dialog does come up but the new file name is only applied by the IDE to the file. The class in the file has to be manually renamed. Again, not a big deal but does introduce a distraction that does not exist in Java.
The issue you are referring to also demonstrates what I said about reporting bugs or asking for features. The issue was opened 03 Sep 2015 04:47 but is a duplicate of an earlier one opened 19 Jun 2015 21:09
The fact that it is known does not address the fact that it is not resolved. The fact that it is over 18 months old says that these issues are not a priority. Then why bother asking for more requests if there is no plan to address them?
When issue age starts to span years I know not to waste my time reporting similar ones. I too have better things to do than spend time on low priority tasks.
In any large project with a public issue tracker, you can find an issue that is unresolved for X months, for almost any value of X, and use this as evidence that filing issues is useless (and, if you wish to continue, that the project doesn’t care about its users, that it’s doomed to fail, and so on and so forth). At the same time, there were many hundreds of other issues that were filed and successfully resolved during those X months, and the users who have filed them now enjoy improved productivity because the team has addressed their complaints.
It is true that we do not always prioritize issues in the best way possible. In this particular case, it’s my personal fault that I underestimated the need for the Copy Class refactoring in Kotlin and didn’t bump the priority of this task earlier, and I’m sorry for that. But once again: to correct this kind of mistakes, we need your feedback on specific pain points. If you find filing issues to be time-consuming, please at least vote for issues that are already there; this doesn’t take much time. General grumbling “Kotlin’s IDE support isn’t as good as Java” will not change the situation in any way.
@yole, I understand about issue prioritization and having to triage issues otherwise the team will bog down. It is the reality of having to live with the resources we have, not the resources we would like to have. I would like to thank you for being honest about having set lower priority on some of these issues. There is no need to apologize for being human, being honest about it is the best action that can be taken and you have done that already.
As far as grumbling about lack of Kotlin features is concerned, sometimes you are lucky to get that. Many users will vote with their feet without feedback. Listening to the shrill of excitement from devotees can be misleading. The devotees are willing to overlook any and all issues, creating a wrong impression of an average user experience.
I was a relatively early adopter of Kotlin for production code, in my plugin I used pre-release Kotlin and stuck with it because I find it a beautiful language. I don’t consider myself to be an expert in Kotlin nor do I care to push the language boundaries. I do have over 70k lines of Kotlin with over a year worth of production experience so don’t consider my experience to be based on impressions from short term, limited use.
I did not open this topic to bitch about Kotlin or trying to put you or the Kotlin team on the defensive. Quite the contrary. I want Kotlin to succeed. I was sharing my experience to bring to your attention to the mundane and boring features that most developers would not find exciting which are causing a significant impact on productivity in Kotlin vs Java, in contrast to topics here which focus on missing language features to make Kotlin even more expressive.
I don’t expect Kotlin support in the IDE to match Java for obvious business reasons. This is not to question JetBrains’ commitment to Kotlin but to accept the reality that Java has and will continue to have more resources allocated to it for quite a while if not forever.
However, the quality of Kotlin support in the IDE leaves better to be desired: exceptions, index corruption, inability to handle invalid Kotlin code as occurs regularly when code is being edited, refactoring deleting code if it results in incomplete or incorrect Kotlin instead of leaving incomplete code as is, should not be a regular occurrence when using Kotlin.
Your honesty goes a long way to help address the unspoken perception that no one cares about mundane “low priority” features in Kotlin.
I wanted to switch from Microsoft. I was using C# just because of Resharper and not bad VS. I would like to have a refactoring tool like Resharper for Kotlin.
All the refactoring tools implemented for Kotlin are available as part of the Kotlin plugin for IntelliJ IDEA. Why would you need a separate refactoring tool?
I was not clear enough. What I need is similar refactorings which Resharper has. Here’re the short list of what I often used:
Reorder method arguments
Add an argument to a method
Promote expression as an argument
Move static/nonstatic method
Extract an interface
All of these refactorings, except for “Move nonstatic method”, are supported in the current version of the Kotlin plugin for IntelliJ IDEA.
Well, that’s good. Thanks for your answer.