├── LICENSE ├── README.md └── android ├── java └── README.md └── kotlin └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Project Style Guides 2 | ============ 3 | A collection of style guides for standardizing code formatting, naming, organization, 4 | and other general styles across projects. These are not intended to be absolute however 5 | if a particular project doesn't follow the defined styles it should have a section in 6 | the README.md that lists the changes and why. 7 | 8 | 9 | Adding Languages or Platforms 10 | -------- 11 | Each new style guide should be located underneath a folder indicating the platform and language 12 | (e.g. `android/kotlin/` or `android/java`). If there are style guides that are shared across 13 | platforms (e.g. `android/java` and `backend/java`) the secondary platform should link to the primary 14 | in the main style README. 15 | -------------------------------------------------------------------------------- /android/java/README.md: -------------------------------------------------------------------------------- 1 | # Android/Java style guidelines 2 | ###### Version 1.0.0 3 | 4 | ## 1 Project structure 5 | The project should follow standard [Android project guidelines](https://developer.android.com/studio/projects/index.html) 6 | however in short: 7 | ``` 8 | root/ 9 | └─ app/ 10 | └─ gradle/ 11 | └─ lib/ 12 | └─ miscFiles.txt 13 | ``` 14 | 15 | ## 2 Package structure 16 | 17 | ### 2.1 Applications 18 | The root structure should follow major source categories: 19 | ``` 20 | app/ 21 | └─ data/ 22 | └─ injection/ 23 | └─ receiver/ 24 | └─ service/ 25 | └─ ui/ 26 | ``` 27 | 28 | The `ui` category needs to be more granular based on the section and follow MVP organization. 29 | This means a login screen will have its own package with `contract` and `platform` sub packages. 30 | ``` 31 | ui/ 32 | └─ login/ 33 | └─ contract/ 34 | └─ platform/ 35 | ``` 36 | 37 | Each category has sub structures to increase the granularity. e.g. 38 | ``` 39 | data/ 40 | └─ webservice/ 41 | └─ database/ 42 | ``` 43 | 44 | ### 2.2 Libraries 45 | Similar to the Applications structure; the root structure should follow major source categories: 46 | ``` 47 | lib/ 48 | └─ api/ 49 | └─ data/ 50 | └─ injection/ 51 | └─ receiver/ 52 | └─ service/ 53 | └─ util/ 54 | ``` 55 | 56 | Each category has sub structures to increase the granularity. e.g. 57 | ``` 58 | api/ 59 | └─ account/ 60 | └─ devices/ 61 | ``` 62 | 63 | ## 3 File naming 64 | 65 | ### 3.1 Class files 66 | Class names should be written in [UpperCamelCase](http://en.wikipedia.org/wiki/CamelCase). 67 | 68 | For classes that extend an Android component, the name of the class should end with the name of the component; for example: 69 | * `SignInActivity` 70 | * `SignInFragment` 71 | * `ImageUploaderService` 72 | * `ChangePasswordDialog` 73 | 74 | ### 3.1 Resources files 75 | 76 | Resources file names are written in __lowercase_underscore__. e.g. 77 | * `ic_launcher` 78 | * `background_default` 79 | 80 | #### 3.1.1 Drawables 81 | 82 | ##### 3.1.1.1 Icons 83 | Icons should follow the naming scheme seen in [Material Icons](https://github.com/google/material-design-icons/) which 84 | follows the format `ic___`; the exception being launcher images which should be named `ic_launcher`. 85 | For example: 86 | 87 | * `ic_link_black_24dp.xml` 88 | * `ic_user_white_48dp.xml` 89 | 90 | 91 | ##### 3.1.1.2 Selector States 92 | Assuming a selector state requires an image instead of an embedded shape, each images should be 93 | named based on the main selector (`button_order` in the example) with the states as a suffix. e.g. 94 | 95 | | State | Suffix | Example | 96 | |--------------|--------------|-----------------------------| 97 | | Normal | `_normal` | `button_order_normal.9.png` | 98 | | Pressed | `_pressed` | `button_order_pressed.9.png` | 99 | | Focused | `_focused` | `button_order_focused.9.png` | 100 | | Disabled | `_disabled` | `button_order_disabled.9.png` | 101 | | Selected | `_selected` | `button_order_selected.9.png` | 102 | 103 | 104 | #### 3.1.2 Layout files 105 | Layout file names should be prefixed with the section the source code will be used by _without_ prefixing 106 | the Android component name. e.g. 107 | 108 | | Component | Class Name | Layout Name | 109 | | ---------------- | ---------------------- | --------------------- | 110 | | Activity | `LoginActivity` | `login.xml` | 111 | | Fragment | `SignUpFragment` | `sign_up.xml` | 112 | | Dialog | `ChangePasswordDialog` | `change_password.xml` | 113 | | AdapterView item | `PersonViewHolder` | `person.xml` | 114 | 115 | 116 | #### 3.1.3 Menu files 117 | Menu file names should match the parent layout naming, they should _not_ include `menu` as they are already 118 | separated by the `R.menu.*` reference. e.g. 119 | 120 | | Parent Layout | Menu Name | 121 | | ------------------ | -------------- | 122 | | `user_profile.xml` | `user_profile` | 123 | | `person.xml` | `person` | 124 | 125 | 126 | #### 3.1.4 Values files 127 | Resource files in the values folder should be __plural__; i.e.: 128 | * `strings.xml` 129 | * `styles.xml` 130 | * `colors.xml` 131 | * `dimens.xml` 132 | * `attrs.xml` 133 | 134 | 135 | # 4 Code guidelines 136 | 137 | ## 4.1 XML style rules 138 | 139 | ### 4.1.1 Prefer self closing tags 140 | When possible self closing tags should be used. e.g. 141 | 142 | ```xml 143 | 147 | ``` 148 | 149 | **Not** 150 | ```xml 151 | 155 | 156 | ``` 157 | 158 | ### 4.1.2 Resource naming 159 | Resources should follow __lowercase_underscore__ naming, the exception being Ids, Styles and Themes (described below) 160 | 161 | #### 4.1.2.1 IDs 162 | IDs should have a suffix indicating the element or category type in [LowerCamelCase](http://en.wikipedia.org/wiki/CamelCase). e.g. 163 | 164 | | Element | Suffix | 165 | | -------------------- | ------------------- | 166 | | `TextView` | `someTextView` | 167 | | `ImageView` | `anImageView` | 168 | | `Button` | `helpButton` | 169 | | `Menu Item` | `loginMenuItem` | 170 | | `Action Mode Menu` | `artistActionMenu` | 171 | | `Context Menu` | `personContextMenu` | 172 | 173 | 174 | #### 4.1.2.2 Strings 175 | String names start with a prefix that identifies the section they belong to. For example `registration_email_hint` 176 | or `registration_name_hint`. If a string __doesn't belong__ to any section then a simple name should be used. e.g. 177 | 178 | | Name | Value | 179 | | ----------------------- | --------------------------------------- | 180 | | `done` | `Done` | 181 | | `general_network_error` | `There was an unknown network error` | 182 | 183 | 184 | #### 4.1.2.3 Styles and Themes 185 | Unlike the rest of resources, style names are written in [UpperCamelCase](http://en.wikipedia.org/wiki/CamelCase). 186 | 187 | ### 4.1.3 Attribute ordering 188 | Attributes should follow the auto ordering that Android Studio enforces; in general this is 189 | 190 | 1. `id` 191 | 2. `style` and `theme` 192 | 3. `layout_width`, `layout_height`, and `layout_weight` 193 | 4. Other attributes sorted alphabetically 194 | 5. Non-`android` namespace items (e.g. `app`) sorted alphabetically 195 | 6. `tools` namespace items sorted alphabetically 196 | 197 | 198 | ## 4.2 Java language rules 199 | 200 | ### 4.2.1 Always handle exceptions 201 | While you may think that your code will never encounter this error condition or that it is not important to handle, 202 | ignoring exceptions creates mines in your code for someone to eventually trip over. Every exception should be handled 203 | by one of the following methods: 204 | 205 | * Add an explicit `throws` to the method definition (e.g. `void someErrorProneFunction() throws IOException`) 206 | * Catch the exception and cancel future functionality (silently failures should be avoided) 207 | * Catch the exception and use a default value instead 208 | 209 | You should **Never** throw [Unchecked Exceptions](https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html) 210 | 211 | 212 | ### 4.2.2 Catch generic Exceptions sparingly 213 | In many cases there are good ways to handle specific issues (e.g. a `FileNotFoundException` should be caught to inform 214 | the user that the file doesn't exist). If this is caught by a generic Exception then there is no good way to inform the 215 | user. However there are some cases that we only care if the process fails, not the reason it failed; in these cases it 216 | is alright to catch generic Exceptions. 217 | 218 | For Example: 219 | 220 | ```java 221 | try { 222 | someComplicatedIOFunction(); // may throw IOException 223 | someComplicatedParsingFunction(); // may throw ParsingException 224 | someComplicatedSecurityFunction(); // may throw SecurityException 225 | } catch (Exception e) { // I'll just catch all exceptions (generic) 226 | handleError(); // with one generic handler! 227 | } 228 | ``` 229 | 230 | See the reason why and some alternatives [here](https://source.android.com/source/code-style.html#dont-catch-generic-exception) 231 | 232 | ### 4.2.3 Don't use finalizers 233 | _We don't use finalizers. There are no guarantees as to when a finalizer will be called, or even that it will be called at all. 234 | In most cases, you can do what you need from a finalizer with good exception handling. If you absolutely need it, define a 235 | `close()` method (or the like) and document exactly when that method needs to be called. See `InputStream` for an example. 236 | In this case it is appropriate but not required to print a short log message from the finalizer, as long as it is not expected 237 | to flood the logs._ - ([Android code style guidelines](https://source.android.com/source/code-style.html#dont-use-finalizers)) 238 | 239 | 240 | ### 4.2.4 Fully qualify imports 241 | While excessive methods and imports can be stripped out with proguard, it is good practice to minimize the amount of 242 | code included. More information can be found [here](https://source.android.com/source/code-style.html#fully-qualify-imports) 243 | 244 | For Example: 245 | an import should read `import foo.Bar;` instead of `import foo.*;` 246 | 247 | 248 | ## 4.3 Java style rules 249 | 250 | ### 4.3.1 Fields definition and naming 251 | Fields should be defined at the __top of the file__ and they should follow the naming rules listed below. 252 | 253 | * private constants `private static final` are all caps (e.x. `MY_CONST`) 254 | * public constants `public static final` are all caps (e.x. `MY_CONST`) 255 | * all other fields should follow [LowerCamelCase](http://en.wikipedia.org/wiki/CamelCase) conventions 256 | 257 | Example: 258 | 259 | ```java 260 | public class MyClass { 261 | private static final int FOO = 1; 262 | public static final int SOME_CONSTANT = 42; 263 | 264 | private int privateVar; 265 | protected int protectedVar; 266 | /*package*/ int packageVar; 267 | public int publicVar; 268 | } 269 | ``` 270 | 271 | ### 4.3.3 Treat acronyms as words 272 | | Good | Bad | 273 | | ---------------- | ---------------- | 274 | | `XmlHttpRequest` | `XMLHTTPRequest` | 275 | | `getCustomerId` | `getCustomerID` | 276 | | `String url` | `String URL` | 277 | | `long id` | `long ID` | 278 | 279 | ### 4.3.4 Use spaces for indentation 280 | Use __4 space__ indentations for blocks: 281 | 282 | ```java 283 | if (i == 1) { 284 | i++; 285 | } 286 | ``` 287 | 288 | Use __8 space__ indentations for line wraps: 289 | ```java 290 | Instrument instrument = 291 | someLongExpression(that, wouldNotFit, on, one, line); 292 | ``` 293 | 294 | ### 4.3.5 Use standard brace style 295 | Braces go on the same line as the code before them and are always required. 296 | 297 | ```java 298 | class MyClass { 299 | int func() { 300 | if (something) { 301 | // ... 302 | } else if (somethingElse) { 303 | // ... 304 | } else { 305 | // ... 306 | } 307 | } 308 | } 309 | ``` 310 | 311 | 312 | ### 4.3.6 Use standard Java annotations 313 | According to the Android code style guide, the standard practices for some of the predefined annotations in Java are: 314 | 315 | | Annotation | Description | 316 | | ---------- | ----------- | 317 | | `@Override` | The @Override annotation __must be used__ whenever a method overrides the declaration or implementation from a super-class. For example, if you use the @inheritdocs Javadoc tag, and derive from a class (not an interface), you must also annotate that the method @Overrides the parent class's method. | 318 | | `@SuppressWarnings` | The @SuppressWarnings annotation should only be used under circumstances where it is impossible to eliminate a warning. If a warning passes this "impossible to eliminate" test, the @SuppressWarnings annotation must be used, so as to ensure that all warnings reflect actual problems in the code. | 319 | | `@Nullable` | The @Nullable annotation should be used whenever a method may return null or a field or parameter accepts a null value | 320 | | `@NonNull` | The @NonNull annotation should be used whenever a method won't return null or a field or parameter cannot be null | 321 | 322 | More information about annotations guidelines can be found [here](http://source.android.com/source/code-style.html#use-standard-java-annotations). 323 | 324 | 325 | ### 4.3.7 Limit variable scope 326 | _The scope of local variables should be kept to a minimum (Effective Java Item 29). By doing so, you increase the readability 327 | and maintainability of your code and reduce the likelihood of error. Each variable should be declared in the innermost block 328 | that encloses all uses of the variable._ 329 | 330 | _Local variables should be declared at the point they are first used. Nearly every local variable declaration should contain an 331 | initializer. If you don't yet have enough information to initialize a variable sensibly, you should postpone the declaration 332 | until you do._ - ([Android code style guidelines](https://source.android.com/source/code-style.html#limit-variable-scope)) 333 | 334 | 335 | ### 4.3.8 Logging guidelines 336 | For simplicity [Timber](https://github.com/JakeWharton/timber) should be used for logging in place of the default 337 | one provided by Android. 338 | 339 | ### 4.3.9 Class member ordering 340 | There is no single correct solution for this but using a __logical__ and __consistent__ order will improve code 341 | readability. It is recommendable to use the following order: 342 | 343 | 1. Constants 344 | 2. Fields 345 | 1. Constants 346 | 2. `@Inject` 347 | 3. `@Bind` 348 | 4. `@BindExtra` 349 | 5. `@BindArgument` 350 | 6. `@SaveState` 351 | 7. Member Variables 352 | 3. Static methods 353 | 4. Constructors 354 | 5. Override methods and callbacks (public or private) 355 | 6. Public methods 356 | 7. Private methods 357 | 8. Inner classes or interfaces 358 | 359 | Example: 360 | 361 | ```java 362 | public class MainActivity extends Activity { 363 | private static final String TAG = "TAG"; 364 | 365 | @Inject //Dagger 366 | Prefs prefs; 367 | 368 | @Bind(R.id.toolbar) //ButterKnife 369 | Toolbar toolbar; 370 | 371 | @BindExtra //PocketKnife 372 | String userId; 373 | 374 | @SaveState //PocketKnife 375 | int currentPosition; 376 | 377 | @Nullable 378 | private String title; 379 | 380 | public static String getTag() { 381 | return TAG; 382 | } 383 | 384 | public void setTitle(@Nullable String title) { 385 | this.title = title; 386 | } 387 | 388 | @Override 389 | public void onCreate() { 390 | //... 391 | } 392 | 393 | private void setUpView() { 394 | //... 395 | } 396 | 397 | static class AnInnerClass { 398 | //... 399 | } 400 | 401 | } 402 | ``` 403 | 404 | If your class is extending and __Android component__ such as an Activity or a Fragment, it is a good practise to order the 405 | override methods so that they __match the component's lifecycle__. For example, if you have an Activity that implements 406 | `onCreate()`, `onDestroy()`, `onPause()` and `onResume()`, then the correct order is: 407 | 408 | ```java 409 | public class MainActivity extends Activity { 410 | @Override 411 | public void onCreate() {} 412 | 413 | @Override 414 | public void onResume() {} 415 | 416 | @Override 417 | public void onPause() {} 418 | 419 | @Override 420 | public void onDestroy() {} 421 | } 422 | ``` 423 | 424 | ### 4.3.10 Parameter ordering in methods 425 | When programming for Android, it is quite common to define methods that take a `Context`. If you are writing a method 426 | like this, then the __Context__ must be the __first__ parameter. 427 | 428 | The opposite case are __callback__ interfaces that should always be the __last__ parameter. 429 | 430 | Examples: 431 | 432 | ```java 433 | // Context always go first 434 | public User loadUser(@NonNull Context context, int userId); 435 | 436 | // Callbacks always go last 437 | public void loadUserAsync(@NonNull Context context, int userId, @Nullable UserCallback callback); 438 | ``` 439 | 440 | ### 4.3.11 String constants, naming and values 441 | Many elements of the Android SDK such as `SharedPreferences`, `Bundle` or `Intent` use a key-value pair approach so 442 | it's very likely that even for a small app you end up having to write a lot of String constants. 443 | 444 | When using one of these components, you __must__ define the keys as a `static final` fields and they should be prefixed as indicated below. 445 | 446 | | Element | Prefix | 447 | | ----------------- | ----------------- | 448 | | SharedPreferences | `PREF_` | 449 | | Bundle | `BUNDLE_` | 450 | | Fragment Arguments | `ARGUMENT_` | 451 | | Intent Extra | `EXTRA_` | 452 | | Intent Action | `ACTION_` | 453 | 454 | Note that the arguments of a Fragment - `Fragment.getArguments()` - are also a Bundle. However, because this is a quite common 455 | use of Bundles, we define a different prefix for them. 456 | 457 | Example: 458 | 459 | ```java 460 | // Note the value of the field is the same as the name to avoid duplication issues 461 | static final String PREF_EMAIL = "PREF_EMAIL"; 462 | static final String BUNDLE_AGE = "BUNDLE_AGE"; 463 | static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID"; 464 | 465 | // Intent-related items use full package name as value 466 | static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME"; 467 | static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER"; 468 | ``` 469 | 470 | ### 4.3.12 Arguments in Fragments and Activities 471 | When data is passed into an `Activity `or `Fragment` via `Intents` or a `Bundles`, the keys for the different values 472 | __must__ follow the rules described in the section above. 473 | 474 | When an `Activity` or `Fragment` expect arguments, it should provide a `static public` method that facilitates the 475 | creation of the `Fragment` or `Intent`. 476 | 477 | In the case of Activities the method is usually called `getStartIntent()` 478 | 479 | ```java 480 | public static Intent getStartIntent(@NonNull Context context, @NonNull User user) { 481 | Intent intent = new Intent(context, ThisActivity.class); 482 | intent.putParcelableExtra(EXTRA_USER, user); 483 | return intent; 484 | } 485 | ``` 486 | 487 | For Fragments it's named `newInstance()` and it handles the creation of the Fragment with the right arguments. 488 | 489 | ```java 490 | public static UserFragment newInstance(@NonNull User user) { 491 | UserFragment fragment = new UserFragment; 492 | Bundle args = new Bundle(); 493 | args.putParcelable(ARGUMENT_USER, user); 494 | fragment.setArguments(args) 495 | return fragment; 496 | } 497 | ``` 498 | 499 | ### 4.3.13 Line length limit 500 | Code lines should not exceed __160 characters__. If the line is longer than this limit there are usually two options to reduce its length: 501 | 502 | * Extract a local variable or method (Preferable). 503 | * Apply line-wrapping to divide a single line into multiple ones. 504 | 505 | There are two __exceptions__ where is possible to have lines longer than 160: 506 | 507 | * Lines that are not possible to split, e.g. long URLs in comments. 508 | * `package` and `import` statements. 509 | 510 | 511 | #### 4.3.13.1 Line-wrapping strategies 512 | There isn't an exact formula that explains how to line-wrap and quite often different solutions are valid. However 513 | there are a few rules that can be applied to common cases. 514 | 515 | __Method chain case__ 516 | 517 | When multiple methods are chained in the same line - for example when using Builders - every call to a method should 518 | go in its own line, breaking the line before the `.` 519 | 520 | ```java 521 | Picasso.with(context).load("http://ribot.co.uk/images/sexyjoe.jpg").into(imageView); 522 | ``` 523 | 524 | ```java 525 | Picasso.with(context) 526 | .load("http://ribot.co.uk/images/sexyjoe.jpg") 527 | .into(imageView); 528 | ``` 529 | 530 | __Long parameters case__ 531 | 532 | When a method has many parameters or its parameters are very long we should break the line after every comma `,` 533 | 534 | ```java 535 | loadPicture(context, "http://ribot.co.uk/images/sexyjoe.jpg", mImageViewProfilePicture, clickListener, "Title of the picture"); 536 | ``` 537 | 538 | ```java 539 | loadPicture(context, 540 | "http://ribot.co.uk/images/sexyjoe.jpg", 541 | mImageViewProfilePicture, 542 | clickListener, 543 | "Title of the picture"); 544 | ``` 545 | -------------------------------------------------------------------------------- /android/kotlin/README.md: -------------------------------------------------------------------------------- 1 | # Android/Kotlin style guidelines 2 | ###### Version 1.0.0 3 | 4 | ## 1 Project structure 5 | The project should follow standard [Android project guidelines](https://developer.android.com/studio/projects/index.html) 6 | however in short: 7 | ``` 8 | root/ 9 | └─ app/ 10 | └─ gradle/ 11 | └─ lib/ 12 | └─ miscFiles.txt 13 | ``` 14 | 15 | ## 2 Package structure 16 | 17 | ### 2.1 Applications 18 | The root structure should follow major source categories: 19 | ``` 20 | app/ 21 | └─ data/ 22 | └─ injection/ 23 | └─ receiver/ 24 | └─ service/ 25 | └─ ui/ 26 | ``` 27 | 28 | The `ui` category needs to be more granular based on the section and follow MVP organization. 29 | This means a login screen will have its own package with `contract` and `platform` sub packages. 30 | ``` 31 | ui/ 32 | └─ login/ 33 | └─ contract/ 34 | └─ platform/ 35 | ``` 36 | 37 | Each category has sub structures to increase the granularity. e.g. 38 | ``` 39 | data/ 40 | └─ webservice/ 41 | └─ database/ 42 | ``` 43 | 44 | ### 2.2 Libraries 45 | Similar to the Applications structure; the root structure should follow major source categories: 46 | ``` 47 | lib/ 48 | └─ api/ 49 | └─ data/ 50 | └─ injection/ 51 | └─ receiver/ 52 | └─ service/ 53 | └─ util/ 54 | ``` 55 | 56 | Each category has sub structures to increase the granularity. e.g. 57 | ``` 58 | api/ 59 | └─ account/ 60 | └─ devices/ 61 | ``` 62 | 63 | ## 3 File naming 64 | 65 | ### 3.1 Class files 66 | Class names should be written in [UpperCamelCase](http://en.wikipedia.org/wiki/CamelCase). 67 | 68 | For classes that extend an Android component, the name of the class should end with the name of the component; for example: 69 | * `SignInActivity` 70 | * `SignInFragment` 71 | * `ImageUploaderService` 72 | * `ChangePasswordDialog` 73 | 74 | ### 3.1 Resources files 75 | 76 | Resources file names are written in __lowercase_underscore__. e.g. 77 | * `ic_launcher` 78 | * `background_default` 79 | 80 | #### 3.1.1 Drawables 81 | 82 | ##### 3.1.1.1 Icons 83 | Icons should follow the naming scheme seen in [Material Icons](https://github.com/google/material-design-icons/) which 84 | follows the format `ic___`; the exception being launcher images which should be named `ic_launcher`. 85 | For example: 86 | 87 | * `ic_link_black_24dp.xml` 88 | * `ic_user_white_48dp.xml` 89 | 90 | 91 | ##### 3.1.1.2 Selector States 92 | Assuming a selector state requires an image instead of an embedded shape, each images should be 93 | named based on the main selector (`button_order` in the example) with the states as a suffix. e.g. 94 | 95 | | State | Suffix | Example | 96 | |--------------|--------------|-----------------------------| 97 | | Normal | `_normal` | `button_order_normal.9.png` | 98 | | Pressed | `_pressed` | `button_order_pressed.9.png` | 99 | | Focused | `_focused` | `button_order_focused.9.png` | 100 | | Disabled | `_disabled` | `button_order_disabled.9.png` | 101 | | Selected | `_selected` | `button_order_selected.9.png` | 102 | 103 | 104 | #### 3.1.2 Layout files 105 | Layout file names should be prefixed with the section the source code will be used by _without_ prefixing 106 | the Android component name. e.g. 107 | 108 | | Component | Class Name | Layout Name | 109 | | ---------------- | ---------------------- | --------------------- | 110 | | Activity | `LoginActivity` | `login.xml` | 111 | | Fragment | `SignUpFragment` | `sign_up.xml` | 112 | | Dialog | `ChangePasswordDialog` | `change_password.xml` | 113 | | AdapterView item | `PersonViewHolder` | `person.xml` | 114 | 115 | 116 | #### 3.1.3 Menu files 117 | Menu file names should match the parent layout naming, they should _not_ include `menu` as they are already 118 | separated by the `R.menu.*` reference. e.g. 119 | 120 | | Parent Layout | Menu Name | 121 | | ------------------ | -------------- | 122 | | `user_profile.xml` | `user_profile` | 123 | | `person.xml` | `person` | 124 | 125 | 126 | #### 3.1.4 Values files 127 | Resource files in the values folder should be __plural__; i.e.: 128 | * `strings.xml` 129 | * `styles.xml` 130 | * `colors.xml` 131 | * `dimens.xml` 132 | * `attrs.xml` 133 | 134 | 135 | # 4 Code guidelines 136 | 137 | ## 4.1 XML style rules 138 | 139 | ### 4.1.1 Prefer self closing tags 140 | When possible self closing tags should be used. e.g. 141 | 142 | ```xml 143 | 147 | ``` 148 | 149 | **Not** 150 | ```xml 151 | 155 | 156 | ``` 157 | 158 | ### 4.1.2 Resource naming 159 | Resources should follow __lowercase_underscore__ naming, the exception being Ids, Styles and Themes (described below) 160 | 161 | #### 4.1.2.1 IDs 162 | IDs should have a suffix indicating the element or category type in [LowerCamelCase](http://en.wikipedia.org/wiki/CamelCase). e.g. 163 | 164 | | Element | Suffix | 165 | | -------------------- | ------------------- | 166 | | `TextView` | `someTextView` | 167 | | `ImageView` | `anImageView` | 168 | | `Button` | `helpButton` | 169 | | `Menu Item` | `loginMenuItem` | 170 | | `Action Mode Menu` | `artistActionMenu` | 171 | | `Context Menu` | `personContextMenu` | 172 | 173 | 174 | #### 4.1.2.2 Strings 175 | String names start with a prefix that identifies the section they belong to. For example `registration_email_hint` 176 | or `registration_name_hint`. If a string __doesn't belong__ to any section then a simple name should be used. e.g. 177 | 178 | | Name | Value | 179 | | ----------------------- | --------------------------------------- | 180 | | `done` | `Done` | 181 | | `general_network_error` | `There was an unknown network error` | 182 | 183 | 184 | #### 4.1.2.3 Styles and Themes 185 | Unlike the rest of resources, style names are written in [UpperCamelCase](http://en.wikipedia.org/wiki/CamelCase). 186 | 187 | ### 4.1.3 Attribute ordering 188 | Attributes should follow the auto ordering that Android Studio enforces; in general this is 189 | 190 | 1. `id` 191 | 2. `style` and `theme` 192 | 3. `layout_width`, `layout_height`, and `layout_weight` 193 | 4. Other attributes sorted alphabetically 194 | 5. Non-`android` namespace items (e.g. `app`) sorted alphabetically 195 | 6. `tools` namespace items sorted alphabetically 196 | 197 | 198 | ## 4.2 Kotlin language rules 199 | 200 | ### 4.2.1 Always handle exceptions 201 | While you may think that your code will never encounter this error condition or that it is not important to handle, 202 | ignoring exceptions creates mines in your code for someone to eventually trip over. Every exception should be handled 203 | by one of the following methods: 204 | 205 | * Add an explicit `throws` to the method definition (e.g. `fun someErrorProneFunction() throws IOException`) 206 | * Catch the exception and cancel future functionality (silently failures should be avoided) 207 | * Catch the exception and use a default value instead 208 | 209 | You should **Never** throw [Unchecked Exceptions](https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html) 210 | 211 | 212 | ### 4.2.2 Catch generic Exceptions sparingly 213 | In many cases there are good ways to handle specific issues (e.g. a `FileNotFoundException` should be caught to inform 214 | the user that the file doesn't exist). If this is caught by a generic Exception then there is no good way to inform the 215 | user. However there are some cases that we only care if the process fails, not the reason it failed; in these cases it 216 | is alright to catch generic Exceptions. 217 | 218 | For Example: 219 | 220 | ```kotlin 221 | try { 222 | someComplicatedIOFunction() // may throw IOException 223 | someComplicatedParsingFunction() // may throw ParsingException 224 | someComplicatedSecurityFunction() // may throw SecurityException 225 | } catch (exception: Exception) { // I'll just catch all exceptions (generic) 226 | handleError() // with one generic handler! 227 | } 228 | ``` 229 | 230 | See the reason why and some alternatives [here](https://source.android.com/source/code-style.html#dont-catch-generic-exception) 231 | 232 | ### 4.2.3 Don't use finalizers 233 | _We don't use finalizers. There are no guarantees as to when a finalizer will be called, or even that it will be called at all. 234 | In most cases, you can do what you need from a finalizer with good exception handling. If you absolutely need it, define a 235 | `close()` method (or the like) and document exactly when that method needs to be called. See `InputStream` for an example. 236 | In this case it is appropriate but not required to print a short log message from the finalizer, as long as it is not expected 237 | to flood the logs._ - ([Android code style guidelines](https://source.android.com/source/code-style.html#dont-use-finalizers)) 238 | 239 | 240 | ### 4.2.4 Fully qualify imports 241 | While excessive methods and imports can be stripped out with proguard, it is good practice to minimize the amount of 242 | code included. More information can be found [here](https://source.android.com/source/code-style.html#fully-qualify-imports) 243 | 244 | For Example: 245 | an import should read `import foo.Bar` instead of `import foo.*` 246 | 247 | 248 | ## 4.3 Kotlin style rules 249 | 250 | ### 4.3.1 Fields definition and naming 251 | Fields should be defined at the __top of the file__ and they should follow the naming rules listed below. 252 | 253 | * private constants `private const val` are all caps (e.x. `MY_CONST`) and located in the [companion object](https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects) 254 | * public constants `public const val` are all caps (e.x. `MY_CONST`) and located in the [companion object](https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects) 255 | * all other fields should follow [LowerCamelCase](http://en.wikipedia.org/wiki/CamelCase) conventions 256 | 257 | Example: 258 | 259 | ```kotlin 260 | public class MyClass { 261 | companion object { 262 | private const val FOO = 1 263 | public const val SOME_CONSTANT = 42 264 | } 265 | 266 | private var privateVar: Int 267 | protected var protectedVar: Int 268 | public var publicVar: Int 269 | } 270 | ``` 271 | 272 | ### 4.3.3 Treat acronyms as words 273 | | Good | Bad | 274 | | ---------------- | ---------------- | 275 | | `XmlHttpRequest` | `XMLHTTPRequest` | 276 | | `getCustomerId` | `getCustomerID` | 277 | | `String url` | `String URL` | 278 | | `long id` | `long ID` | 279 | 280 | 281 | ### 4.3.4 Use spaces for indentation 282 | Use __4 space__ indentations for blocks: 283 | 284 | ```kotlin 285 | if (i == 1) { 286 | i++; 287 | } 288 | ``` 289 | 290 | Use __8 space__ indentations for line wraps: 291 | ```kotlin 292 | val instrument = 293 | someLongExpression(that, wouldNotFit, on, one, line) 294 | ``` 295 | 296 | ### 4.3.5 Use standard brace style 297 | Braces go on the same line as the code before them and are always required, except in the case of replacing 298 | the ternary operator. e.g. 299 | 300 | ```kotlin 301 | class MyClass { 302 | fun test() { 303 | if (something) { 304 | // ... 305 | } else if (somethingElse) { 306 | // ... 307 | } else { 308 | // ... 309 | } 310 | } 311 | 312 | //An example of an if...else replacement for a ternary 313 | fun ternaryFunction(someValue: String): Int { 314 | return if (someValue.isEmpty()) 0 else 1 315 | } 316 | } 317 | ``` 318 | 319 | ### 4.3.6 Limit variable scope 320 | _The scope of local variables should be kept to a minimum (Effective Java Item 29). By doing so, you increase the readability 321 | and maintainability of your code and reduce the likelihood of error. Each variable should be declared in the innermost block 322 | that encloses all uses of the variable._ 323 | 324 | _Local variables should be declared at the point they are first used. Nearly every local variable declaration should contain an 325 | initializer. If you don't yet have enough information to initialize a variable sensibly, you should postpone the declaration 326 | until you do._ - ([Android code style guidelines](https://source.android.com/source/code-style.html#limit-variable-scope)) 327 | 328 | 329 | ### 4.3.7 Logging guidelines 330 | For simplicity [Timber](https://github.com/JakeWharton/timber) should be used for logging in place of the default 331 | one provided by Android. 332 | 333 | ### 4.3.8 Class member ordering 334 | There is no single correct solution for this but using a __logical__ and __consistent__ order will improve code 335 | readability. It is recommendable to use the following order: 336 | 337 | 1. Constants 338 | 2. Fields 339 | 1. Constants 340 | 2. `@Inject` 341 | 4. `@BindExtra` 342 | 5. `@BindArgument` 343 | 6. `@SaveState` 344 | 7. Member Variables 345 | 3. Constructors 346 | 4. Override methods and callbacks (public or private) 347 | 5. Public methods 348 | 6. Private methods 349 | 7. Inner classes 350 | 8. Nested classes or interfaces 351 | 352 | Example: 353 | 354 | ```kotlin 355 | public class MainActivity: Activity { 356 | companion object { 357 | private const val ARG_FOO = "TAG" 358 | } 359 | 360 | @Inject //Dagger 361 | Prefs prefs 362 | 363 | @BindExtra //PocketKnife 364 | var userId: String? 365 | 366 | @SaveState //PocketKnife 367 | var currentPosition: Int = 0 368 | 369 | private var title: String? 370 | 371 | public fun setTitle(title: String?) { 372 | this.title = title; 373 | } 374 | 375 | override public fun onCreate() { 376 | //... 377 | } 378 | 379 | private fun setUpView() { 380 | //... 381 | } 382 | 383 | //the `inner` keyword indicates the class is a child of `MainActivity` 384 | private inner class AnInnerClass { 385 | //... 386 | } 387 | 388 | //nested classes are static by default in kotlin 389 | class ANestedClass { 390 | //... 391 | } 392 | } 393 | ``` 394 | 395 | If your class is extending and __Android component__ such as an Activity or a Fragment, it is a good practise to order the 396 | override methods so that they __match the component's lifecycle__. For example, if you have an Activity that implements 397 | `onCreate()`, `onDestroy()`, `onPause()` and `onResume()`, then the correct order is: 398 | 399 | ```kotlin 400 | public class MainActivity: Activity { 401 | override public fun onCreate() {} 402 | 403 | override public fun onResume() {} 404 | 405 | override public fun onPause() {} 406 | 407 | override public fun onDestroy() {} 408 | } 409 | ``` 410 | 411 | ### 4.3.9 Parameter ordering in methods 412 | When programming for Android, it is quite common to define methods that take a `Context`. If you are writing a method 413 | like this, then the __Context__ must be the __first__ parameter. 414 | 415 | The opposite case are __callback__ interfaces that should always be the __last__ parameter. 416 | 417 | Examples: 418 | 419 | ```kotlin 420 | // Context always go first 421 | public fun loadUser(context: Context, userId: Int): User? 422 | 423 | // Callbacks always go last 424 | public fun loadUserAsync(context: Context, userId: Int, callback: UserCallback) 425 | ``` 426 | 427 | ### 4.3.10 String constants, naming and values 428 | Many elements of the Android SDK such as `SharedPreferences`, `Bundle` or `Intent` use a key-value pair approach so 429 | it's very likely that even for a small app you end up having to write a lot of String constants. 430 | 431 | When using one of these components, you __must__ define the keys as a `static final` fields and they should be prefixed as indicated below. 432 | 433 | | Element | Prefix | 434 | | ----------------- | ----------------- | 435 | | SharedPreferences | `PREF_` | 436 | | Bundle | `BUNDLE_` | 437 | | Fragment Arguments | `ARGUMENT_` | 438 | | Intent Extra | `EXTRA_` | 439 | | Intent Action | `ACTION_` | 440 | 441 | Note that the arguments of a Fragment - `Fragment.getArguments()` - are also a Bundle. However, because this is a quite common 442 | use of Bundles, we define a different prefix for them. 443 | 444 | Example: 445 | 446 | ```kotlin 447 | companion object { 448 | // Note the value of the field is the same as the name to avoid duplication issues 449 | public const val PREF_EMAIL = "PREF_EMAIL" 450 | public const val BUNDLE_AGE = "BUNDLE_AGE" 451 | public const val ARGUMENT_USER_ID = "ARGUMENT_USER_ID" 452 | 453 | // Intent-related items use full package name as value 454 | public const val EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME" 455 | public const val ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER" 456 | } 457 | ``` 458 | 459 | ### 4.3.11 Arguments in Fragments and Activities 460 | When data is passed into an `Activity `or `Fragment` via `Intents` or a `Bundles`, the keys for the different values 461 | __must__ follow the rules described in the section above. 462 | 463 | When an `Activity` or `Fragment` expect arguments, it should provide a `static public` method that facilitates the 464 | creation of the `Fragment` or `Intent`. 465 | 466 | In the case of Activities the method is usually called `getStartIntent()` 467 | 468 | ```kotlin 469 | companion object { 470 | public fun getLocation(context: Context, user: User): Location { 471 | val location = Location(user) //performs some work 472 | return location 473 | } 474 | } 475 | ``` 476 | 477 | For Fragments it's named `newInstance()` and it handles the creation of the Fragment with the right arguments. 478 | 479 | ```kotlin 480 | companion object { 481 | public fun newInstance(user: User): UserFragment { 482 | val fragment = UserFragment() 483 | 484 | val args = Bundle() 485 | args.putParcelable(ARGUMENT_USER, user) 486 | fragment.setArguments(args) 487 | 488 | return fragment 489 | } 490 | } 491 | 492 | ``` 493 | 494 | ### 4.3.12 Line length limit 495 | Code lines should not exceed __160 characters__. If the line is longer than this limit there are usually two options to reduce its length: 496 | 497 | * Extract a local variable or method (Preferable). 498 | * Apply line-wrapping to divide a single line into multiple ones. 499 | 500 | There are two __exceptions__ where is possible to have lines longer than 160: 501 | 502 | * Lines that are not possible to split, e.g. long URLs in comments. 503 | * `package` and `import` statements. 504 | 505 | 506 | #### 4.3.12.1 Line-wrapping strategies 507 | There isn't an exact formula that explains how to line-wrap and quite often different solutions are valid. However 508 | there are a few rules that can be applied to common cases. 509 | 510 | __Method chain case__ 511 | 512 | When multiple methods are chained in the same line - for example when using Builders - every call to a method should 513 | go in its own line, breaking the line before the `.` 514 | 515 | ```kotlin 516 | Picasso.with(context).load("http://ribot.co.uk/images/sexyjoe.jpg").into(imageView) 517 | ``` 518 | 519 | ```kotlin 520 | Picasso.with(context).apply { 521 | load("http://ribot.co.uk/images/sexyjoe.jpg") 522 | into(imageView) 523 | } 524 | ``` 525 | 526 | __Long parameters case__ 527 | 528 | When a method has many parameters or its parameters are very long we should break the line after every comma `,` 529 | 530 | ```kotlin 531 | loadPicture(context, "http://ribot.co.uk/images/sexyjoe.jpg", imageViewProfilePicture, clickListener, "Title of the picture"); 532 | ``` 533 | 534 | ```kotlin 535 | loadPicture(context, 536 | "http://ribot.co.uk/images/sexyjoe.jpg", 537 | imageViewProfilePicture, 538 | clickListener, 539 | "Title of the picture"); 540 | ``` 541 | --------------------------------------------------------------------------------