This section presents coding convention used at Makimo for applications written in Kotlin/Android.
The convention is based on the official Kotlin style guide. In case of omitted aspects of code style or some differences between the company policy and Kotlin style guide, the following document gives preferred coding rules.
Try not to exceed 100 characters per line. In some cases it is allowed to use up to 120 characters. If your code line is longer than 120 characters, please look at the official Kotlin style guide to reformat a piece of code.
Always use curly brackets around if
and when
when expression is multiline
as well as around loop statements. Put the opening curly brackets at the end of
the line and the closing one on a separate line aligned to the beginning of the
code block.
for (el in elements) {
// do sth
}
if (bar) {
// do sth
} else {
// do sth else
}
when {
x -> 1
y -> 2
else -> 3
}
In case of one-liners do not use brackets.
if (bar) doSth()
Also look at the official Kotlin style guide paragraph about formating
Do not use type declarations in case of values and variables.
val x: Int = 5 // Bad
var y = "OK" // Good
Try to group code with scope functions such as apply
if possible.
// Bad
val intent = Intent(this, SomeActivity::class.java)
intent.putExtra(VAL_1, 1)
intent.putExtra(VAL_2, 2)
// Good
val intent = Intent(this, SomeActivity::class.java).apply {
putExtra(VAL_1, 1)
putExtra(VAL_2, 2)
}
Other examples of scope functions are: with
, run
, also
and let
.
Look at the official Kotlin style guide section about [using scope functions] (https://kotlinlang.org/docs/reference/coding-conventions.html#using-scope-functions-applywithrunalsolet)
Many Kotlin's structure are expressions so try to use theirs advantages whenever possible.
// Bad
if (bar) {
return 1
} else {
return 2
}
// Good
return if (bar) {
1
} else {
2
}
// Bad
when (value) {
x -> return 1
y -> return 2
else -> return 3
}
// Good
return when (value) {
x -> 1
y -> 2
else -> 3
}
// Bad
fun foo(x: Int): Int {
return 2 * x
}
// Bad (unless context requires explicit type)
fun foo(x: Int): Int = 2 * x
// Good
fun foo(x: Int) = 2 * x
// Bad
fun foo(x: Int, y: String): Bar {
val o = Bar()
o.x = x
o.y = y
return o
}
// Good
fun foo(x: Int, y: String) = Bar().apply{
this.x = x
this.y = y
}
If declaration is below line length limit, put it on a single line, but leave one single line after opening braces:
// Good:
class Foo(val b: Bar) {
fun foo() {
// ...
}
}
// Bad:
class Foo(val b: Bar) {
fun foo() {
// ...
}
}
If declaration is long, break it like so:
class Foo(
val a: ClassA,
val b: ClassB,
val c: ClassC,
val d: ClassD
): SomeInterface {
fun foo() {
// ^ Again one empty line above
}
}
If you're declaring a companion
, use one single line before and after:
class Foo {
companion object {
const val SOME_CONST = "some-const" // Notice no separator line here ^
}
val a = A()
}
Good naming is an absolute must for an Android project. In order to make searching for Android layout files easier, we use prefixes corresponding to their function. Accordingly:
-
activity_
- Activity layout files; -
fragment_
- Fragment layout files; -
layout_
- Raw layouts; imported via<layout name="...">
; -
dialog_
- Dialog layout files; -
item_
- List view item layout files; -
view_
- View layout files, used by widgets and small self-contained widgets;
-
btn_
- Custom button layout; -
ic_
- Icon layout; -
bkg_
- Background layout for a view; -
view_
- Generic view layout (when other type does not fit); -
selector_
- Selectors defining different states of components;
Color names should correspond to the color they represent, not functionality
it is related to, such as appBarColor
or navBarBackgroundColor
.
Those are too hard to remember.
It does not matter whether the color values are written in uppercase or lowercase, But it's important to be consistent and stick to a chosen notation.
<!-- Bad -->
<color name="lightCerulean">#7bd3f7</color>
<color name="cerulean">#019FD9</color>
<color name="tealBlue">#007bb2</color>
<color name="pinkishRed">#F31F32</color>
<!-- Good -->
<color name="lightCerulean">#7bd3f7</color>
<color name="cerulean">#019fd9</color>
<color name="tealBlue">#007bb2</color>
<color name="pinkishRed">#f31f32</color>
<!-- Good -->
<color name="lightCerulean">#7BD3F7</color>
<color name="cerulean">#019FD9</color>
<color name="tealBlue">#007BB2</color>
<color name="pinkishRed">#F31F32</color>
Strings in most applications are divided into one-time specific strings
and generic informational strings, such as error-messages, confirmation
buttons, retry labels and so on. Accordingly, strings
should reflect
this division. Examples of generic strings used throughout the application:
<string name="next">Next</string>
<string name="cancel">Cancel</string>
<string name="error_while_loading_data">There was a problem loading the data. Check your internet connection.</string>
Examples of specific strings:
<string name="next_event_date">Next event date: %1$s</string>
<string name="policy_number">Policy number: %1$s</string>
When possible, dimensions should be divisible by 2, e.g.: 4, 8, 12, 16, 20, 24, 32, 50. Most projects should use a finite set of standard paddings; e.g.:
<dimen name="xsmall_padding">4dp</dimen>
<dimen name="small_padding">8dp</dimen>
<dimen name="normal_padding">16dp</dimen>
<dimen name="large_padding">24dp</dimen>
<dimen name="xlarge_padding">32dp</dimen>
If the application contains a large number of dimens and naming them starts to be challenging it's a good practice to name them based on their value; eg.;
<dimen name="dim_8">8dp</dimen>
<dimen name="dim_16">16dp</dimen>
<dimen name="dim_24">24dp</dimen>
<dimen name="dim_32">32dp</dimen>
In the same way, you can define dimensions for text; eg.:
<dimen name="h0">48sp</dimen>
<dimen name="h1">24sp</dimen>
<dimen name="h2">20sp</dimen>
<dimen name="h3">18sp</dimen>
<dimen name="sp_4">4sp</dimen>
<dimen name="sp_8">8sp</dimen>
<dimen name="sp_10">10sp</dimen>
<dimen name="sp_14">14sp</dimen>
Similar to naming colors, styles should be as generic as possible and correspond to their appearance or properties, not functionality.
<!-- Good -->
<style name="RedButton">
<item name=""></item>
</style>
<!-- Bad -->
<style name="NoInternetConnectionButton">
<item name=""></item>
</style>
It's also a good practice to separate the common base of different variants of styles, in such a case
we should specify the variant name after the ParentName.
beginning with a capital letter; eg.;
<style name="RedButton">
<item name=""></item>
</style>
<style name="RedButton.Large" parent="RedButton">
<item name=""></item>
</style>
<style name="RedButton.Small" parent="RedButton">
<item name=""></item>
</style>