Skip to content

Commit d82d00c

Browse files
committed
docs: Add Kotlin language standards (#33)
Document our Kotlin language standards for upcoming projects. * Add `kotlin.md` and reference it in `coding-standards.md`.
1 parent 4aa930f commit d82d00c

2 files changed

Lines changed: 175 additions & 0 deletions

File tree

coding-standards.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Additional language-specific standards are available in the following documents:
1616

1717
* [TypeScript](coding-standards/typescript.md)
1818
* [Swift](coding-standards/swift.md)
19+
* [Kotlin](coding-standards/kotlin.md)
1920

2021

2122
## Abbreviations

coding-standards/kotlin.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Silvermine Coding Standards Specific to Kotlin
2+
3+
## Formatting
4+
5+
### Whitespace
6+
7+
* No trailing whitespace
8+
* One blank line between method definitions
9+
* No blank line after opening brace
10+
* No blank line before closing brace
11+
* One space after colon in type declarations
12+
* No space before colon in type declarations
13+
* One newline at the end of the file
14+
15+
```kotlin
16+
// Good:
17+
class MyClass {
18+
fun myFunction1() {
19+
// ...
20+
}
21+
22+
fun myFunction2() {
23+
// ...
24+
}
25+
}
26+
27+
val name: String = "John"
28+
29+
// Bad:
30+
class MyClass{
31+
32+
fun myFunction1() {
33+
// ...
34+
}
35+
fun myFunction2() {
36+
// ...
37+
}
38+
39+
}
40+
41+
val name : String = "John"
42+
```
43+
44+
### Line Length
45+
46+
* Break long lines at logical points
47+
* Indent continuation lines by our standard indentation
48+
49+
```kotlin
50+
// Good:
51+
val result = someFunctionWithAVeryLongName(
52+
parameter1,
53+
parameter2,
54+
parameter3
55+
)
56+
57+
// Bad:
58+
val result = someFunctionWithAVeryLongName(parameter1, parameter2, parameter3)
59+
```
60+
61+
## Naming Conventions
62+
63+
### General
64+
65+
* Use camelCase for variable and function names
66+
* Use PascalCase for type names (classes, structs, enums)
67+
* Use `UPPER_SNAKE_CASE` for constants
68+
* Use backticks with descriptive sentences for test functions
69+
* Use descriptive names that convey meaning
70+
71+
```kotlin
72+
// Good:
73+
val userAge = 30
74+
fun sendEmail(to: String) { /* ... */ }
75+
class UserProfile { /* ... */ }
76+
const val MAX_CONNECTIONS = 100
77+
@Test fun `test that user can be created`() { /* ... */ }
78+
79+
// Bad:
80+
val user_age = 30
81+
fun SendEmail(to: String) { /* ... */ }
82+
class userProfile { /* ... */ }
83+
const val max_connections = 100
84+
@Test fun testUserCreation() { /* ... */ }
85+
```
86+
87+
## Language Features
88+
89+
### Null Safety
90+
91+
* Prefer non-nullable types over nullable types.
92+
* Use the safe call operator (`?.`) or the Elvis operator (`?:`) to handle
93+
nullable types.
94+
* Avoid the not-null assertion operator (`!!`) unless you are absolutely sure that
95+
the value is not null.
96+
97+
```kotlin
98+
// Good:
99+
val name: String? = "John"
100+
val length = name?.length ?: 0
101+
102+
// Bad:
103+
val name: String? = "John"
104+
val length = name!!.length
105+
```
106+
107+
### Data Classes
108+
109+
* Use data classes to represent simple data-holding classes.
110+
* Keep data classes immutable by using `val` instead of `var`.
111+
112+
```kotlin
113+
// Good:
114+
data class User(val name: String, val age: Int)
115+
116+
// Bad:
117+
class User(var name: String, var age: Int)
118+
```
119+
120+
### Coroutines
121+
122+
* Use coroutines for asynchronous programming.
123+
* Use `suspend` functions for long-running operations.
124+
* Use `viewModelScope` or `lifecycleScope` to launch coroutines in Android.
125+
126+
```kotlin
127+
// Good:
128+
viewModelScope.launch {
129+
val user = repository.getUser()
130+
// ...
131+
}
132+
```
133+
134+
## Comments
135+
136+
* Write comments to explain *why* code is written a certain way, not *what* the
137+
code does.
138+
* Use KDoc for documenting public APIs.
139+
140+
```kotlin
141+
// Good:
142+
/**
143+
* Returns the user with the given ID.
144+
* @param userId The ID of the user to return.
145+
* @return The user with the given ID, or null if not found.
146+
*/
147+
fun getUser(userId: String): User? {
148+
// ...
149+
}
150+
151+
// Bad:
152+
// Gets the user
153+
fun getUser(userId: String): User? {
154+
// ...
155+
}
156+
```
157+
158+
## Testing
159+
160+
* Follow the given-when-then pattern for structuring tests.
161+
162+
```kotlin
163+
@Test
164+
fun `test that user can be created`() {
165+
// Given
166+
val user = User("John", 30)
167+
168+
// When
169+
val result = repository.saveUser(user)
170+
171+
// Then
172+
assertTrue(result)
173+
}
174+
```

0 commit comments

Comments
 (0)