Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Kotlin Design Patterns and Best Practices
Kotlin Design Patterns and Best Practices

Kotlin Design Patterns and Best Practices: Build scalable applications using traditional, reactive, and concurrent design patterns in Kotlin , Second Edition

eBook
$31.99 $35.99
Paperback
$44.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Product feature icon AI Assistant (beta) to help accelerate your learning
OR
Modal Close icon
Payment Processing...
tick Completed

Billing Address

Table of content icon View table of contents Preview book icon Preview Book

Kotlin Design Patterns and Best Practices

Chapter 1: Getting Started with Kotlin

The bulk of this chapter will be dedicated to basic Kotlin syntax. It is important to be comfortable with a language before we start implementing any design patterns in it.

We'll also briefly discuss what problems design patterns solve and why you should use them in Kotlin. This will be helpful to those who are less familiar with the concept of design patterns. But even for experienced engineers, it may provide an interesting perspective.

This chapter doesn't aim to cover the entire language vocabulary but to get you familiar with some basic concepts and idioms. The following chapters will expose you to even more language features as they become relevant to the design patterns that we'll discuss.

In this chapter, we will cover the following main topics:

  • Basic language syntax and features
  • Understanding Kotlin code structure
  • Type system and null safety
  • Reviewing Kotlin data structures
  • Control flow
  • Working with text and loops
  • Classes and inheritance
  • Extension functions
  • Introduction to design patterns

By the end of this chapter, you'll have a knowledge of Kotlin's basics, which will be the foundation for the following chapters.

Technical requirements

To follow the instructions in this chapter, you'll need the following:

The code files for this chapter are available at https://github.com/PacktPublishing/Kotlin-Design-Patterns-and-Best-Practices/tree/main/Chapter01.

Basic language syntax and features

Whether you come from Java, C#, Scala, or any other statically typed programming language, you'll find Kotlin syntax quite familiar. This is not by coincidence but to make the transition to this new language as smooth as possible for those with previous experience in other languages. Besides that familiarity, Kotlin brings a vast amount of features, such as better type safety. As we move ahead, you'll notice that all of them are attempting to solve real-world problems. That pragmatic approach is remarkably consistent across the language. For example, one of the strongest benefits of Kotlin is complete Java interoperability. You can have Java and Kotlin classes alongside each other and freely use any library that is available in Java for a Kotlin project.

To summarize, the goals of the language are as follows:

  • Pragmatic: Makes things we do often easy to achieve
  • Readable: Keeps a balance between conciseness and clarity on what the code does
  • Easy to reuse: Supports adapting code to different situations
  • Safe: Makes it hard to write code that crashes
  • Interoperable: Allows the use of existing libraries and frameworks

This chapter will discuss how these goals are achieved.

Multi-paradigm language

Some of the major paradigms in programming languages are procedural, object-oriented, and functional paradigms.

Being pragmatic, Kotlin allows for any of these paradigms. It has classes and inheritance, coming from the object-oriented approach. It has higher-order functions from functional programming. You don't have to wrap everything in classes if you don't want to, though. Kotlin allows you to structure your entire code as just a set of procedures and structs if you need to. You will see how all these approaches come together, as different examples will combine different paradigms to solve the problems discussed.

Instead of covering all aspects of a topic from start to finish, we will be building the knowledge as we go.

Understanding Kotlin code structure

The first thing you'll need to do when you start programming in Kotlin is to create a new file. Kotlin's file extension is usually .kt.

Unlike Java, there's no strong relationship between the filename and class name. You can put as many public classes in your file as you want, as long as the classes are related to one another and your file doesn't grow too long to read.

Naming conventions

As a convention, if your file contains a single class, name your file the same as your class.

If your file contains more than one class, then the filename should describe the common purpose of those classes. Use Camel case when naming your files, as per the Kotlin coding conventions: https://kotlinlang.org/docs/coding-conventions.html.

The main file in your Kotlin project should usually be named Main.kt.

Packages

A package is a collection of files and classes that all share a similar purpose or domain. Packages are a convenient way to have all your classes and functions under the same namespace, and often in the same folder. That's the reason Kotlin, similar to many other languages, uses the notion of a package.

The package that the file belongs to is declared using a package keyword:

package me.soshin

Similar to placing classes in files, you can put any package in any directory or file, but if you're mixing Java and Kotlin, Kotlin files should follow Java package rules, as given at https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html.

In purely Kotlin projects, common package prefixes can be omitted from the folder structure. For example, if all your projects are under the me.soshin package, and part of your application deals with mortgages, you can place your files directly in the /mortgages folder and not in the /me/soshin/mortgages folder like Java requires.

There is no need to declare a package for your Main.kt file.

Comments

Going forward, we will be documenting parts of the code using Kotlin comments. Similar to many other programming languages, Kotlin uses // for a single-line comment and /* */ for multiline comments.

Comments are a useful way to provide more context both to other developers and to your future self. Now, let's write our first Kotlin program and discuss how Kotlin's guiding principles are applied to it.

Hello Kotlin

There's no book dedicated to a programming language that can avoid the ubiquitous Hello World example. We're certainly not going to challenge that honored tradition.

To begin learning how Kotlin works, let's put the following code in our Main.kt file and run it:

fun main() {
    println("Hello Kotlin")
}

When your run this example, for example by pressing the Run button in your IntelliJ IDEA, it simply outputs the following:

> Hello Kotlin

There are some interesting attributes in that piece of code in comparison to the following Java code that does exactly the same:

class Main {
    public static void main(String[] args) {
        System.out.println("Hello Java");
    }
}

Let's focus on those attributes in the next sections.

No wrapping class

In Java, C#, Scala, and many other languages, it's necessary to wrap every function in a class for it to become executable.

Kotlin, though, has the concept of package-level functions. If your function doesn't need to access properties of a class, you don't need to wrap it in a class. It's as simple as that.

We'll discuss package-level functions in more detail in the following chapters.

Important Note:

From here on, we'll use ellipsis notation (three dots) to indicate that some parts of the code were omitted to focus on the important bits. You can always find the full code examples at the GitHub link for this chapter.

No arguments

Arguments, supplied as an array of strings, are a way to configure your command-line application. In Java, you cannot have a runnable main() function that doesn't take this array of arguments:

public static void main(String[] args) { ... }

But in Kotlin, those are entirely optional.

No static modifier

Some languages use the static keyword to indicate that a function in a class can be executed without the need to instantiate the class. The main() function is one such example.

In Kotlin, there's no such limitation. If your function doesn't have any state, you can place it outside of a class, and there is no static keyword in Kotlin.

A less verbose print function

Instead of the verbose System.out.println method that outputs a string to the standard output, Kotlin provides us with an alias called println() that does exactly the same.

No semicolons

In Java, and many other languages, every statement or expression must be terminated with a semicolon, as shown in the following example:

System.out.println("Semicolon =>"); 

Kotlin is a pragmatic language. So, instead, it infers during compilation where it should put the semicolons:

println("No semicolons! =>")

Most of the time, you won't need to put semicolons in your code. They're considered optional.

This is an excellent example of how pragmatic and concise Kotlin is. It sheds lots of fluff and lets you focus on what's important.

Important Note:

You don't have to write your code in a file for simple snippets. You can also play with the language online: try https://play.kotlinlang.org/ or use a REPL and an interactive shell after installing Kotlin and running kotlinc.

Understanding types

Previously, we said that Kotlin is a type-safe language. Let's examine the Kotlin type system and compare it to what Java provides.

Important Note:

The Java examples are for familiarity and not to prove that Kotlin is superior to Java in any way.

Basic types

Some languages make a distinction between primitive types and objects. Taking Java as an example, there is the int type and Integer – the former being more memory-efficient and the latter more expressive by supporting a lack of value and having methods.

There is no such distinction in Kotlin. From a developer's perspective, all the types are the same.

But it doesn't mean that Kotlin is less efficient than Java in that aspect. The Kotlin compiler optimizes types. So, you don't need to worry about it much.

Most of the Kotlin types are named similarly to Java, the exceptions being Java's Integer being called Int and Java's void being called Unit.

It doesn't make much sense to list all the types, but here are some examples:

Table 1.1 - Kotlin types

Table 1.1 - Kotlin types

Type inference

Let's declare our first Kotlin variable by extracting the string from our Hello Kotlin example:

var greeting = "Hello Kotlin"
println(greeting)

Note that nowhere in our code is it stated that greeting is of the String type. Instead, the compiler decides what type of variable should be used. Unlike interpreted languages, such as JavaScript, Python, or Ruby, the type of variable is defined only once.

In Kotlin, this will produce an error:

var greeting = "Hello Kotlin"
greeting = 1 // <- Greeting is a String

If you'd like to define the type of variable explicitly, you may use the following notation:

var greeting: String = "Hello Kotlin"

Values

In Java, variables can be declared final. Final variables can be assigned only once and their reference is effectively immutable:

final String s = "Hi";
s = "Bye"; // Doesn't work

Kotlin urges us to use immutable data as much as possible. Immutable variables in Kotlin are called values and use the val keyword:

val greeting = "Hi"
greeting = "Bye"// Doesn't work, "Val cannot be reassigned"

Values are preferable over variables. Immutable data is easier to reason about, especially when writing concurrent code. We'll touch more on that in Chapter 5, Introducing Functional Programming.

Comparison and equality

We were taught very early in Java that comparing objects using == won't produce the expected results, since it tests for reference equality – whether two pointers are the same, and not whether two objects are equal.

Instead, in Java, we use equals() for objects and == to compare only primitives, which may cause some confusion.

JVM does integer caching and string interning to prevent that in some basic cases, so for the sake of the example, we'll use a large integer:

Integer a = 1000;
Integer b = 1000;
System.out.println(a == b);      // false
System.out.println(a.equals(b)); // true

This behavior is far from intuitive. Instead, Kotlin translates == to equals():

val a = 1000
val b = 1000
println(a == b)      // true
println(a.equals(b)) // true

If you do want to check for reference equality, use ===. This won't work for some of the basic types, though:

println(a === b) // Still true

We'll discuss referential equality more when we learn how to instantiate classes.

Declaring functions

In Java, every method must be wrapped by a class or interface, even if it doesn't rely on any information from it. You're probably familiar with many Util classes in Java that only have static methods, and their only purpose is to satisfy the language requirements and bundle those methods together.

We already mentioned earlier that in Kotlin, a function can be declared outside of a class. We've seen it with the main() function. The keyword to declare a function is fun. The argument type comes after the argument name, and not before:

fun greet(greeting: String) {
    println(greeting)
}

If you need to return a result, its type will come after the function declaration:

fun getGreeting(): String { 
    return "Hello, Kotlin!"
}

You can try this out yourself:

fun main() {
    greet(getGreeting())
}

If the function doesn't return anything, the return type can be omitted completely. There's no need to declare it as void, or its Kotlin counterpart, Unit.

When a function is very short and consists of just a single expression, such as our getGreeting() function, we can remove the return type and the curly brackets, and use a shorter notation:

fun getGreeting() = "Hello, Kotlin!"

Here, the Kotlin compiler will infer that we're returning a String type.

Unlike some scripting languages, the order in which functions are declared is not important. Your main function will have access to all the other functions in its scope, even if those are declared after it in the code file.

There are many other topics regarding function declarations, such as named arguments, default parameters, and variable numbers of arguments. We'll introduce them in the following chapters with relevant examples.

Important Note:

Many examples in this book assume that the code we provide is wrapped in the main function. If you don't see a signature of the function, it probably should be part of the main function. As an alternative, you can also run the examples in an IntelliJ scratch file.

Null safety

Probably the most notorious exception in the Java world is NullPointerException. The reason behind this exception is that every object in Java can be null. The code here shows us why this is a problem:

final String s = null;
System.out.println(s.length()); 
// Causes NullPointerException

It's not like Java didn't attempt to solve that problem, though. Since Java 8, there has been an Optional construct that represents a value that may not be there:

var optional = Optional.of("I'm not null");
if (optional.isPresent()) { 
    System.out.println(optional.get().length());
}

But it doesn't solve our problem. If our function receives Optional as an argument, we can still pass it a null value and crash the program at runtime:

void printLength(Optional<String> optional) {
    if (optional.isPresent()) { // <- Missing null check 
      here
        System.out.println(optional.get().length());
    }
}
printLength (null); // Crashes!

Kotlin checks for nulls during compile time:

val s: String = null // Won't compile

Let's take a look at the printLength() function written in Kotlin:

fun printLength(s: String) { 
    println(s.length)
}

Calling this function with null won't compile at all:

printLength(null) 
// Null cannot be a value of a non-null type String

If you specifically want your type to be able to receive nulls, you'll need to mark it as nullable using the question mark:

fun printLength(stringOrNull: String?) { ... }

There are multiple techniques in Kotlin for dealing with nulls, such as smart casts, the Elvis operator, and so on. We'll discuss alternatives to nulls in Chapter 4, Getting Familiar with Behavioral Patterns. Let's now move on to data structures in Kotlin.

Reviewing Kotlin data structures

There are three important groups of data structures we should get familiar with in Kotlin: lists, sets, and maps. We'll cover each briefly, then discuss some other topics related to data structures, such as mutability and tuples.

Lists

A list represents an ordered collection of elements of the same type. To declare a list in Kotlin, we use the listOf() function:

val hobbits = listOf("Frodo", "Sam", "Pippin", "Merry")

Note that we didn't specify the type of the list. The reason is that the type inference can also be used when constructing collections in Kotlin, the same as when initializing variables.

If you want to provide the type of the list, you similarly do that for defining arguments for a function:

val hobbits: List<String> = listOf("Frodo", "Sam", "Pippin",   "Merry")

To access an element in the list at a particular index, we use square brackets:

println(hobbits[1]) 

The preceding code will output this:

> Sam

Sets

A set represents a collection of unique elements. Looking for the presence of an element in a set is much faster than looking it up in a list. But, unlike lists, sets don't provide indexes access.

Let's create a set of football World Cup champions until after 1994:

val footballChampions = setOf("France", "Germany", "Spain",   "Italy", "Brazil", "France", "Brazil", "Germany")
println(footballChampions) // [France, Germany, Spain,   Italy, Brazil]

You can see that each country exists in a set exactly once. To check whether an element is in a Set collection, you can use the in function:

println("Israel" in footballChampions)
println("Italy" in footballChampions) 

This gives us the following:

> false
> true

Note that although sets, in general, do not guarantee the order of elements, the current implementation of a setOf() function returns LinkedHashSet, which preserves insertion order – France appears first in the output, since it was the first country in the input.

Maps

A map is a collection of key-value pairs, in which keys are unique. The keyword that creates a pair of two elements is to. In fact, this is not a real keyword but a special function. We'll learn about it more in Chapter 5, Introducing Functional Programming.

In the meantime, let's create a map of some of the Batman movies and the actors that played Bruce Wayne in them:

val movieBatmans = mapOf(
    "Batman Returns" to "Michael Keaton",
    "Batman Forever" to "Val Kilmer",
    "Batman & Robin" to "George Clooney"
)
println(movieBatmans) 

This prints the following:

> {Batman Returns=Michael Keaton, 
> Batman Forever=Val Kilmer, 
> Batman & Robin=George Clooney}

To access a value by its key, we use square brackets and provide the key:

println(movieBatmans["Batman Returns"])

The preceding code will output this:

> Michael Keaton

Those data structures also support checking that an element doesn't exist:

println(" Batman Begins " !in movieBatmans)

We get the following output:

> true

Mutability

All of the data structures we have discussed so far are immutable or, more correctly, read-only.

There are no methods to add new elements to a list we create with the listOf() function, and we also cannot replace any element:

hobbits[0] = "Bilbo " // Unresolved reference!

Immutable data structures are great for writing concurrent code. But, sometimes, we still need a collection we can modify. In order to do that, we can use the mutable counterparts of the collection functions:

val editableHobbits = mutableListOf("Frodo", "Sam",   "Pippin", "Merry")
editableHobbits.add("Bilbo")

Editable collection types have functions such as add() that allow us to modify or, in other words, mutate them.

Alternative implementations for collections

If you have worked with JVM before, you may know that there are other implementations of sets and maps. For example, TreeMap stores the keys in a sorted order.

Here's how you can instantiate them in Kotlin:

import java.util.*
// Mutable map that is sorted by its keys 
val treeMap = java.util.TreeMap( 
    mapOf(
        "Practical Pig" to "bricks",
        "Fifer" to "straw",
        "Fiddler" to "sticks"
    )
)
 
println(treeMap.keys)

We will get the following output:

> [Fiddler, Fifer, Practical Pig]

Note that the names of the Three Little Pigs are ordered alphabetically.

Arrays

There is one other data structure we should cover in this section – arrays. In Java, arrays have a special syntax that uses square brackets. For example, an array of strings is declared String[], while a list of strings is declared as List<String>. An element in a Java array is accessed using square brackets, while an element in a list is accessed using the get() method.

To get the number of elements in an array in Java, we use the length() method, and to do the same with a collection, we use the size() method. This is part of Java's legacy and its attempts to resemble C++.

In Kotlin, array syntax is consistent with other types of collections. An array of strings is declared as Array<String>:

val musketeers: Array<String> = arrayOf("Athos", "Porthos",   "Aramis")

This is the first time we see angle brackets in Kotlin code. Similar to Java or TypeScript, the type between them is called type argument. It indicates that this array contains strings. We'll discuss this topic in detail in Chapter 4, Getting Familiar with Behavioral Patterns, while covering generics.

If you already have a collection and would like to convert it into an array, use the toTypedArray function:

listOf(1, 2, 3, 5).toTypedArray()

In terms of its abilities, a Kotlin array is very similar to a list. For example, to get the number of elements in a Kotlin array, we use the same size property as other collections.

When would you need to use arrays then? One example is accepting arguments in the main function. Previously, we've seen only main functions without arguments, but sometimes you want to pass them from a command line.

Here's an example of a main function that accepts arguments from a command line and prints all of them, separated by commas:

fun main(args: Array<String>) { 
    println(args.joinToString(", "))
}

Other cases include invoking Java functions that expect arrays or using varargs syntax, which we will discuss in Chapter 3, Understanding Structural Patterns.

As we are now familiar with some basic data structures, it's time to discuss how we can apply logic to them using if and when expressions.

Control flow

You could say that the control flow is the bread and butter of writing programs. We'll start with two conditional expressions, if and when.

The if expression

In Java, if is a statement. Statements do not return any value. Let's look at the following function, which returns one of two possible values:

public String getUnixSocketPolling(boolean isBsd) { 
    if (isBsd) {
        return "kqueue"; 
    }
    else {
        return "epoll";
    }
}

While this example is easy to follow, in general, having multiple return statements is considered bad practice because they often make the code harder to comprehend.

We could rewrite this method using Java's var keyword:

public String getUnixSocketPolling(boolean isBsd) { 
    var pollingType = "epoll";
    if (isBsd) {
        pollingType = "kqueue";
    }
    return pollingType;
}

Now, we have a single return statement, but we had to introduce a mutable variable. Again, with such a simple example, this is not an issue. But, in general, you should try to avoid mutable shared state as much as possible, since such code is not thread-safe.

Why are we having problems writing that in the first place, though?

Contrary to Java, in Kotlin, if is an expression, meaning it returns a value. We could rewrite the previous function in Kotlin as follows:

fun getUnixSocketPolling(isBsd: Boolean): String {
    return if (isBsd) {
        "kqueue"
    } else {
        "epoll"
    }
}

Or we could use a shorter form:

fun getUnixSocketPolling(isBsd: Boolean): String     = if (isBsd) "kqueue" else "epoll"

Due to the fact that if is an expression, we didn't need to introduce any local variables.

Here, we're again making use of single-expression functions and type inference. The important part is that if returns a value of the String type. There's no need for multiple return statements or mutable variables whatsoever.

Important Note:

Single-line functions in Kotlin are very cool and pragmatic, but you should make sure that somebody else other than you understands what they do. Use with care.

The when expression

What if (no pun intended) we want to have more conditions in our if statement?

In Java, we use the switch statement. In Kotlin, there's a when expression, which is a lot more powerful, since it can embed some other Kotlin features. Let's create a method that's given a superhero and tells us who their archenemy is:

fun archenemy(heroName: String) = when (heroName) {
    "Batman" -> "Joker"
    "Superman" -> "Lex Luthor"
    "Spider-Man" -> "Green Goblin"
    else -> "Sorry, no idea"
}

The when expression is very powerful. In the next chapters, we will elaborate on how we can combine it with ranges, enums, and sealed classes as well.

As a general rule, use when if you have more than two conditions. Use if for simple cases.

Working with text

We've already seen many examples of working with text in the previous section. After all, it's not possible to print Hello Kotlin without using a string, or at least it would be very awkward and inconvenient.

In this section, we'll discuss some of the more advanced features that allow you to manipulate text efficiently.

String interpolation

Let's assume now we would like to actually print the results from the previous section.

First, as you may have already noticed, in one of the previous examples, Kotlin provides a nifty println() standard function that wraps the bulkier System.out.println command from Java.

But, more importantly, as in many other modern languages, Kotlin supports string interpolation using the ${} syntax. Let's take the example from before:

val hero = "Batman"
println("Archenemy of $hero is ${archenemy(hero)}")

The preceding code would print as follows:

> Archenemy of Batman is Joker

Note that if you're interpolating a value of a function, you need to wrap it in curly braces. If it's a variable, curly braces could be omitted.

Multiline strings

Kotlin supports multiline strings, also known as raw strings. This feature exists in many modern languages, and was brought to Java 15 as text blocks.

The idea is quite simple. If we want to print a piece of text that spans multiple lines, let's say something from Alice's Adventures in Wonderland by Lewis Carroll, one way is to concatenate it:

println("Twinkle, Twinkle Little Bat\n" +
    "How I wonder what you're at!\n" +
    "Up above the world you fly,\n" +
    "Like a tea tray in the sky.\n" +
    "Twinkle, twinkle, little bat!\n" +
    "How I wonder what you're at!")

While this approach certainly works, it's quite cumbersome.

Instead, we could define the same string literal using triple quotes:

println("""Twinkle, Twinkle Little Bat 
           How I wonder what you're at!
           Up above the world you fly,
           Like a tea tray in the sky.
           Twinkle, twinkle, little bat!
           How I wonder what you're at!""")

This is a much cleaner way to achieve the same goal. If you execute this example, you may be surprised that the poem is not indented correctly. The reason is that multiline strings preserve whitespace characters, such as tabs.

To print the results correctly, we need to add a trimIndent() invocation:

println("""
    Twinkle, Twinkle Little Bat
    How I wonder what you're at! 
    """.trimIndent())

Multiline strings also have another benefit – there's no need to escape quotes in them. Let's look at the following example:

println("From \" Alice's Adventures in Wonderland\" ")

Notice how the quote characters that are part of the text had to be escaped using the backslash character.

Now, let's look at the same text using multiline syntax:

println(""" From " Alice's Adventures in Wonderland" """)

Note that there's no need for escape characters anymore.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Understand traditional and modern design patterns to improve the design of your application
  • Combine the benefits of object-oriented, functional, reactive, and concurrent programming
  • Choose the best microservices architecture and frameworks for your web application

Description

This book shows you how easy it can be to implement traditional design patterns in the modern multi-paradigm Kotlin programming language, and takes you through the new patterns and paradigms that have emerged. This second edition is updated to cover the changes introduced from Kotlin 1.2 up to 1.5 and focuses more on the idiomatic usage of coroutines, which have become a stable language feature. You'll begin by learning about the practical aspects of smarter coding in Kotlin, as well as understanding basic Kotlin syntax and the impact of design patterns on your code. The book also provides an in-depth explanation of the classical design patterns, such as Creational, Structural, and Behavioral families, before moving on to functional programming. You'll go through reactive and concurrent patterns, and finally, get to grips with coroutines and structured concurrency to write performant, extensible, and maintainable code. By the end of this Kotlin book, you'll have explored the latest trends in architecture and design patterns for microservices. You’ll also understand the tradeoffs when choosing between different architectures and make informed decisions.

Who is this book for?

This book is for developers who want to apply design patterns they’ve learned from other languages in Kotlin and build reliable, scalable, and maintainable applications. You’ll need a good grasp on at least one programming language before you get started with this book. Java or design patterns will be particularly useful, but you’ll still be able to follow along if you code in other languages.

What you will learn

  • Implement all the classical design patterns using the Kotlin programming language
  • Apply reactive and concurrent design patterns to make your application more scalable
  • Discover best practices in Kotlin and explore its new features
  • Understand the key principles of functional programming and learn how they apply to Kotlin
  • Find out how to write idiomatic Kotlin code and learn which patterns to avoid
  • Harness the power of Kotlin to design concurrent and reliable systems with ease
  • Create an effective microservice with Kotlin and the Ktor framework

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Jan 21, 2022
Length: 356 pages
Edition : 2nd
Language : English
ISBN-13 : 9781801816281
Category :
Languages :
Tools :

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Product feature icon AI Assistant (beta) to help accelerate your learning
OR
Modal Close icon
Payment Processing...
tick Completed

Billing Address

Product Details

Publication date : Jan 21, 2022
Length: 356 pages
Edition : 2nd
Language : English
ISBN-13 : 9781801816281
Category :
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 130.97
Kotlin Design Patterns and Best Practices
$44.99
Clean Android Architecture
$38.99
Kickstart Modern Android Development with Jetpack and Kotlin
$46.99
Total $ 130.97 Stars icon

Table of Contents

16 Chapters
Section 1: Classical Patterns Chevron down icon Chevron up icon
Chapter 1: Getting Started with Kotlin Chevron down icon Chevron up icon
Chapter 2: Working with Creational Patterns Chevron down icon Chevron up icon
Chapter 3: Understanding Structural Patterns Chevron down icon Chevron up icon
Chapter 4: Getting Familiar with Behavioral Patterns Chevron down icon Chevron up icon
Section 2: Reactive and Concurrent Patterns Chevron down icon Chevron up icon
Chapter 5: Introducing Functional Programming Chevron down icon Chevron up icon
Chapter 6: Threads and Coroutines Chevron down icon Chevron up icon
Chapter 7: Controlling the Data Flow Chevron down icon Chevron up icon
Chapter 8: Designing for Concurrency Chevron down icon Chevron up icon
Section 3: Practical Application of Design Patterns Chevron down icon Chevron up icon
Chapter 9: Idioms and Anti-Patterns Chevron down icon Chevron up icon
Chapter 10: Concurrent Microservices with Ktor Chevron down icon Chevron up icon
Chapter 11: Reactive Microservices with Vert.x Chevron down icon Chevron up icon
Assessments Chevron down icon Chevron up icon
Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.5
(13 Ratings)
5 star 76.9%
4 star 7.7%
3 star 7.7%
2 star 7.7%
1 star 0%
Filter icon Filter
Top Reviews

Filter reviews by




Maxwell Oct 22, 2022
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Clearly explained and even entertaining at times with the source code provided on GitHub.
Amazon Verified review Amazon
Samuel Stegall May 31, 2022
Full star icon Full star icon Full star icon Full star icon Full star icon 5
"Kotlin Design Patterns and Best Practices" is a book that covers three major topics: design patterns, commonly-used Kotlin language features, and applications of patterns and language features by designing concurrent and reactive microservices. Currently, I work as an Android programmer. The Android platform uses Kotlin as its flagship programming language, which has convinced me to do a deep-dive on the language and its advanced features, which led me to this book. Because of this book, I have a greater understanding of fundamental Kotlin, the Kotlin language's best features, and how to more effectively write and use Kotlin in my Android apps.This book features many different design patterns, which are very important to learn as you become a more senior software engineer. Proper understanding and application of design patterns allows you to more-effectively structure your code, and communicate your code's intent to other engineers. Because of this, many engineers dedicate time and effort to learning these patterns, making this book a fantastic resource. This book shows examples of each pattern in Kotlin, as well as hypothetical examples of where you might apply a given pattern, which can make this book a great reference on design patterns.While I was reading this, it became very apparent that the designers of the Kotlin language selected keywords for the language to more effectively communicate a given keyword's pattern application. For example, the "object" keyword aligns with the Singleton pattern in the book, where no such exclusive keyword exists in Kotlin's parent language of Java. What this means for readers of this book is that the examples shown in the book are relatively concise and easy to understand. Because of this language design decision, and the multiple design decisions made for the Kotlin language, I can think of no better language to teach and communicate design patterns.The second major focus of this book is on the Kotlin language's features, including its features for functional programming, multithreading, and reasoning around nullability. Kotlin provides more-advanced language features around handling nullability, similar to languages like Go. This helps combat nullability errors, which are a common pain point for developers. The book covers how Kotlin handles nullability, and how you can properly structure your code with nullability in mind, with things like the let function. This nullability concept is a common pain-point among developers, so I find it nice that this book makes strong mention of how to combat this.This book also covers the functional programming techniques and methods that the Kotlin language supports. Most languages still in use today have some form of functional programming available, but Kotlin holds its own by comparison. One thing that I learned was how you could use the "also" function to show intermediate effects in a function chain without having to break the function chain. I haven't seen this in other languages, though it may exist in them. Either way, the book makes special mention of it, and I can think of a few places where it might be useful in some of my projects.This book also covers the multithreading and parallelism aspects of the Kotlin language, which are supported to great effect with things like coroutines, observers, subscribers, and locks. These concepts are very important in Android in particular because all data processing and network requests in Android must take place off of the main thread. This means that any asynchronous app, which is almost all of them, makes use of these features. In my onboarding as an Android developer, this was a point of pain to learn, but this book has really helped iron these concepts out in my mind. I will probably need to review this section a bit more to more fully understand what is happening, but I am significantly better off reading this book to understand these concepts.The last section of the book goes over how to apply the first two sections of the book to produce concurrent and reactive microservices. I used to work as a web developer, so I would occasionally work on back-end projects. Going through these microservice sections, it was nice to see some of the earlier parts of the book applied. Furthermore, it was nice to see an example of how to implement APIs in Kotlin first-hand.Luckily, I found few spelling and grammar errors in this book. It was edited well, structured thoughtfully, and written to be useful. I expect that this will be a book that I keep close by throughout all my time working as an Android developer. My overall rating of this book is 4.5 out of 5. I think that the book is a very, very relevant book for Kotlin programmers and Android developers of all skill levels. I have only two criticisms for the book. The first would be that as approachable as the book is, novice developers will have trouble understanding the section of the book on concurrency: concurrency is an advanced topic that can be somewhat difficult for people to reason about, particularly if a given reader has little exposure to the topic beforehand. My second criticism is that the section about microservices at the end comes up a little bit abruptly and could probably go through some fleshing out. Coming from a prior webdev background, I had little issue interfacing with the API I was writing, but new developers may run into issues interfacing with the API. Also, since this section relies on external things like IntelliJ IDEA and its plugins, the screenshots for this section with respect to the IntelliJ IDEA editor are recently out of date with what's shown in new versions of IntelliJ IDEA.Overall, this is a great book that I'll keep by my side mostly to reference the different Kotlin design patterns and language features. I expect that I'll be referencing it regularly as these patterns and features come up in my work.
Amazon Verified review Amazon
Android Developer Jan 31, 2022
Full star icon Full star icon Full star icon Full star icon Full star icon 5
I'm an Android developer who is always trying to brush up on my fundamentals. This book is great for anyone working with Kotlin and has maybe looked at the gang of four classic in the past. This takes those design patterns and ideas and translates them into easy to understand examples, with arguably better guidance of how or when you would apply them into your code.The introduction to Kotlin in the first half of the book was still valuable to me, even though I've been working with it for coming up to two years.I felt the author struck the balance perfectly between talking technically whilst keeping the content accessible, with a light hearted approach to the examples.Highly recommended and I'll definitely keep an eye out for other books by them.Dave,Android Developer
Amazon Verified review Amazon
Santosh Pandit Feb 05, 2022
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book is simply awesome n perfect to learn design patterns in kotlin. It has great content & exercises to test the kotlin knowledge in each chapter. To learn and follow up with learning progress, It has code examples on github repository which I believe is a nice approach for learning new things in programming.Overall I'm very happy to get a copy of it. I would strongly recommend it to anyone who has interest in Kotlin Design Patterns or wants to excell kotlin programming knowledge.
Amazon Verified review Amazon
Placeholder Feb 23, 2023
Full star icon Full star icon Full star icon Full star icon Full star icon 5
It helps you understanding core of Kotlin and how actually things works inside in some cases.It helps me in cracking Walmart
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook? Chevron down icon Chevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website? Chevron down icon Chevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook? Chevron down icon Chevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support? Chevron down icon Chevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks? Chevron down icon Chevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook? Chevron down icon Chevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.