Code Example Style Guide

This guide establishes standards for code examples in TrustWeave documentation to ensure consistency, clarity, and correctness.

General Principles

  1. Runnable: All examples should be copy-paste ready and executable
  2. Complete: Include all necessary imports and setup
  3. Idiomatic: Use Kotlin best practices and idioms
  4. Contextual: Show appropriate error handling for the context
  5. Clear: Use descriptive variable names and comments

Error Handling Patterns

Pattern 1: Quick Start / Prototypes (getOrThrow)

When to use:

  • Quick start examples
  • Prototypes and demos
  • Test code
  • Simple scripts
  • Documentation examples where error handling would obscure the main point

Example:

1
2
3
// Quick start pattern
val did = TrustWeave.createDid().getOrThrow()
val credential = TrustWeave.issueCredential(...).getOrThrow()

Marking: Add comment when using this pattern:

1
2
3
// Quick start: using getOrThrow() for simplicity
// In production, use fold() for proper error handling
val did = TrustWeave.createDid().getOrThrow()

Pattern 2: Production Code (fold)

When to use:

  • Production code examples
  • Error handling guides
  • When demonstrating error recovery
  • User-facing applications

Example:

1
2
3
4
5
6
7
8
9
10
// Production pattern: explicit error handling
val result = TrustWeave.createDid()
result.fold(
    onSuccess = { did ->
        processDid(did)
    },
    onFailure = { error ->
        handleError(error)
    }
)

Pattern 3: Result Chaining (map/flatMap)

When to use:

  • Chaining multiple operations
  • Functional style examples
  • When demonstrating result transformation

Example:

1
2
3
4
5
6
7
// Chaining pattern
val credential = TrustWeave.createDid()
    .map { did ->
        TrustWeave.issueCredential(issuerDid = did.id, ...)
    }
    .flatMap { it }  // Unwrap nested Result
    .getOrThrow()

Import Statements

Required Imports

Always include complete imports at the top of examples:

1
2
3
4
5
6
7
8
9
10
11
12
// TrustWeave imports
import org.trustweave.TrustWeave
import org.trustweave.core.*
import org.trustweave.did.*
import org.trustweave.credential.models.VerifiableCredential

// Kotlinx imports
import kotlinx.coroutines.runBlocking
// Note: buildJsonObject is only needed for standalone JSON creation outside DSL
// Within DSL blocks (subject {}, credential {}, etc.), use DSL syntax instead
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put

Import Organization

  1. TrustWeave imports (grouped by module)
  2. Kotlinx imports
  3. Standard library imports
  4. Third-party imports

DSL vs buildJsonObject

Within DSL blocks, use the DSL syntax:

1
2
3
4
5
6
7
8
9
10
11
12
subject {
    id("did:key:holder")
    "name" to "Alice"
    "address" {
        "street" to "123 Main St"
        "city" to "New York"
    }
    "grades" to arrayOfObjects(
        { "course" to "CS101"; "grade" to "A" },
        { "course" to "MATH101"; "grade" to "B" }
    )
}

Outside DSL blocks (for standalone JSON creation), use buildJsonObject:

1
2
3
4
val jsonPayload = buildJsonObject {
    put("id", "did:key:holder")
    put("name", "Alice")
}

Code Comments

When to Comment

  • Explain non-obvious behavior
  • Clarify why a pattern is used
  • Note important considerations
  • Warn about production vs testing

Comment Style

1
2
3
4
5
6
7
8
9
10
11
// Good: Explains why
// Using getOrThrow() for quick start - in production use fold()
val did = TrustWeave.createDid().getOrThrow()

// Good: Clarifies behavior
// This creates an in-memory wallet (testing only)
val wallet = TrustWeave.createWallet(holderDid).getOrThrow()

// Bad: States the obvious
// Create a DID
val did = TrustWeave.createDid().getOrThrow()

Variable Naming

Naming Conventions

  • Use descriptive names: issuerDid, credentialSubject, walletId
  • Avoid abbreviations: vccredential, didDocdidDocument
  • Use domain terms: holderDid, issuerKeyId, credentialId

Examples

1
2
3
4
5
6
7
8
9
10
// Good: Descriptive names
val issuerDid = "did:key:issuer"
val issuerKeyId = "did:key:issuer#key-1"
// Note: For DSL usage, build subject directly in credential block
// For standalone JSON, use: val credentialSubject = buildJsonObject { ... }

// Bad: Abbreviations
val iDid = "did:key:issuer"
val kId = "did:key:issuer#key-1"
val cs = buildJsonObject { ... }

Package Declarations

When to Include

  • Complete, runnable examples
  • Examples in getting-started guides
  • Tutorial examples

When to Omit

  • API reference snippets
  • Inline code examples
  • Quick reference examples

Format

1
2
3
4
5
6
7
package com.example.TrustWeave.quickstart

// ... imports ...

fun main() = runBlocking {
    // ... code ...
}

Version Tags

When to Tag

  • Examples using version-specific features
  • Examples that may not work in all versions
  • Breaking change examples

Format

1
2
3
4
> **Version:** 1.0.0-SNAPSHOT
> **API:** TrustWeave Facade

This example uses the TrustWeave facade API available in 1.0.0+.

Context Indicators

Marking Context

Add context indicators to examples:

1
2
3
4
5
6
7
8
9
10
11
12
// Quick start example
val did = TrustWeave.createDid().getOrThrow()

// Production example
val result = TrustWeave.createDid()
result.fold(
    onSuccess = { did -> /* handle */ },
    onFailure = { error -> /* handle */ }
)

// Testing example
val testDid = TrustWeave.createDid().getOrThrow()

Complete Example Template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.example.TrustWeave.example

// TrustWeave imports
import org.trustweave.TrustWeave
import org.trustweave.core.*
import org.trustweave.did.*

// Kotlinx imports
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put

/**
 * Example: Creating and using a DID
 *
 * This example demonstrates:
 * - Creating a DID with default options
 * - Resolving a DID
 * - Error handling patterns
 */
fun main() = runBlocking {
    // Create TrustWeave instance
    val TrustWeave = TrustWeave.create()

    // Create DID with error handling
    val didResult = TrustWeave.createDid()
    didResult.fold(
        onSuccess = { did ->
            println("Created DID: ${did.id}")

            // Resolve the DID
            val resolution = TrustWeave.resolveDid(did.id).getOrThrow()
            if (resolution.document != null) {
                println("Resolved DID document")
            }
        },
        onFailure = { error ->
            when (error) {
                is TrustWeaveError.DidMethodNotRegistered -> {
                    println("Method not registered: ${error.method}")
                }
                else -> {
                    println("Error: ${error.message}")
                }
            }
        }
    )
}

Best Practices

  1. Always include imports for complete examples
  2. Use descriptive variable names that match domain terminology
  3. Add context comments when using patterns that might not be obvious
  4. Show error handling appropriate to the context
  5. Include expected output for complete examples
  6. Tag version-specific examples
  7. Use consistent formatting (ktlint-compliant)

Anti-Patterns to Avoid

  1. Missing imports - Examples won’t compile
  2. Inconsistent error handling - Confuses readers
  3. Unclear variable names - Hard to understand
  4. Missing context - Readers don’t know when to use pattern
  5. Incomplete examples - Can’t run as-is
  6. Version-specific code without tags - May not work in all versions

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