-
Notifications
You must be signed in to change notification settings - Fork 0
Kotlin code style
Kotlin code of Spine SDK follows the standard conventions with the extensions and modifications described below.
Kotlin conventions for property names encourage using SCREAMING_SNAKE_CASE
for constant properties.
Unlike in Kotlin conventions, we prefer lowerCamelCase
for naming such properties for the following reasons.
Compare "$group:$infix-fat-cli:$version"
and "$GROUP:$INFIX-fat-cli:$VERSION"
.
Uppercase constants usually attract more attention than real interesting text around them.
There's no need to SCREAM
about them ALL_THE_TIME
.
This is more important than №1 above.
Suppose you have a dependency defined via constant that end up with interpolated string such as "$GROUP:$INFIX-fat-cli:$VERSION"
.
The dependency is used in several modules of your project.
After some time, you figure out that the version to be used depends on some condition.
So VERSION
is no longer a const val
but simply val
.
So, by standard convention, you now need to rename it.
In turn, the constant which previously defined the dependency is also no longer a constant because its value is interpolated from non-constant.
Now this property also has to be renamed. A slight extension of logic resulted in a cascade of changes.
If we do not SCREAM
about constants, we hide the implementation details (at this micro level), making our code is less "fragile".
Consider this code:
public object ProtoData {
private const val VERSION: String = "1.0.1"
public const val GROUP: String = "io.spine.protodata"
internal const val INFIX: String = "protodata"
//...
public const val COORDINATES: String = "$GROUP:$INFIX-cli:$VERSION"
}
public data class ProtocPluginArtifact {
private const val VERSION: String = "1.0.2"
public val coordinates: String = "${ProtoData.GROUP}:${ProtoData.INFIX}-protoc:$VERSION:exe@jar"
}
The ProtoData.COORDINATES
property is a constant, while ProtocPluginArtifact.coordinates
is not because.
It could not be declared as const val
because interpolated from constant (!) properties of another object, ProtoData
.
In order to reduce the mental load on remembering if a property is a real constant or not, we relaxed the constant value name rule.
It is still make sense to follow the SCREAMING_CASE
rule for cases related to performance optimization.
Instead of Gradle version catalogs we declare dependencies as Kotlin objects.
We started using dependency objects in order to avoid string-based mess when when wording with dependencies. Then Version catalog feature appeared in Gradle, and were in incubation state for some time. Gradle started promoting this feature more recently.
Assuming the amount of planned work for the production code of Spine SDK, we don't see much benefits in migrating to Gradle Version Catalogs in the near future. Still, it should be done to reduce the cognitive load on new developers of the SDK.
See the
io.spine.internal.dependency
package underbuildSrc
of a Spine SDK subproject for details.
Versions and Maven coordinates of dependencies are defined using lowerCamelCase
.
Kotlin provides a powerful way of teaching existing code new tricks.
Here are basic principles regarding extensions to follow in our code:
-
Make extensions
internal
or evenprivate
if you are not sure they are going to be popular outside of the module you work on.
We can always promote it later.
We do not want to introduce much of naïve extension noise. -
If your extensions are really
public
, gather them in separate files.
They are easier to find this way. -
Name the public extension files after this pattern:
<TypeOrTypes>Exts.kt
.
For example,FileTypesExts.kt
,CharSequenceExts.kt
.
TheExts
stands forExtensions
, but is shorter, easier to read and type, and almost equally understood.
When concatenating a long string, start each continuation line with a space character:
const val text = "This is an important error message." +
" Here are some details regarding what happened." +
" See the documentation for more information."
It's easier to spot and understand as a continuation. Oftentimes, people miss a space character in concatenated messages. With the starting space, it happens less often.