agentic-team-templates 0.13.2 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +6 -1
  2. package/package.json +1 -1
  3. package/src/index.js +91 -13
  4. package/src/index.test.js +95 -1
  5. package/templates/cpp-expert/.cursorrules/concurrency.md +211 -0
  6. package/templates/cpp-expert/.cursorrules/error-handling.md +170 -0
  7. package/templates/cpp-expert/.cursorrules/memory-and-ownership.md +220 -0
  8. package/templates/cpp-expert/.cursorrules/modern-cpp.md +211 -0
  9. package/templates/cpp-expert/.cursorrules/overview.md +87 -0
  10. package/templates/cpp-expert/.cursorrules/performance.md +223 -0
  11. package/templates/cpp-expert/.cursorrules/testing.md +230 -0
  12. package/templates/cpp-expert/.cursorrules/tooling.md +312 -0
  13. package/templates/cpp-expert/CLAUDE.md +242 -0
  14. package/templates/csharp-expert/.cursorrules/aspnet-core.md +311 -0
  15. package/templates/csharp-expert/.cursorrules/async-patterns.md +206 -0
  16. package/templates/csharp-expert/.cursorrules/dependency-injection.md +206 -0
  17. package/templates/csharp-expert/.cursorrules/error-handling.md +235 -0
  18. package/templates/csharp-expert/.cursorrules/language-features.md +204 -0
  19. package/templates/csharp-expert/.cursorrules/overview.md +92 -0
  20. package/templates/csharp-expert/.cursorrules/performance.md +251 -0
  21. package/templates/csharp-expert/.cursorrules/testing.md +282 -0
  22. package/templates/csharp-expert/.cursorrules/tooling.md +254 -0
  23. package/templates/csharp-expert/CLAUDE.md +360 -0
  24. package/templates/java-expert/.cursorrules/concurrency.md +209 -0
  25. package/templates/java-expert/.cursorrules/error-handling.md +205 -0
  26. package/templates/java-expert/.cursorrules/modern-java.md +216 -0
  27. package/templates/java-expert/.cursorrules/overview.md +81 -0
  28. package/templates/java-expert/.cursorrules/performance.md +239 -0
  29. package/templates/java-expert/.cursorrules/persistence.md +262 -0
  30. package/templates/java-expert/.cursorrules/spring-boot.md +262 -0
  31. package/templates/java-expert/.cursorrules/testing.md +272 -0
  32. package/templates/java-expert/.cursorrules/tooling.md +301 -0
  33. package/templates/java-expert/CLAUDE.md +325 -0
  34. package/templates/javascript-expert/.cursorrules/overview.md +5 -3
  35. package/templates/javascript-expert/.cursorrules/typescript-deep-dive.md +348 -0
  36. package/templates/javascript-expert/CLAUDE.md +34 -3
  37. package/templates/kotlin-expert/.cursorrules/coroutines.md +237 -0
  38. package/templates/kotlin-expert/.cursorrules/error-handling.md +149 -0
  39. package/templates/kotlin-expert/.cursorrules/frameworks.md +227 -0
  40. package/templates/kotlin-expert/.cursorrules/language-features.md +231 -0
  41. package/templates/kotlin-expert/.cursorrules/overview.md +77 -0
  42. package/templates/kotlin-expert/.cursorrules/performance.md +185 -0
  43. package/templates/kotlin-expert/.cursorrules/testing.md +213 -0
  44. package/templates/kotlin-expert/.cursorrules/tooling.md +258 -0
  45. package/templates/kotlin-expert/CLAUDE.md +276 -0
  46. package/templates/swift-expert/.cursorrules/concurrency.md +230 -0
  47. package/templates/swift-expert/.cursorrules/error-handling.md +213 -0
  48. package/templates/swift-expert/.cursorrules/language-features.md +246 -0
  49. package/templates/swift-expert/.cursorrules/overview.md +88 -0
  50. package/templates/swift-expert/.cursorrules/performance.md +260 -0
  51. package/templates/swift-expert/.cursorrules/swiftui.md +260 -0
  52. package/templates/swift-expert/.cursorrules/testing.md +286 -0
  53. package/templates/swift-expert/.cursorrules/tooling.md +285 -0
  54. package/templates/swift-expert/CLAUDE.md +275 -0
@@ -0,0 +1,149 @@
1
+ # Kotlin Error Handling
2
+
3
+ Sealed types for expected failures. Exceptions for exceptional conditions. Never swallow errors.
4
+
5
+ ## Sealed Result Types
6
+
7
+ ```kotlin
8
+ // Model expected outcomes explicitly
9
+ sealed interface Result<out T> {
10
+ data class Success<T>(val value: T) : Result<T>
11
+ data class Failure(val error: AppError) : Result<Nothing>
12
+ }
13
+
14
+ sealed interface AppError {
15
+ data class NotFound(val entity: String, val id: String) : AppError
16
+ data class Validation(val errors: Map<String, String>) : AppError
17
+ data class Conflict(val message: String) : AppError
18
+ data class Unauthorized(val reason: String) : AppError
19
+ }
20
+
21
+ // Usage in services
22
+ class UserService(private val userRepo: UserRepository) {
23
+ suspend fun register(request: CreateUserRequest): Result<User> {
24
+ val errors = validate(request)
25
+ if (errors.isNotEmpty()) {
26
+ return Result.Failure(AppError.Validation(errors))
27
+ }
28
+
29
+ val existing = userRepo.findByEmail(request.email)
30
+ if (existing != null) {
31
+ return Result.Failure(AppError.Conflict("Email already registered"))
32
+ }
33
+
34
+ val user = userRepo.create(request)
35
+ return Result.Success(user)
36
+ }
37
+ }
38
+
39
+ // Handling in routes/controllers
40
+ when (val result = userService.register(request)) {
41
+ is Result.Success -> call.respond(HttpStatusCode.Created, result.value)
42
+ is Result.Failure -> when (result.error) {
43
+ is AppError.Validation -> call.respond(HttpStatusCode.BadRequest, result.error)
44
+ is AppError.Conflict -> call.respond(HttpStatusCode.Conflict, result.error)
45
+ is AppError.NotFound -> call.respond(HttpStatusCode.NotFound, result.error)
46
+ is AppError.Unauthorized -> call.respond(HttpStatusCode.Unauthorized, result.error)
47
+ }
48
+ }
49
+ ```
50
+
51
+ ## kotlin.Result and runCatching
52
+
53
+ ```kotlin
54
+ // For wrapping operations that might throw
55
+ val result: kotlin.Result<User> = runCatching {
56
+ userRepository.findById(id)
57
+ }
58
+
59
+ result
60
+ .onSuccess { user -> logger.info("Found user: ${user.id}") }
61
+ .onFailure { error -> logger.error("Failed to find user", error) }
62
+
63
+ val user = result.getOrNull()
64
+ val userOrDefault = result.getOrDefault(User.anonymous())
65
+ val userOrElse = result.getOrElse { error ->
66
+ logger.warn("Falling back to anonymous", error)
67
+ User.anonymous()
68
+ }
69
+
70
+ // Chaining
71
+ val displayName = runCatching { fetchUser(id) }
72
+ .map { it.displayName }
73
+ .getOrDefault("Unknown User")
74
+ ```
75
+
76
+ ## Validation
77
+
78
+ ```kotlin
79
+ // require — preconditions (throws IllegalArgumentException)
80
+ fun createOrder(customerId: String, items: List<OrderItem>) {
81
+ require(customerId.isNotBlank()) { "customerId must not be blank" }
82
+ require(items.isNotEmpty()) { "Order must have at least one item" }
83
+ require(items.size <= MAX_ITEMS) { "Maximum $MAX_ITEMS items allowed" }
84
+ }
85
+
86
+ // check — state invariants (throws IllegalStateException)
87
+ fun ship(order: Order) {
88
+ check(order.status == OrderStatus.PAID) { "Can only ship paid orders" }
89
+ check(order.items.isNotEmpty()) { "Cannot ship empty order" }
90
+ }
91
+
92
+ // requireNotNull / checkNotNull
93
+ val user = requireNotNull(userRepo.findById(id)) {
94
+ "User $id must exist after authentication"
95
+ }
96
+ ```
97
+
98
+ ## Exception Best Practices
99
+
100
+ ```kotlin
101
+ // Custom exceptions for domain boundaries
102
+ class OrderProcessingException(
103
+ val orderId: OrderId,
104
+ message: String,
105
+ cause: Throwable? = null
106
+ ) : RuntimeException(message, cause)
107
+
108
+ // Catch specific exceptions
109
+ try {
110
+ paymentService.charge(order)
111
+ } catch (e: PaymentDeclinedException) {
112
+ logger.warn("Payment declined for order ${order.id}", e)
113
+ return Result.Failure(AppError.PaymentDeclined(e.reason))
114
+ } catch (e: PaymentTimeoutException) {
115
+ logger.error("Payment timeout for order ${order.id}", e)
116
+ throw OrderProcessingException(order.id, "Payment timed out", e)
117
+ }
118
+
119
+ // Never catch Exception broadly without rethrowing CancellationException
120
+ try {
121
+ suspendingOperation()
122
+ } catch (e: CancellationException) {
123
+ throw e // Always rethrow — coroutine cancellation must propagate
124
+ } catch (e: Exception) {
125
+ logger.error("Operation failed", e)
126
+ }
127
+ ```
128
+
129
+ ## Anti-Patterns
130
+
131
+ ```kotlin
132
+ // Never: empty catch blocks
133
+ try { riskyOperation() }
134
+ catch (e: Exception) { } // Silently swallowed
135
+
136
+ // Never: catch Throwable (catches OutOfMemoryError, StackOverflowError)
137
+ try { work() }
138
+ catch (e: Throwable) { } // Too broad
139
+ // Use: catch (e: Exception) at most
140
+
141
+ // Never: using exceptions for control flow
142
+ try { return items.first { it.isActive } }
143
+ catch (e: NoSuchElementException) { return null }
144
+ // Use: items.firstOrNull { it.isActive }
145
+
146
+ // Never: wrapping without context
147
+ catch (e: Exception) { throw RuntimeException(e) }
148
+ // Add context: throw OrderProcessingException(orderId, "Failed to process", e)
149
+ ```
@@ -0,0 +1,227 @@
1
+ # Kotlin Frameworks
2
+
3
+ Ktor for Kotlin-first, Spring Boot for ecosystem breadth. Both done idiomatically.
4
+
5
+ ## Ktor
6
+
7
+ ```kotlin
8
+ fun main() {
9
+ embeddedServer(Netty, port = 8080) {
10
+ configureRouting()
11
+ configureSerialization()
12
+ configureAuthentication()
13
+ }.start(wait = true)
14
+ }
15
+
16
+ // Routing
17
+ fun Application.configureRouting() {
18
+ routing {
19
+ route("/api/v1") {
20
+ userRoutes()
21
+ orderRoutes()
22
+ }
23
+ }
24
+ }
25
+
26
+ fun Route.userRoutes() {
27
+ route("/users") {
28
+ get {
29
+ val users = userService.findAll()
30
+ call.respond(users)
31
+ }
32
+
33
+ get("/{id}") {
34
+ val id = UserId(call.parameters["id"]
35
+ ?: return@get call.respond(HttpStatusCode.BadRequest, "Missing id"))
36
+
37
+ when (val result = userService.findById(id)) {
38
+ is Result.Success -> call.respond(result.value)
39
+ is Result.Failure -> when (result.error) {
40
+ is AppError.NotFound -> call.respond(HttpStatusCode.NotFound)
41
+ else -> call.respond(HttpStatusCode.InternalServerError)
42
+ }
43
+ }
44
+ }
45
+
46
+ post {
47
+ val request = call.receive<CreateUserRequest>()
48
+ when (val result = userService.create(request)) {
49
+ is Result.Success -> call.respond(HttpStatusCode.Created, result.value)
50
+ is Result.Failure -> call.respond(HttpStatusCode.BadRequest, result.error)
51
+ }
52
+ }
53
+ }
54
+ }
55
+
56
+ // Content negotiation
57
+ fun Application.configureSerialization() {
58
+ install(ContentNegotiation) {
59
+ json(Json {
60
+ prettyPrint = false
61
+ ignoreUnknownKeys = true
62
+ encodeDefaults = true
63
+ isLenient = false
64
+ })
65
+ }
66
+ }
67
+ ```
68
+
69
+ ## Spring Boot with Kotlin
70
+
71
+ ```kotlin
72
+ @SpringBootApplication
73
+ class Application
74
+
75
+ fun main(args: Array<String>) {
76
+ runApplication<Application>(*args)
77
+ }
78
+
79
+ // REST controller — Kotlin-idiomatic
80
+ @RestController
81
+ @RequestMapping("/api/v1/orders")
82
+ class OrderController(private val orderService: OrderService) {
83
+
84
+ @GetMapping("/{id}")
85
+ suspend fun getById(@PathVariable id: UUID): ResponseEntity<OrderResponse> {
86
+ return orderService.findById(OrderId(id.toString()))
87
+ ?.let { ResponseEntity.ok(OrderResponse.from(it)) }
88
+ ?: ResponseEntity.notFound().build()
89
+ }
90
+
91
+ @PostMapping
92
+ suspend fun create(@Valid @RequestBody request: CreateOrderRequest): ResponseEntity<OrderResponse> {
93
+ return when (val result = orderService.create(request)) {
94
+ is Result.Success -> ResponseEntity
95
+ .created(URI("/api/v1/orders/${result.value.id}"))
96
+ .body(OrderResponse.from(result.value))
97
+ is Result.Failure -> ResponseEntity
98
+ .badRequest()
99
+ .build()
100
+ }
101
+ }
102
+ }
103
+
104
+ // Configuration with Kotlin DSL
105
+ @Configuration
106
+ class SecurityConfig {
107
+ @Bean
108
+ fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
109
+ return http {
110
+ csrf { disable() }
111
+ authorizeHttpRequests {
112
+ authorize("/api/public/**", permitAll)
113
+ authorize("/actuator/health", permitAll)
114
+ authorize(anyRequest, authenticated)
115
+ }
116
+ oauth2ResourceServer { jwt { } }
117
+ sessionManagement { sessionCreationPolicy = SessionCreationPolicy.STATELESS }
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ ## Exposed (Kotlin SQL Framework)
124
+
125
+ ```kotlin
126
+ // Type-safe SQL — no string queries
127
+ object Users : Table("users") {
128
+ val id = uuid("id").autoGenerate()
129
+ val name = varchar("name", 200)
130
+ val email = varchar("email", 255).uniqueIndex()
131
+ val active = bool("active").default(true)
132
+ val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
133
+
134
+ override val primaryKey = PrimaryKey(id)
135
+ }
136
+
137
+ // Repository
138
+ class UserRepository(private val database: Database) {
139
+
140
+ suspend fun findByEmail(email: String): User? = dbQuery {
141
+ Users.selectAll()
142
+ .where { Users.email eq email }
143
+ .map { it.toUser() }
144
+ .singleOrNull()
145
+ }
146
+
147
+ suspend fun create(request: CreateUserRequest): User = dbQuery {
148
+ val id = Users.insert {
149
+ it[name] = request.name
150
+ it[email] = request.email
151
+ } get Users.id
152
+
153
+ findById(UserId(id.toString()))!!
154
+ }
155
+
156
+ private suspend fun <T> dbQuery(block: suspend () -> T): T =
157
+ newSuspendedTransaction(Dispatchers.IO) { block() }
158
+ }
159
+ ```
160
+
161
+ ## Ktor Client (HTTP)
162
+
163
+ ```kotlin
164
+ // Shared client instance with configuration
165
+ val httpClient = HttpClient(CIO) {
166
+ install(ContentNegotiation) { json() }
167
+ install(HttpTimeout) {
168
+ requestTimeoutMillis = 30_000
169
+ connectTimeoutMillis = 5_000
170
+ }
171
+ install(HttpRequestRetry) {
172
+ retryOnServerErrors(maxRetries = 3)
173
+ exponentialDelay()
174
+ }
175
+ }
176
+
177
+ // Type-safe API calls
178
+ suspend fun fetchGitHubUser(username: String): GitHubUser {
179
+ return httpClient.get("https://api.github.com/users/$username").body()
180
+ }
181
+ ```
182
+
183
+ ## Dependency Injection (Koin)
184
+
185
+ ```kotlin
186
+ // Module definition
187
+ val appModule = module {
188
+ single { Database.connect(get<DatabaseConfig>().url) }
189
+ single { UserRepository(get()) }
190
+ single { OrderRepository(get()) }
191
+ factory { UserService(get(), get()) }
192
+ factory { OrderService(get(), get()) }
193
+ }
194
+
195
+ // Ktor integration
196
+ fun Application.configureKoin() {
197
+ install(Koin) {
198
+ modules(appModule)
199
+ }
200
+ }
201
+
202
+ // Injection in routes
203
+ fun Route.userRoutes() {
204
+ val userService by inject<UserService>()
205
+ // ...
206
+ }
207
+ ```
208
+
209
+ ## Anti-Patterns
210
+
211
+ ```kotlin
212
+ // Never: blocking calls in coroutine context
213
+ suspend fun fetchData(): Data {
214
+ val response = okHttpClient.newCall(request).execute() // BLOCKS the thread
215
+ // Use: a suspend-compatible HTTP client (Ktor Client, suspend wrappers)
216
+ }
217
+
218
+ // Never: exposing mutable state from services
219
+ class UserService {
220
+ val users = mutableListOf<User>() // Anyone can mutate
221
+ // Use: private mutableListOf, expose as List
222
+ }
223
+
224
+ // Never: Java-style builder patterns (use named arguments + copy())
225
+ User.builder().name("Alice").email("a@b.com").build()
226
+ // Use: User(name = "Alice", email = "a@b.com")
227
+ ```
@@ -0,0 +1,231 @@
1
+ # Kotlin Language Features
2
+
3
+ Modern Kotlin used deliberately. Every feature exists for safety, clarity, or expressiveness.
4
+
5
+ ## Null Safety
6
+
7
+ ```kotlin
8
+ // The type system enforces null safety — respect it
9
+ fun findUser(email: String): User? {
10
+ return userRepository.findByEmail(email)
11
+ }
12
+
13
+ // Safe call chain
14
+ val cityName = user?.address?.city?.name
15
+
16
+ // Elvis operator for defaults
17
+ val displayName = user?.name ?: "Anonymous"
18
+
19
+ // Elvis with throw for required values
20
+ val userId = request.userId ?: throw IllegalArgumentException("userId is required")
21
+
22
+ // Smart casts — the compiler narrows for you
23
+ fun process(value: Any) {
24
+ if (value is String) {
25
+ println(value.length) // Smart cast to String
26
+ }
27
+ }
28
+
29
+ // Safe cast
30
+ val number = value as? Int // null if not Int, no ClassCastException
31
+
32
+ // NEVER: !! without proof
33
+ user!!.name // If user is null → NPE. Only use when you've verified externally.
34
+ // Prefer: requireNotNull(user) { "User must exist after authentication" }
35
+ ```
36
+
37
+ ### Rules
38
+
39
+ - `!!` is a code smell. Every usage needs a comment explaining why it's safe
40
+ - Prefer `requireNotNull()` or `checkNotNull()` — they provide meaningful error messages
41
+ - Use `?.let { }` for nullable transformations
42
+ - Return nullable types from functions that legitimately might not find a result
43
+
44
+ ## Data Classes
45
+
46
+ ```kotlin
47
+ // Immutable data carriers — the default for DTOs, events, value objects
48
+ data class CreateUserRequest(
49
+ val name: String,
50
+ val email: String,
51
+ val role: UserRole = UserRole.USER
52
+ )
53
+
54
+ // Defensive copying for collections
55
+ data class Order(
56
+ val id: OrderId,
57
+ val customerId: CustomerId,
58
+ val items: List<OrderItem>, // Immutable List, not MutableList
59
+ val status: OrderStatus,
60
+ val createdAt: Instant
61
+ )
62
+
63
+ // Non-destructive updates
64
+ val updatedOrder = order.copy(status = OrderStatus.SHIPPED)
65
+
66
+ // Value objects with validation
67
+ @JvmInline
68
+ value class Email(val value: String) {
69
+ init {
70
+ require(value.contains("@")) { "Invalid email: $value" }
71
+ }
72
+ }
73
+
74
+ @JvmInline
75
+ value class UserId(val value: String) {
76
+ init {
77
+ require(value.isNotBlank()) { "UserId must not be blank" }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ## Sealed Types
83
+
84
+ ```kotlin
85
+ // Exhaustive state modeling — the compiler enforces completeness
86
+ sealed interface PaymentResult {
87
+ data class Success(val transactionId: String, val processedAt: Instant) : PaymentResult
88
+ data class Failure(val errorCode: String, val message: String) : PaymentResult
89
+ data class Pending(val referenceId: String, val estimatedWait: Duration) : PaymentResult
90
+ }
91
+
92
+ // Exhaustive when — add a new subtype, get a compile error everywhere
93
+ fun describe(result: PaymentResult): String = when (result) {
94
+ is PaymentResult.Success -> "Paid: ${result.transactionId}"
95
+ is PaymentResult.Failure -> "Failed: ${result.message}"
96
+ is PaymentResult.Pending -> "Pending: ${result.referenceId}"
97
+ }
98
+
99
+ // Result modeling
100
+ sealed interface Result<out T> {
101
+ data class Success<T>(val value: T) : Result<T>
102
+ data class Failure(val error: AppError) : Result<Nothing>
103
+ }
104
+
105
+ sealed interface AppError {
106
+ data class NotFound(val entity: String, val id: String) : AppError
107
+ data class Validation(val errors: Map<String, String>) : AppError
108
+ data class Conflict(val message: String) : AppError
109
+ }
110
+ ```
111
+
112
+ ## Extension Functions
113
+
114
+ ```kotlin
115
+ // Add behavior to types without inheritance
116
+ fun String.toSlug(): String =
117
+ this.lowercase()
118
+ .replace(Regex("[^a-z0-9\\s-]"), "")
119
+ .replace(Regex("\\s+"), "-")
120
+ .trim('-')
121
+
122
+ // Scoped extensions for domain logic
123
+ fun List<Order>.totalRevenue(): BigDecimal =
124
+ this.filter { it.status == OrderStatus.COMPLETED }
125
+ .sumOf { it.total }
126
+
127
+ // Extension properties
128
+ val String.isValidEmail: Boolean
129
+ get() = this.matches(Regex("^[^@]+@[^@]+\\.[^@]+$"))
130
+
131
+ // Generic extensions
132
+ fun <T> T.also(block: (T) -> Unit): T {
133
+ block(this)
134
+ return this
135
+ }
136
+ ```
137
+
138
+ ## Scope Functions
139
+
140
+ ```kotlin
141
+ // let — transform nullable, scoped operations
142
+ val length = name?.let { it.trim().length }
143
+
144
+ // apply — configure objects
145
+ val connection = HttpClient().apply {
146
+ timeout = Duration.ofSeconds(30)
147
+ retries = 3
148
+ }
149
+
150
+ // run — execute block with receiver
151
+ val result = StringBuilder().run {
152
+ append("Hello")
153
+ append(" ")
154
+ append("World")
155
+ toString()
156
+ }
157
+
158
+ // also — side effects without changing the value
159
+ val user = createUser(request).also { logger.info("Created user: ${it.id}") }
160
+
161
+ // with — operate on an object
162
+ val summary = with(report) {
163
+ "$title: $total items, $revenue revenue"
164
+ }
165
+
166
+ // Rules:
167
+ // - let: nullable chains, scoped transformations
168
+ // - apply: object configuration
169
+ // - run: compute a result from a receiver
170
+ // - also: side effects (logging, validation)
171
+ // - with: multiple operations on same object (avoid for nullable)
172
+ ```
173
+
174
+ ## Collection Operations
175
+
176
+ ```kotlin
177
+ // Kotlin collections are immutable by default
178
+ val users: List<User> = fetchUsers() // Immutable
179
+ val mutableUsers: MutableList<User> = mutableListOf() // Explicit mutation
180
+
181
+ // Functional chains
182
+ val activeAdminEmails = users
183
+ .filter { it.isActive }
184
+ .filter { it.role == Role.ADMIN }
185
+ .map { it.email }
186
+ .sorted()
187
+
188
+ // groupBy, associateBy, partition
189
+ val (active, inactive) = users.partition { it.isActive }
190
+ val byDepartment = users.groupBy { it.department }
191
+ val byId = users.associateBy { it.id }
192
+
193
+ // Sequences for large collections (lazy evaluation)
194
+ val result = users.asSequence()
195
+ .filter { it.isActive }
196
+ .map { it.name }
197
+ .take(10)
198
+ .toList()
199
+
200
+ // buildList, buildMap, buildSet
201
+ val items = buildList {
202
+ add("first")
203
+ addAll(existingItems)
204
+ if (includeExtra) add("extra")
205
+ }
206
+ ```
207
+
208
+ ## Anti-Patterns
209
+
210
+ ```kotlin
211
+ // Never: !! without justification
212
+ user!!.name // NPE waiting to happen
213
+
214
+ // Never: var when val works
215
+ var name = "Alice" // Will it change? If not, use val
216
+
217
+ // Never: MutableList in public APIs
218
+ fun getUsers(): MutableList<User> // Caller can mutate your internal state
219
+ // Use: fun getUsers(): List<User>
220
+
221
+ // Never: Java-style static utilities
222
+ object StringUtils { fun format(s: String): String = ... }
223
+ // Use: extension functions — fun String.format(): String = ...
224
+
225
+ // Never: when without exhaustive matching on sealed types
226
+ when (result) {
227
+ is Success -> handle(result)
228
+ else -> {} // Silently ignores new subtypes
229
+ }
230
+ // Remove else — let the compiler catch missing cases
231
+ ```
@@ -0,0 +1,77 @@
1
+ # Kotlin Expert Overview
2
+
3
+ Principal-level Kotlin engineering. Deep language mastery, coroutines, multiplatform, and idiomatic patterns.
4
+
5
+ ## Scope
6
+
7
+ This guide applies to:
8
+ - Backend services (Ktor, Spring Boot, Quarkus)
9
+ - Android applications (Jetpack Compose, Architecture Components)
10
+ - Kotlin Multiplatform (KMP) — shared code across Android, iOS, web, desktop
11
+ - CLI tools and scripting
12
+ - Libraries and Maven/Gradle artifacts
13
+ - Data processing and streaming
14
+
15
+ ## Core Philosophy
16
+
17
+ Kotlin is a pragmatic language. It gives you safety, expressiveness, and interoperability — use all three.
18
+
19
+ - **Null safety is the foundation.** The type system distinguishes nullable from non-nullable. Respect it — no `!!` without proof.
20
+ - **Immutability by default.** `val` over `var`, immutable collections, data classes. Mutation is explicit and intentional.
21
+ - **Conciseness without cleverness.** Kotlin lets you write less code. That doesn't mean you should write unreadable code.
22
+ - **Coroutines are structured.** Structured concurrency is not optional — every coroutine has a scope, every scope has a lifecycle.
23
+ - **Interop is a feature, not a compromise.** Kotlin's Java interop is seamless. Use Java libraries freely, but write Kotlin idiomatically.
24
+ - **If you don't know, say so.** Admitting uncertainty is professional. Guessing at coroutine behavior you haven't verified is not.
25
+
26
+ ## Key Principles
27
+
28
+ 1. **Null Safety Is Non-Negotiable** — No `!!` without documented justification. Use safe calls, elvis, and smart casts
29
+ 2. **Immutability by Default** — `val`, `List` (not `MutableList`), `data class`, `copy()`
30
+ 3. **Structured Concurrency** — Every coroutine lives in a scope. No `GlobalScope`. No fire-and-forget
31
+ 4. **Extension Functions Over Utility Classes** — Extend types at the call site, not in static helpers
32
+ 5. **Sealed Types for State Modeling** — Exhaustive `when` expressions, impossible states are compile errors
33
+
34
+ ## Project Structure
35
+
36
+ ```
37
+ project/
38
+ ├── src/main/kotlin/com/example/myapp/
39
+ │ ├── Application.kt # Entry point
40
+ │ ├── config/ # Configuration
41
+ │ ├── domain/ # Core domain (no framework deps)
42
+ │ │ ├── model/ # Data classes, value objects, sealed types
43
+ │ │ ├── service/ # Domain services
44
+ │ │ └── event/ # Domain events
45
+ │ ├── application/ # Use cases, orchestration
46
+ │ │ ├── command/
47
+ │ │ ├── query/
48
+ │ │ └── port/ # Interfaces
49
+ │ ├── infrastructure/ # External concerns
50
+ │ │ ├── persistence/ # Database (Exposed, JPA, R2DBC)
51
+ │ │ ├── messaging/ # Kafka, RabbitMQ
52
+ │ │ └── client/ # HTTP clients
53
+ │ └── api/ # REST/gRPC endpoints
54
+ │ ├── route/ # Ktor routes or Spring controllers
55
+ │ └── dto/ # Request/response models
56
+ ├── src/test/kotlin/com/example/myapp/
57
+ │ ├── unit/
58
+ │ ├── integration/
59
+ │ └── architecture/
60
+ ├── build.gradle.kts
61
+ └── Dockerfile
62
+ ```
63
+
64
+ ## Definition of Done
65
+
66
+ A Kotlin feature is complete when:
67
+
68
+ - [ ] Compiles with zero warnings (`-Werror` or `allWarningsAsErrors = true`)
69
+ - [ ] All tests pass
70
+ - [ ] No `!!` without documented justification
71
+ - [ ] No `var` where `val` suffices
72
+ - [ ] No `MutableList`/`MutableMap` exposed in public APIs
73
+ - [ ] Coroutines use structured concurrency (no `GlobalScope`)
74
+ - [ ] Nullable types handled explicitly (no suppressed warnings)
75
+ - [ ] Detekt reports zero findings
76
+ - [ ] No `TODO` without an associated issue
77
+ - [ ] Code reviewed and approved