1## Sample code in Kotlin modules 2 3### Background 4 5Public API can (and should!) have small corresponding code snippets that 6demonstrate functionality and usage of a particular API. These are often exposed 7inline in the documentation for the function / class - this causes consistency 8and correctness issues as this code is not compiled against, and the underlying 9implementation can easily change. 10 11KDoc (JavaDoc for Kotlin) supports a `@sample` tag, which allows referencing the 12body of a function from documentation. This means that code samples can be just 13written as a normal function, compiled and linted against, and reused from other 14modules such as tests! This allows for some guarantees on the correctness of a 15sample, and ensuring that it is always kept up to date. 16 17### Enforcement 18 19There are still some visibility issues here - it can be hard to tell if a 20function is a sample, and is used from public documentation - so as a result we 21have lint checks to ensure sample correctness. 22 23Primarily, there are three requirements when using sample links: 24 251. All functions linked to from a `@sample` KDoc tag must be annotated with 26 `@Sampled` 272. All sample functions annotated with `@Sampled` must be linked to from a 28 `@sample` KDoc tag 293. All sample functions must live inside a separate `samples` library 30 submodule - see the section on module configuration below for more 31 information. 32 33This enforces visibility guarantees, and make it easier to know that a sample is 34a sample. This also prevents orphaned samples that aren't used, and remain 35unmaintained and outdated. 36 37### Sample usage 38 39The follow demonstrates how to reference sample functions from public API. It is 40also recommended to reuse these samples in unit tests / integration tests / test 41apps / library demos where possible to help ensure that the samples work as 42intended. 43 44**Public API:** 45 46``` 47/* 48 * Fancy prints the given [string] 49 * 50 * @sample androidx.printer.samples.fancySample 51 */ 52fun fancyPrint(str: String) ... 53``` 54 55**Sample function:** 56 57``` 58package androidx.printer.samples 59 60import androidx.printer.fancyPrint 61 62@Sampled 63fun fancySample() { 64 fancyPrint("Fancy!") 65} 66``` 67 68**Generated documentation visible on d.android.com / within Android Studio** 69 70``` 71fun fancyPrint(str: String) 72 73Fancy prints the given [string] 74 75<code> 76 import androidx.printer.fancyPrint 77 78 fancyPrint("Fancy!") 79<code> 80``` 81 82Warning: Only the body of the function is used in generated documentation, so 83any other references to elements defined outside the body of the function (such 84as variables defined within the sample file) will not be visible. To ensure that 85samples can be easily copy and pasted without errors, make sure that any 86references are defined within the body of the function. 87 88### Module configuration 89 90The following module setups should be used for sample functions: 91 92**Per-module samples** 93 94For library groups with relatively independent sub-libraries. This is the 95recommended project setup, and should be used in most cases. 96 97Gradle project name: `:foo-library:foo-module:foo-module-samples` 98 99``` 100foo-library/ 101 foo-module/ 102 samples/ 103``` 104 105**Group-level samples** 106 107For library groups with strongly related samples that want to share code and be 108reused across a library group, a singular shared samples library can be created. 109In most cases this is discouraged - samples should be small and show the usage 110of a particular API / small set of APIs, instead of more complicated usage 111combining multiple APIs from across libraries. For these cases a sample 112application is more appropriate. 113 114Gradle project name: `:foo-library:foo-library-samples` 115 116``` 117foo-library/ 118 foo-module/ 119 bar-module/ 120 samples/ 121``` 122 123**Samples module configuration** 124 125Samples modules are published to GMaven so that they are available to Android 126Studio, which displays referenced samples as hover-over pop-ups. 127 128To achieve this, samples modules must declare the same MavenGroup and `publish` 129as the library(s) they are samples for. 130