├── README.md └── android-resources.md /README.md: -------------------------------------------------------------------------------- 1 | # Style guide 2 | 3 | Code styles shall be adhered to in the following order (whereas their precedence follows the order listed and subsequent 4 | guides can be used as fall back if the previous does not cover a specific topic): 5 | 6 | 1. This Guide 7 | 2. [Android Kotlin Guides](https://android.github.io/kotlin-guides/style.html) 8 | 3. [JetBrain's Kotlin Coding Conventions](https://kotlinlang.org/docs/reference/coding-conventions.html) 9 | 10 | ## Naming 11 | 12 | ### Variables 13 | 14 | Variable names should be named to remove ambiguity. In general, including a variable's type in it's 15 | name is overly verbose, unless it provides necessary clarity. For example, a list of locations 16 | (`List`) would appropriately be named `locations` (by virtue of being plural, it implies 17 | that the variable is likely a `Collection`). 18 | 19 | #### Data Streams 20 | 21 | Data streams (e.g. `Flow`, `Channel` or `LiveData`) shall be named to describe the data flowing 22 | through them. For example, a data stream of singular color values (e.g. `Flow`) should be 23 | named `color`. For data streams of `Collections` (e.g. `Flow>`) they should take the 24 | plural form (e.g. `colors`). 25 | 26 | | Type | Naming | Example Type | Example Naming | 27 | |----------------------------|----------|---------------------|----------------| 28 | | Single value variable | Singular | `Color` | `color` | 29 | | Collection | Plural | `List` | `colors` | 30 | | Data flow of single values | Singular | `Flow` | `color` | 31 | | Data flow of collections | Plural | `Flow>` | `colors` | 32 | 33 | Instances where naming would conflict (when you have a property to hold a single value of the same 34 | type as a property referencing a data flow, e.g. `Color` and `Flow`) the naming precedence 35 | shall follow the ordering of the table above, with the lower precedence being postfixed with it's 36 | type. 37 | 38 | When you have naming conflicts with multiple data flow properties, their naming precedence is as 39 | follows: 40 | 41 | - `Flow` 42 | - `Channel` 43 | - `LiveData` 44 | 45 | ```kotlin 46 | interface Example { 47 | val color: Color // Single value property takes precedence over data flow properties. 48 | val colorFlow: Flow // Name postfixed with type to resolve naming conflict. 49 | } 50 | ``` 51 | 52 | ```kotlin 53 | interface Example { 54 | val color: Flow // Flow takes precedence over LiveData. 55 | val colorLiveData: LiveData // Naming of LiveData property is postfixed to resolve naming conflict. 56 | } 57 | ``` 58 | 59 | ```kotlin 60 | interface Example { 61 | val color: Color 62 | val colorFlow: Flow 63 | val colorLiveData: LiveData 64 | } 65 | ``` 66 | 67 | #### Abbreviations 68 | 69 | Abbreviations in variable names are strongly discouraged. Acronyms may be used if they are standard nomenclature 70 | (commonly used in place of their longhand counterparts). 71 | 72 | ```kotlin 73 | val bookTitle = "Programming 101" // Okay 74 | 75 | val bookTtl = "Programming 101" // WRONG! 76 | ``` 77 | 78 | ```kotlin 79 | val ipAddress = "127.0.0.1" // Okay 80 | 81 | val ipAddr = "127.0.0.1" // WRONG! 82 | ``` 83 | 84 | #### Feature Flags 85 | Boolean Feature Flags configured remotely should be named such that `true` coresponds to the feature being `enabled` and `false` is `disabled`. 86 | 87 | ```kotlin 88 | val featureAbc = ExampleRemoteBoolean("feature_abc", true) // Okay, defaults to enabled 89 | 90 | val featureAbc = ExampleRemoteBoolean("feature_abc", false) // Okay, defaults to disabled 91 | 92 | val featureAbc = ExampleRemoteBoolean("feature_abc_disabled", true) // WRONG! true would result in feature being enabled 93 | ``` 94 | 95 | ### Android Resources 96 | 97 | See [Android Resources](android-resources.md) document for resource ID naming conventions. 98 | 99 | ## Nullability 100 | 101 | | Operation | Usage ("When the value...") | Throws | 102 | |--------------------|---------------------------------|--------------------------------| 103 | | [`!!`] | is "known" to be non-`null`. | [`KotlinNullPointerException`] | 104 | | [`checkNotNull`] | is "expected" to be non-`null`. | [`IllegalStateException`] | 105 | | [`requireNotNull`] | "must" not be `null`. | [`IllegalArgumentException`] | 106 | 107 | ### `!!` 108 | 109 | The use of [`!!`] (double bang) operator is allowed but should be used sparingly. It should _only_ 110 | be used when the value is **known** to never be `null` (but the compiler is unable to ascertain 111 | nullness), such as: 112 | 113 | - Type provided by Java code does not have nullability markers 114 | - Smart casting is not possible when accessing variable from another module 115 | 116 | When the reason for the `!!` usage is not immediately obvious, then a comment should be added with 117 | rationale for the `!!` usage. 118 | 119 | ### `checkNotNull` 120 | 121 | `checkNotNull` should be used when a variable can be `null` but you are **not expecting** it to be. 122 | An example is having a nullable `var` that is inialized to `null` but is assigned a value at a later 123 | time. When accessing the `var` (and expecting the value to no longer be `null`) then `checkNotNull` 124 | should be used. 125 | 126 | ### `requireNotNull` 127 | 128 | When you are provided a value (for example, as an argument of a function) to which it's nullness is 129 | unknown (e.g. Java type that is missing nullability markers) but value **must** not be `null`, then 130 | `requireNotNull` should be used. 131 | 132 | ## Coroutines 133 | 134 | ### `suspend` vs `CoroutineScope` 135 | 136 | Per [Kotlin Coroutines in Practice by Roman Elizarov], the following conventions are recommended: 137 | 138 | | Paradigm | Usage | 139 | |---------------------------|--------------------------------------------------------------------| 140 | | `suspend` | Does something long & waits for it to complete without blocking. | 141 | | `CoroutineScope` function | Launches new Coroutines & quickly returns, does not wait for them. | 142 | 143 | ```kotlin 144 | // Does not return until it (and it's children) are done. 145 | suspend fun downloadContent(location: Location): Content 146 | 147 | // Launches Coroutines and returns immediately. 148 | fun CoroutineScope.processReferences(...) 149 | ``` 150 | 151 | # License 152 | 153 | [![Creative Commons License](https://i.creativecommons.org/l/by/4.0/80x15.png)](http://creativecommons.org/licenses/by/4.0/) 154 | 155 | This work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/). 156 | 157 | 158 | [`!!`]: https://kotlinlang.org/docs/reference/null-safety.html#the--operator 159 | [`KotlinNullPointerException`]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-kotlin-null-pointer-exception/ 160 | [`checkNotNull`]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/check-not-null.html 161 | [`IllegalStateException`]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-illegal-state-exception/#kotlin.IllegalStateException 162 | [`requireNotNull`]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/require-not-null.html 163 | [`IllegalArgumentException`]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-illegal-argument-exception/#kotlin.IllegalArgumentException 164 | [Kotlin Coroutines in Practice by Roman Elizarov]: https://youtu.be/a3agLJQ6vt8?t=2160 165 | [snake_case]: https://en.wikipedia.org/wiki/Snake_case 166 | -------------------------------------------------------------------------------- /android-resources.md: -------------------------------------------------------------------------------- 1 | # Naming Conventions 2 | 3 | ## Why? 4 | 5 | Per [Joroean Mol][joroenmol]: 6 | 7 | > Whenever we start a new project, we take a lot of care in setting up our architecture, CI, build flavors,… But do you also have a strategy to name your resources? 8 | > 9 | > You should! Because the lack of XML namespaces, makes managing Android resources tedious. And causes things to grow out of control easily, especially in large projects. 10 | > 11 | > So let’s introduce a simple scheme that will solve your pains. 12 | > 13 | > - easy lookup of any resource (autocomplete) 14 | > - logical, predictable names 15 | > - clean ordering of resources 16 | > - strongly typed resources 17 | 18 | I propose that we do not adopt his final mechanism, but and instead rely on an older tool for information gathering. 19 | 20 | ## Basic Principle 21 | 22 | A global, hierarchical naming structure based on the [Five Ws][fivews], with some extras: 23 | 24 | 1. Subtype 25 | 2. Who 26 | 3. What 27 | 4. Where 28 | 5. When 29 | 6. Why 30 | 7. Value 31 | 32 | ## Element Types 33 | 34 | ### Subtype 35 | A subtype for a resource. 36 | Generally, these should be deterministic 37 | 38 | - Drawables should use one of the following: 39 | - `ic` for icons, as is standard Android convention. 40 | - `grad` for gradients 41 | - `pic` for pictures or illustrations 42 | - `shape` for shapes 43 | - `layers` for layer lists 44 | - `selector` for selectors 45 | - Ids for a view should use a (snake case) version of the view's type, such as `button` or `text_view`. 46 | - Layout will always be one of the following: 47 | - `activity`, `fragment`, and `include` should all be self-explanatory 48 | - `item` for adapter items like recyclers/view pagers 49 | - `view` for custom views 50 | 51 | ### Who 52 | The owner of a resource. 53 | For resources that do not have a clear owner or are shared between unrelated owners, use `all`. 54 | 55 | ### What 56 | The description of a resource. 57 | This should be kept broad whenever possible to group things together. 58 | If further detail is necessary, it can be added here. 59 | For the sake of making things explicit, this is marked as another column on the example table. 60 | 61 | ### When 62 | The condition of a resource. 63 | Use it for things like selectors/state lists, an `include` layout which is only sometimes visible, or associating an error's cause to its message. 64 | 65 | ### Where 66 | The location of a resource, such as where it appears in a layout if it occurs more than once (a link in both the `body` and `footer`, perhaps). 67 | 68 | ### Why 69 | An motivation for a resource, such as legacy version support (`v21`). 70 | 71 | ### Value 72 | A raw value associated with the resource, that is necessary to identify it. 73 | Example uses are alpha-blended colors (specify the opacity percent). 74 | 75 | ### Crafting Names 76 | Elements should be appended in the order above, only including ones that are actually useful. 77 | If an element contains multiple words, each word must be separated with an underscore (`_`). 78 | Elements must also be separated by an underscore. 79 | 80 | Resource types where `all` is more-or-less universal (like colors, ids, drawables) may skip listing it. 81 | 82 | ### Examples 83 | 84 | | Resource Type | Subtype | Who | What | (detail) | Where | When | Why | Value | Combined Name | 85 | | ------------- | ---------- | ---------------- | ------------ | ---------- | ----- | --------------- | --- | ----- | ------------------------------------ | 86 | | **color** | | | `black` | `alpha` | | | | `50` | `black_alpha_50` | 87 | | **color** | | | `mint_green` | | | | | | `mint_green` | 88 | | **dimen** | | `all` | `margin` | | | | | | `all_margin` | 89 | | **dimen** | | `grid` | `10` | | | | | | `grid_10` | 90 | | **drawable** | `ic` | | `chevron` | `right` | | | | | `ic_chevron_right` | 91 | | **id** | `button` | | `sign_out` | | | | | | `button_sign_out` | 92 | | **layout** | `activity` | `main` | | | | | | | `activity_main` | 93 | | **layout** | `include` | `av` | `banner` | | | `no_internet` | | | `include_av_banner_no_internet` | 94 | | **string** | | `all` | `action` | `sign_out` | | | | | `all_action_sign_out` | 95 | | **string** | | `application` | `title` | | | | | | `application_title` | 96 | | **string** | | `authentication` | `error` | | | `invalid_email` | | | `authentication_error_invalid_email` | 97 | 98 | ## Alternatives 99 | 100 | - Joroen Mol's ["A successful XML naming convention"][joroenmol] 101 | - MindOrk's ["Android Resource Naming Convention"][mindork] 102 | - Many others! This is a popular blog topic 103 | 104 | [fivews]: https://en.wikipedia.org/wiki/Five_Ws 105 | [joroenmol]: https://jeroenmols.com/blog/2016/03/07/resourcenaming/ 106 | [mindork]: https://medium.com/mindorks/android-resource-naming-convention-42e4e8026614 107 | --------------------------------------------------------------------------------