Last Updated:

How to make Kotlin code more understandable


Practical advice

Use require and check:

 

 

Use functions instead of comments:

 

 

Or better yet, the extension functions:

 

 

Infix functions make the code easier to read:

 

Make functions infix if:

  • the function has no side effects;
  • has simple logic;
  • has a short name;
  • used in places where parentheses will interfere with reading.

Use the with, apply, and also functions:

 

 

Do not specify a type where you can omit it:

 

Exceptions:

  • the type returned by the function is too complex, for example Map<Int, Map<String, String>>;
  • When you call functions that do not have nullable annotations (for example, regular Java functions).

Use assignment when you create a function that consists of a single expression:

 

 

Typealias will simplify the work with complex types:

 

 

Use precision labels to specify the type of value being assigned:

 

 

Use underlining to make long numbers more readable:

 

 

Interpolate strings to make them more readable:

 

 

Use the operator ? To return control:

 

 

Use the Sequence type to optimize the processing of very long lists (more than 1000 items):

 

 

Use back quotation marks when writing test names:

 

 

Kotlin problems and solutions

Problem number 1: let. Many programmers are accustomed to using let as a simple and convenient alternative to if (x == null):

You shouldn't do that. Using it is bad form because multiple it can mix if another similar lambda appears in the code. Can you try to fix this with the imageFile construct?. let { image ->, but in the end you will make it even worse, because in the same scope there will be another variable that refers to the same value, but has a different name. And this name will have to be invented!

In fact, in most cases, this problem can be fixed by simply abandoning let:

This code is fine. Smart type conversion will do the job, and you can reference the imageFile after checking as a non-nullable variable.

But! This technique will not work if we are not talking about a local variable, but about the fields of the class. Because class fields can be modified by multiple methods running on different threads, the compiler will not be able to use smartcasting.

This is where you can use let.

But there are more unusual ways. For example, exit the function if the field value is null:

Or use the takeIf method:

You can even combine both approaches:

 

The point of such code is to limit the creation of an intent and its use to two different areas of view, which in theory should have a beneficial effect on its modularity.

In fact, such constructions only clutter the code. Much more beautiful is its more straightforward version:

Better yet, put the object configuration code in a separate function:

Problem number 3: Run. A common technique is to use the run function to frame code blocks:

This is absolutely pointless clutter of the code. It makes it difficult to read essentially simple code:

If the code in the block "if null" is more than one line, then you can use this construct:

Problem number 4: with. In this case, the problem is not with the with function itself, but with ignoring it. Developers simply do not use this feature, despite all its beauty:

There are usually two reasons not to use it:

  • it cannot be used in function call chains.
  • it's not good with nullable variables.

With these tips, you can make the Kotlin code cleaner, clearer and more unambiguous.