Starting with Kotlin

I found Kotlin looking for a language native to the JVM that was as much as possible like Java (object oriented, statically typed, general purpose) but without the verbosity or legacy bad design decisions kept for backwards compatibility.

I was also looking for a language that included more functional features than Java. Although these exist in Java 8 already, the resulting code is still far more verbose than it needs to be. Consider for example how to write a list comprehension to transform a list of strings to uppercase strings in Python versus Java 8 and Kotlin. I didn't even include the list creation code in Java!
 //python  
 upper = [x.upper() for x in ["a","b","c"]]  
 //Java  
 List<String> upper = list.stream().map(String::toUpperCase).collect(Collectors.toList());  
 //Java, transform the list in place  
 list.replaceAll(String::toUpperCase);  
 //Kotlin  
 var upper = listOf("a", "b").map { it.toUpperCase() }  

The four most prominent languages that run natively on the JVM are: Scala, Clojure, Groovy and Kotlin.

Scala and Clojure are functional. More precisely, the latter is functional and the former should be written in a functional style. So I'm not considering them Java substitutes whenever I would otherwise have chosen Java.

While Kotlin is a relatively new language, its enthusiastic widespread adoption make it look likely to remain popular in the future.

Another reason why I was looking for a Java-like language was to leverage my existing knowledge as a Java developer rather than start from scratch with a new language.

Of the two remaining candidates: Groovy and Kotlin, it seems Groovy's popularity has regressed and a come back is unlikely.

My first impression with Kotlin was that it is much more than a concise Java and that one won't get to write idiomatic code without spending some time learning it. However a Java programmer can start writing substandard, non idiomatic but working code from almost the get-go.

Kotlin was created by Jetbrains, so, as expected, there is better support for Intellij IDEA than for Eclipse. At the time of writing there is a total of just one Kotlin plugin in Eclipse (for any plugin category).

Unfortunately there are no static code analyzer plugins in Eclipse yet, although there are some stand alone tools that I haven't tried. Hopefully there will be a plugin in the future as good as findbugs is for Java.

To get started I turned an existing Java project into a Java and Kotlin one right away. The interoperability between classes of both languages is seamless.

Here are the steps to do that for an existing Java maven project in Eclipse:
  1. Add the Kotlin plugin to Eclipse and restart.
  2. Add Kotlin nature to the Maven project.
  3. Adjust the project's configuration. Here is an example. It is probably not the only way to do it.

  4. findbugs-exclude.xml


       <Match>  
         <Source name="~.*\.kt" />  
       </Match>  
    

    pom.xml
         <repository>  
           <snapshots>  
             <enabled>false</enabled>  
           </snapshots>  
           <id>kotlin-bintray</id>  
           <name>Kotlin Bintray</name>  
           <url>http://dl.bintray.com/kotlin/kotlin-dev</url>  
         </repository>  
       </repositories>  
       <pluginRepositories>  
         <pluginRepository>  
           <id>kotlin-bintray</id>  
           <name>Kotlin Bintray</name>  
           <url>http://dl.bintray.com/kotlin/kotlin-dev</url>  
           <releases>  
             <enabled>true</enabled>  
           </releases>  
           <snapshots>  
             <enabled>false</enabled>  
           </snapshots>  
         </pluginRepository>  
       </pluginRepositories>  
    
         <dependency>  
           <groupId>org.jetbrains.kotlin</groupId>  
           <artifactId>kotlin-runtime</artifactId>  
           <version>${kotlin.version}</version>  
         </dependency>  
    
         <dependency>  
           <groupId>org.jetbrains.kotlin</groupId>  
           <artifactId>kotlin-stdlib</artifactId>  
           <version>${kotlin.version}</version>  
         </dependency>  
    
       <build>  
         <plugins>  
           <plugin>  
             <groupId>org.jetbrains.kotlin</groupId>  
             <artifactId>kotlin-maven-plugin</artifactId>  
             <version>${kotlin.version}</version>  
             <executions>  
               <execution>  
                 <id>compile</id>  
                 <phase>process-sources</phase>  
                 <goals>  
                   <goal>compile</goal>  
                 </goals>  
                 <configuration>  
                   <source>1.8</source>  
                   <target>1.8</target>  
                   <sourceDirs>  
                     <source>src/main/java</source>  
                     <source>src/main/kotlin</source>  
                     <source>src/main/resources</source>  
                   </sourceDirs>  
                 </configuration>  
               </execution>  
               <execution>  
                 <id>test-compile</id>  
                 <phase>process-test-sources</phase>  
                 <goals>  
                   <goal>test-compile</goal>  
                 </goals>  
                 <configuration>  
                   <sourceDirs>  
                     <source>src/test/java</source>  
                     <source>src/test/kotlin</source>  
                     <source>src/test/resources</source>  
                   </sourceDirs>  
                 </configuration>  
               </execution>  
             </executions>  
           </plugin>  
           <plugin>  
             <artifactId>maven-compiler-plugin</artifactId>  
             <version>3.6.1</version>  
             <configuration>  
               <source>1.8</source>  
               <target>1.8</target>  
             </configuration>  
           </plugin>  
           <plugin>  
             <groupId>org.codehaus.mojo</groupId>  
             <artifactId>findbugs-maven-plugin</artifactId>  
             <version>3.0.4</version>  
             <configuration>  
               <effort>Max</effort>  
               <threshold>Low</threshold>  
               <xmlOutput>true</xmlOutput>  
               <excludeFilterFile>findbugs-exclude.xml</excludeFilterFile>  
             </configuration>  
             <executions>  
               <execution>  
                 <phase>verify</phase>  
                 <goals>  
                   <goal>check</goal>  
                 </goals>  
               </execution>  
             </executions>  
           </plugin>  
         </plugins>  
       </build>  
    

  5. Create all extra folders "src/main/kotlin", etc. 
  6.  This is an important one: Make sure that the version of kotlin in your pom.xml file matches that of the plugin. You can find the Kotlin version of your plugin by simply making sure the plugin is up-to-date and then looking at the plugin source code, which is hosted on github, to see what version of the Kotlin compiler they use.
  7. Finally you can start converting some of your classes (or all of them, or write new ones).

    For simplicity, if you are a total beginner with Kotlin, start with a self-contained subset of simple POJO classes and start translating them to Kotlin manually. Don't bother with the automatic conversion tool, it won't help you learning in the process and you'll have to fix most of the code anyway in some cases.
When a class is converted to Kotlin, any Java users of that class change, except in some fringe cases like including the companion object in a call to static methods in interface in Kotlin 1.1.1

Learning the syntax, type inference, nullable, what's the Unit type, regular class vs data class and other low level bits is quite trivial.

I found the biggest hurdle in understanding the particularities of Kotlin classes: lack of packages, what is a module, difference between val and var, constructors, visibility, how to prevent having getters and setters, etc. It doesn't quite work the same as in Java.

One controversial design decision for some developers is the lack of the equivalent package, or default in Java, level visibility. While it's true that package visibility is easily broken, it still provides self-documenting value.

A possible fix for this is putting all package-intended level classes inside a single file which you can call however you want, irrespective of the name of the classes inside and use the private or protected keyword. Although you have to put several classes in the same file with this method, at least each class typically has much fewer lines of code than their Java version.

My first impression of Kotlin was very positive overall. The language is concise but not more concise than it needs to be (ie not at the cost of readability).

For example, irregular syntax makes for more compact code, but some cases like omitting curly braces for empty bodies or omitting the type when it is obvious from the value assigned, come so naturally that don't put a mental burden on the novice developer.

This is not the case in many other modern languages, especially functional ones, eg. Clojure, where even the standard way of doing things sometimes leads to writing hard to decipher expressions.

This balance between conciseness and readability is an aspect of Kotlin that a programming team with developers of all skill levels and the usual high turnover ratio should not overlook when looking to Kotlin as a language to adopt.

Comments