CHAPTER 1
Kotlin - Powerful and Pragmatic
This chapter is meant to explain the major features which make Kotlin an excellent and efficient language for modern application development and the reasons why you might want to learn it. Weâll learn the basic ideas which stand behind the Kotlin design and get an overview of Kotlin libraries and frameworks for different application areas such as Android applications, concurrency, testing and web development. In conclusion, weâll guide you through the steps required to set up a Kotlin project in two popular development environments, IntelliJ IDEA and Eclipse, and introduce you to the interactive Kotlin shell.
Structure
We will cover the following topics:
- What is Kotlin?
- Major components of the Kotlin ecosystem
- Setting up a Kotlin project in IDE and online editors
Objectives
At the end of the chapter, youâll get an understanding of the basic Kotlin principles and the Kotlin ecosystem as well as what simple a Kotlin program looks like and you will be able to set up a project in common IDEs.
What is Kotlin?
Kotlin is a multiplatform and multiparadigm programming language emphasizing safety, conciseness, and interoperability. Conceived in late 2010, it had reached its first release in February 2016 and has been steadily becoming an increasingly popular and promising tool in many development areas such as Android development, desktop applications, or server-side solutions. The company which stands behind the language and has been investing in its development ever since is JetBrains which is famous for its excellent software engineering tools such as IntelliJ IDEA. By August 2020, Kotlin had reached version 1.4, acquiring massive community, well-developed ecosystems, and extensive tooling. Having overgrown an original intent of creating a better Java alternative, it now embraces multiple platforms, including Java Virtual Machine, Android, JavaScript, and native applications. In 2017, Google announced Kotlin an officially supported language of the Android platform which gave a tremendous boost to the language popularity. Nowadays, a lot of companies â among them Google, Amazon, Netflix, Pinterest, Uber, and many others â are using Koltin for production development, and the number of open positions for Kotlin developers is growing steadfast.
It all became possible thanks to the efforts devoted to the careful language design and putting into action the primary traits which make Kotlin such an excellent development tool. The language philosophy has mainly arisen based on the problems it was intended to solve back in 2010. By that time, JetBrains had already accumulated an extensive Java code base for products centered around its IntelliJ platform which was arguably the most known IntelliJ IDEA, had also included a set of minor IDEs dedicated to different technologies such as WebStorm, PhpStorm, RubyMine, etc. The maintenance and growth of such codebase, however, was being hampered by Java itself due to its slow evolution and lack of many useful features which at that moment had already been available in such languages as Scala and C#. Having researched the JVM languages available at that moment, the company concluded that no existing language proved satisfiable for their needs and decided to invest resources into implementation of their own language. The new language was eventually named Kotlin as a tribute to an island near Saint-Peteresburg, Russia where most of its development team was located.
So what are those traits which have been shaping the language from the very beginning? In fact, weâve already given the answer in its definition. The reason behind Kotlin is a need for a multiparadigm language emphasizing safety, conciseness, and interoperability. Letâs look at these traits in more detail.
Safe
For a programming language, being safe means being able to prevent a programmerâs errors. In practice, designing the language with respect to safety is a matter of tradeoff since error prevention typically comes at a cost. You give the compiler more detailed information about your program or allow it to spend more time reasoning about it correctness (probably both). One of Kotlin design goals was to find a sort of golden mean; contriving a language with more stronger safety guarantees than Java, but not so strong to frustrate a developerâs productivity. And although the Kotlin solution is by no means absolute, it has repeatedly proved to be an efficient choice in practice.
Weâll discuss various aspects of Kotlin safety as we go through the book. Here, weâd like to point out some major features:
- Type inference which allows the developer to omit explicit declaration types in most cases (Java 10 introduced this for local variables)
- Nullable types regulate the usage of null and help to prevent infamous NullPointerException
- Smart casts which simplify type casting reducing the chance of casting errors at runtime
Multiparadigm
Initially, the meaning behind Kotlin multiparadigmality implied the support of functional programming in addition to the conventional object-oriented paradigm typical for many mainstream programming languages such as Java. The functional programming is based around the idea of using functions as values: passing them as parameters or returning from other functions, declaring locally, storing in variables, etc. Another aspect of the functional paradigm is an idea of immutability which means that objects you manipulate canât change their state once created and functions canât produce side effects.
The major benefit of this approach is improved programming flexibility. Being able to create a new kind of abstraction, you can write more expressive and concise code, thus increasing your productivity. Note that although functional programming principles can be employed in many languages (Javaâs anonymous classes, for example, were an obvious choice before introduction of lambdas), not every language has necessary syntactic facilities encouraging the writing of such code. Kotlin, on the contrary, included necessary features right from the start. They include, in particular, functional types smoothly integrating functions into the language type systems and lambda expressions meant to create functionally-typed values from code blocks. The standard library as well as external frameworks provides an extensive API facilitating the functional style. Nowadays, many of that also apply to Java which had introduced functional programming support starting with Java 8. But its expressiveness still somewhat falls behind Kotlinâs.
Weâll cover the basics of functional programming in Chapter 5, Leveraging Advanced Functions and Functional Programming, but its applications and examples will accompany us throughout the book.
Over its growth, the language also began to exhibit two more programming paradigms. Thanks to the ability to design APIs in the form of domain-specific languages (DSLs) Kotlin can be used in a declarative style. In fact, many Kotlin frameworks provide their own DSLs for specific tasks with no need to sacrifice type-safety or expressive power of the general-purpose programming language. For example, the exposed framework includes a DSL for defining database schema and manipulating its data, whereas kotlinx.html gives a concise and type-safe alternative to HTML template languages. In Chapter 11, Domain-Specific Languages, weâll discuss these examples in more detail as well as learn how to create our own DSLs.
One more paradigm, namely, concurrent programming, entered the language with the introduction of coroutines. Although, concurrency support by itself is present in many languages, including Java, the Kotlin features a rich set of programming patterns which enable a new programming approach. Weâll cover the basics of this approach in Chapter 13, Concurrency.
All in all, the presence of multiple paradigms greatly increases the languageâs expressive power, making it a more flexible and multi-purposed tool.
Concise and expressive
Developer productivity is largely tied with the ability to quickly read and understand the code, be it some other developerâs work or maybe your own after a significant time has passed. In order to understand what a specific piece of code does, you need to also understand how itâs related to other parts of your program. Thatâs why reading the existing code generally takes more time than writing a new one and thatâs why language conciseness and the ability to clearly express a programmerâs intents without much information noise is a crucial aspect of language efficiency as a development tool.
The designers of Kotlin did their best to make language as concise as possible, eliminating a lot of notorious Java boilerplate such as field getters and setters, anonymous classes, explicit delegation, and so on. On the other hand, they made sure the conciseness is not overtly abused â unlike Scala; for example, Kotlin doesnât allow the programmer to define custom operators, but only redefine existing ones since the former tends to obfuscate the operation meaning. In the course of the book, weâll see numerous implications of this decision and how useful it turned to be.
Another aspect of Kotlinâs conciseness is tightly related to the DSLs (see Chapter 11, Domain-Specific Languages which greatly simplify the description of specific programming domains with a minimum of syntactic noise.
Interoperable
Java interoperability was a major point in Kotlin design since the Kotlin code wasnât mean to exist in isolation, but to cooperate as smoothly as possible...