Code Style

This guide outlines the coding conventions and style guidelines for TrustWeave.

Overview

TrustWeave follows Kotlin coding conventions with some project-specific guidelines:

  • Kotlin Style Guide – follows official Kotlin style guide
  • ktlint – automated formatting with ktlint
  • Naming Conventions – clear, descriptive names
  • Documentation – comprehensive KDoc comments

Code Formatting

ktlint Configuration

The project uses ktlint for code formatting. Format your code:

1
2
3
4
5
# Check formatting
./gradlew ktlintCheck

# Auto-format
./gradlew ktlintFormat

Format on Save

Configure your IDE to format on save:

IntelliJ IDEA:

  1. Install ktlint plugin
  2. Enable “Reformat code on save”
  3. Configure ktlint as formatter

Naming Conventions

Classes

Use PascalCase for class names:

1
2
3
class MyCustomDidMethod : DidMethod {
    // ...
}

Functions

Use camelCase for function names:

1
2
3
suspend fun createDid(options: DidCreationOptions): DidDocument {
    // ...
}

Variables

Use camelCase for variable names:

1
2
val issuerDid = "did:key:issuer"
val credentialSubject = buildJsonObject { }

Constants

Use UPPER_SNAKE_CASE for constants:

1
2
3
4
companion object {
    const val DEFAULT_TIMEOUT = 30000L
    const val MAX_RETRIES = 3
}

Code Structure

File Organization

Organize files logically:

1
2
3
4
5
6
7
8
9
10
11
// Package declaration
package org.trustweave.example

// Imports
import org.trustweave.did.*
import kotlinx.coroutines.runBlocking

// Class/object definitions
class Example {
    // ...
}

Function Length

Keep functions concise:

  • Short functions – prefer functions under 20 lines
  • Complex logic – extract to separate functions
  • Single responsibility – each function should do one thing

Class Size

Keep classes focused:

  • Single responsibility – each class should have one purpose
  • Composition over inheritance – prefer composition
  • Interfaces – use interfaces for abstractions

Documentation

KDoc Comments

Document public APIs:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * Creates a DID using the specified method.
 *
 * @param method The DID method to use (e.g., "key", "web")
 * @param options Configuration options for DID creation
 * @return Result containing the created DID document or error
 */
suspend fun createDid(
    method: String,
    options: DidCreationOptions
): Result<DidDocument> {
    // ...
}

Inline Documentation

Add comments for complex logic:

1
2
// Generate identifier from public key using multibase encoding
val identifier = multibase.encode(key.publicKey)

Error Handling

Result Types

Use Result<T> for operations that can fail:

1
2
3
4
5
6
7
8
9
10
11
12
suspend fun createDid(): Result<DidDocument> {
    return try {
        // Implementation
        Result.success(didDocument)
    } catch (e: Exception) {
        Result.failure(
            TrustWeaveError.DidCreationFailed(
                reason = e.message ?: "Unknown error"
            )
        )
    }
}

Error Types

Use structured error types:

1
2
3
4
5
sealed class TrustWeaveError : Exception() {
    data class DidCreationFailed(val reason: String) : TrustWeaveError()
    data class DidResolutionFailed(val reason: String) : TrustWeaveError()
    // ...
}

Testing

Test Naming

Use descriptive test names:

1
2
3
4
5
6
7
8
9
@Test
fun testCreateDidWithEd25519Algorithm() = runBlocking {
    // ...
}

@Test
fun testResolveDidReturnsDocument() = runBlocking {
    // ...
}

Test Organization

Organize tests logically:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class DidMethodTest {
    @Test
    fun testCreateDid() = runBlocking {
        // ...
    }

    @Test
    fun testResolveDid() = runBlocking {
        // ...
    }

    @Test
    fun testUpdateDid() = runBlocking {
        // ...
    }
}

Best Practices

Immutability

Prefer immutable data:

1
2
3
4
5
6
7
8
9
// Prefer immutable data classes
data class DidDocument(
    val id: String,
    val verificationMethod: List<VerificationMethod>
)

// Avoid mutable state
// ❌ var document: DidDocument? = null
// ✅ val document: DidDocument? = null

Null Safety

Use Kotlin’s null safety features:

1
2
3
4
5
6
7
8
// Use nullable types when appropriate
val didDocument: DidDocument? = resolveDid(did)

// Use safe calls
didDocument?.verificationMethod?.first()

// Use Elvis operator for defaults
val method = didDocument?.verificationMethod?.first() ?: throw NotFoundException()

Extension Functions

Use extension functions for utilities:

1
2
3
fun DidDocument.toJson(): JsonObject {
    // Conversion logic
}

Scope Functions

Use scope functions appropriately:

1
2
3
4
5
6
7
8
9
10
// Use `let` for null checks
didDocument?.let { document ->
    // Use document
}

// Use `apply` for configuration
val config = MyConfig().apply {
    endpoint = "https://example.com"
    timeout = 30000L
}

Code Review Guidelines

Checklist

Before submitting code for review:

  • Code is formatted (./gradlew ktlintCheck)
  • All tests pass (./gradlew test)
  • Public APIs are documented
  • Error handling is appropriate
  • Code follows naming conventions
  • No hardcoded values (use constants)
  • No commented-out code

Review Feedback

When reviewing code:

  • Be constructive and respectful
  • Focus on code quality, not style preferences
  • Suggest improvements, don’t just point out issues
  • Explain why changes are needed

Next Steps

References


This site uses Just the Docs, a documentation theme for Jekyll.