The appearance of Kotlin is an important bonus for developers. A high-level language that seamlessly integrates with Java greatly enhances the capabilities of programmers. However, in any language, we constantly encounter some troubles, which, on the contrary, create limitations, and Kotlin, of course, is no exception. We will talk about them today.

Kotlin was enthusiastically received by the community, as the new programming language greatly simplifies writing code, replacing Java with itself. This is especially noticeable on Android, where new versions of Java appear, to put it mildly, “with a creak”. Many devices are updated with large delays, even more - do not receive firmware updates at all. At best, the support of the device ends approximately 2 years after its release, which promises one, maximum two system updates. However, people continue to use devices, which means that developers have to focus on (as yet) the latest Android 8, and on Android 5, or even earlier versions, where there is definitely not only the latest, but even the current implementation of Java. For reference, now the total share of Android 7 and 8 - those versions where there is Java 8 support from the system libraries - is 42.9%, all the rest is Java 7.
Some might say that Java is outdated. But there is also an opinion that Java is a language that is “as is” good and should not be touched. It is like the gcd (the greatest common divisor) in mathematics. It contains a gentlemanly set of functions, and for those who need additional features, special languages ​​are already available that work on top of the JVM. There are already quite a lot of these languages: Scala, Clojure, JRuby, Jython, Groovy and others, less known. However, Kotlin has a number of advantages. This language leaves more freedom to the programmer: it allows you to simultaneously use ready-made fragments in Java, combining old and new code.
')
But with all the advantages of the new language, which we do not in any way dispute, in the development process there were some minuses in it. And today it would be interesting to hear the opinion of colleagues about whether they interfere with work the same way as us.
Hide can not be shown?
Packages, as usual, are a fairly common way to organize classes by namespace. But their plus is not only in this; in Java, they also act as a means to limit the visibility of classes and their members.
Let me remind you that in Java there are 4 different categories that allow you to distinguish between visibility. For classes there are only two - they are visible either within the package (package private), or fully open (public). But the method or field can already be made private (it will not be available outside the class), visible only to the package (package private), it can be made so that the method is additionally visible to its heirs, both in its package and outside the package (protected), and it can also be made visible to all (public).
In Java 9, it became possible to break code into modules, and now it is possible to make some of the code visible everywhere inside the module, but not from the outside. And it turns out to be very useful for building a sensible API.
In short, there are more than enough options in Java. But for some reason, Kotlin limited itself to introducing public and private visibility, as well as visibility for the heirs. In addition, however, they introduced a distinction between modules, but it became impossible to differentiate access to methods and classes by packages. A module is no longer a construction of the language itself, and quite often people understand this term as quite different things. Kotlin officially defines the module as a "
set of Kotlin files compiled together ."
The hitch consists that the module, as a rule, leads to additional expenses of resources. At the same time, if you create a separate package and put classes with functions that are visible only in this package, there are no problems, because all packages will be compiled together and no additional resources will be required.
This is especially pronounced if, for example, to collect projects in Gradle, as usual, Android applications are collected. Modules tend to be relatively large, so that they represent a complete functional unit. Within one module, a method cannot be made visible to one and not visible to other classes. And if we want to make the visibility of methods more granular, a problem arises.
Here I immediately want to remember about the packages, because in Kotlin this entity has not disappeared anywhere, but, alas, it does not affect the visibility. Of course, you can always make more modules, but, given the characteristics of Gradle, this is simply irrational: the assembly speed will decrease. Yes, it is possible to put classes in one file, but in the case of a large project, the file will become really “heavy”. Therefore, I would like to get some other method of hiding methods, for example, following the Java model.
Do not process it ... even if it is necessary
The second is rather controversial (because some consider their use as a mauveton), but nevertheless a minus is the lack of checked exceptions. These tools are in Java, but Kotlin decided not to implement them. The
official documentation has an example about the Appendable interface. Strings can be attached to Appendable, and since strings can be connected to objects related to input / output, for example, when writing to a file or to a network, when you call interface methods, you can potentially get an IOException. And such cases make the use of checked exceptions inconvenient.
The creators of the language explain their argument as follows: if we use StringBuilder, accessing it via Appendable, we, it turns out, need to handle an IOException, even if you are sure that it cannot happen in principle:
Appendable log = new StringBuilder(); try { log.append(message); } catch (IOException e) {
The way out: the exception is “caught”, but they do not do anything with it, which, of course, is not good. However, the question arises: if we deliberately work with StringBuilder through the Appendable interface - why not to interact directly with StringBuilder? There is an important difference: when working with Appendable, if we don’t know which implementation it is under, the I / O exception really becomes possible, but StringBuilder will not produce it exactly, and the corresponding methods are declared in it, although they are implement the interface. So the example turns out to be rather strained ...
It is especially interesting that the authors of the documentation refer to chapter 77 in Effective Java, where it says that exceptions cannot be caught and ignored. But only in the next chapters it is written that checked exceptions can and should be used if we do it wisely. If you quote so selectively, you can justify any point of view.
As a result, the Kotlin developers made it so that, in effect, all methods could potentially throw some kind of exception. But then where are the tools for handling errors in the new language? How now to understand where the exception can appear? At the level of the language, alas, we do not find help in these matters, and even with the source code (which is not always available without taking into account various tweaks), it is difficult to understand what to do in each specific situation.
If you ask a question to the developers, they simply shrug their shoulders and say that
in other languages ​​there are no checked exceptions and nothing , they also create large and reliable programs. But they are successfully written in frankly unsuccessful languages, this is not an argument. On StackOverflow, a similar question is said that “
you need to read the documentation ” is a good answer, very convenient in such situations. Only here the documentation may not be, it may be incomplete or outdated - the compiler does not check it. Finally, you can never find the answer in it.
Yes, it is true that the presence of checked exceptions can lead to the creation of awkward APIs. When checking for exceptions is obviously unnecessary, so that the compiler is “satisfied”, you have to prescribe try ... catch and in fact just create a garbage code, because nothing is done when handling these exceptions. And the fact that in the functional code it is inconvenient to use them is also true. But after all, checked exceptions are only a tool that can be used competently in the same way, where it is needed.
It is not clear why the language took this opportunity, if Kotlin's philosophy is to trust more tools to the programmer (at least, it seemed to us), and if the author of the code can correctly spell out where any exceptions will be, why not believe him? To take the same overloaded operators that have been removed from Java, because they can lead to the appearance of API with unobvious actions - this was the protection of programmers from themselves. In contrast, Kotlin has the ability to overload operators and do many other things - so why aren’t there any checked exceptions? Have the creators done it because it was just not like in Java?
We are waiting for changes…
The maximum that we can rely on for Android is Java 7 or Java 8 (but with some limitations and qualifications), while Java 11 is on the way. Using Kotlin, programming on Android becomes much easier, the number of lines of text is reduced .
One can only hope that the developers will complement this very useful language with those features that for obvious reasons are absent today. Maybe in future versions there will be new tools for analyzing exceptions in the IDE, as well as new categories of privacy. But, apparently, this is the case in the best case of the distant future, since the developers of the language have not even voiced any promises.