简介

A good library is one that has:

  • Backward compatibility
  • Complete and easy-to-understand documentation
  • Minimum cognitive complexity
  • Consistent API

This guide contains a summary of best practices and ideas to consider when writing an API for your library. It consists of the following chapters:

Many of the following best practices provide advice on how to reduce the cognitive complexity of an API. As such, this guide provides an explanation of cognitive complexity before proceeding to best practices.

Cognitive complexity

Cognitive complexity is the amount of mental effort a person needs to spend to understand a piece of code. A codebase with high cognitive complexity is more difficult to understand and maintain, which can lead to bugs and delays in development.

An example of high cognitive complexity is a class or module that does not follow the Single Responsibility Principle. A class or module that does too many things is hard to understand and modify. In contrast, a class or module that has one clear and well-defined responsibility is easier to work with.

Functions can also have high cognitive complexity. Some traits of a "badly written" function are:

  • Too many arguments, variables, or loops.
  • Complex logic with many nested if-else statements.

A function like that is harder to work with than a function with clear and simple logic – one with few parameters and an easy-to-understand control flow. An example of high cognitive complexity:

fun processData(
    data: List<String>,
    delimiter: String,
    ignoreCase: Boolean,
    sort: Boolean,
    maxLength: Int
) {
    // Some complex processing logic
}

Decomposing this functionality lowers the cognitive complexity:

fun delimit(data: List<String>, delimiter: String) { … }
fun ignoreCase(data: List<String>) { … }
fun sortAscending(data: List<String>) { … }
fun sortDescending(data: List<String>) { … }
fun maxLength(data: List<String>, maxLength: Int) { … }

You can simplify the code above even more with the help of extension functions:

fun List<String>.delimit(delimiter: String): List<String> { … }
fun List<String>.sortAscending(): List<String> { … }
fun List<String>.sortDescending(): List<String> { … }
fun List<String>.maxLength(maxLength: Int): List<String> { … }
…

What's next?

Learn about APIs' readability.