kt.academy Logo

Effective Kotlin:

Best Practices

Effective Kotlin
Kotlin is a powerful and pragmatic language, but it's not enough to know about its features. We also need to know when they should be used and in what way. This book is a guide for Kotlin developers on how to become excellent Kotlin developers. It presents and explains in-depth the best practices for Kotlin development. Each item is presented as a clear rule of thumb, supported by detailed explanations and practical examples.
Effective Kotlin provides insights into the idiomatic way of Kotlin development, as well as many general programming best practices and details about advanced Kotlin features like DSL creation, generics, platform types or inline functions and classes. All that for experienced Kotlin developers to get more effective when they use this programming language: to make safe, well designed and efficient code.

The purpose

To really unleash the advantages of Kotlin, we need to use it properly. To do so, not only do we need to know about different Standard Library (stdlib) functions but even more, we need a good understanding of Kotlin features, purpose, and design. The main goal of this book is to explain how to use different Kotlin features to achieve safe, readable, scalable, and efficient code. Since this book is written to help developers get better at writing code, it also touches many general rules for programmers. This book tries to compose as much knowledge about best practices in Kotlin as possible. You can call it a collection of best practices.

Who is this book for

This book is not teaching basics. It assumes that you have enough knowledge and skills to do Kotlin development. If you don’t, I recommend starting first from [resource designed for beginners](/book/kotlin_essentials). Effective Kotlin is directed to experienced Kotlin developers. Though I will assume that even experienced developers might not know some features. This is why I explain some concepts like: * Property * Platform type * Named arguments * Property delegation * DSL creation * Inline classes and functions * Tail recursion I want this book to be a complete guide for Kotlin developers on how to become an amazing Kotlin developer.

Book structure

🔒

Good code

More general rules about making good quality code. This part is for every Kotlin developer, no matter how big their project is. It starts from items about safety and later talks about readability. It is not a coincidence that the first chapter is dedicated to safety. I believe that program correctness generally is of the highest priority, and safety is an important component. Readability is another item because the code is not only for a compiler but also for programmers. Even when we work alone, we want code that is readable and self-explanatory.

🔒

Code design

This section is for developers creating a project together with other developers, or creating libraries. It is about conventions and setting contracts. It will, in the end, reflect on readability and safety, but all in terms of correct code design. This part is a bit more abstract at the beginning, but thanks to that it can explore topics that are often omitted in books about code quality. This section is also about preparing our code for growth. A lot of items are about being ready for changes in the future. Therefore it is an especially important section for developers creating large projects.

🔒

Efficiency

This section is for developers that care about code efficiency. Most of the rules presented here do not come at the cost of development time or readability, so they are suitable for everyone. However, they are particularly important for developers implementing high-performance applications, libraries, or applications for millions.

Chapter by Chapter

Clear path to progress

1.Safety
  • Limit mutability
  • Eliminate critical sections
  • Eliminate platform types as soon as possible
  • Minimize the scope of variables
  • Specify your expectations for arguments and state
  • Prefer standard errors to custom ones
  • Prefer a nullable or Result result type when the lack of a result is possible
  • Close resources with use
  • Write unit tests
2.Readability
  • Design for readability
  • An operator’s meaning should be consistent with its function name
  • Use operators to increase readability
  • Consider making types explicit
  • Consider referencing receivers explicitly
  • Properties should represent a state, not a behavior
  • Avoid returning or operating on Unit?
  • Consider naming arguments
  • Respect coding conventions
3.Reusability
  • Do not repeat knowledge
  • Do not repeat common algorithms
  • Use generics when implementing common algorithms
  • Avoid shadowing type parameters
  • Consider using variance modifiers for generic types
  • Reuse between different platforms by extracting common modules
4.Abstraction design
  • Each function should be written in terms of a single level of abstraction
  • Use abstraction to protect code against changes
  • Specify API stability
  • Consider wrapping external APIs
  • Minimize elements’ visibility
  • Define contracts with documentation
  • Respect abstraction contracts
5.Object creation
  • Consider factory functions instead of secondary constructors
  • Consider a primary constructor with named optional arguments
  • Consider defining a DSL for complex object creation
  • Consider using dependency injection
6.Class design
  • Prefer composition over inheritance
  • Use the data modifier to represent a bundle of data
  • Use function types or functional interfaces to pass operations and actions
  • Use sealed classes and interfaces to express restricted hierarchies
  • Prefer class hierarchies instead of tagged classes
  • Use enum to represent a list of values
  • Respect the contract of equals
  • Respect the contract of hashCode
  • Respect the contract of compareTo
  • Consider extracting non-essential parts of your API into extensions
  • Avoid member extensions
7.Make it cheap
  • Avoid unnecessary object creation
  • Consider using object declarations
  • Use caching when possible
  • Extract objects that can be reused
  • Use the inline modifier for functions with parameters of functional types
  • Consider using inline value classes
  • Eliminate obsolete object references
8.Efficient collection processing
  • Prefer Sequences for big collections with more than one processing step
  • Consider associating elements to a map
  • Consider using groupingBy instead of groupBy
  • Limit the number of operations
  • Consider Arrays with primitives for performance-critical processing
  • Consider using mutable collections
  • Use appropriate collection types