{"filename":"kotlin-springboot-best-practices-cursorrules-prompt-file.mdc","content":"---\ndescription: \"Cursor rules for Kotlin Springboot Best Practices.\"\nglobs: **/*\nalwaysApply: false\n---\n# Kotlin Coding Best Practices for Spring Boot Development\n\n## Project Structure and Organization\n\n1.\tGroup your source code into clearly defined packages like controller, service, repository, and model to separate concerns and improve maintainability.\n2.\tOrganize your file system so that each directory mirrors the Kotlin package name (e.g. put com.myapp.users under src/main/kotlin/com/myapp/users).\n3.\tName each Kotlin file after the primary class or concept it contains to make the codebase easier to navigate and understand.\n4.\tAvoid vague file names like Utils.kt; instead, use concise and meaningful names that reflect the purpose of the file’s contents.\n5.\tPlace your Spring Boot application entry point in the root package and structure sub-packages by layer or feature to help Spring scan and organize components efficiently.\n\n## Coding Style and Conventions\n\n1.\tUse PascalCase for class and object names, camelCase for functions and variables, and UPPER_SNAKE_CASE for constants to follow Kotlin naming conventions and improve readability.\n2.\tDeclare variables using `val` by default, and only use `var` when mutation is necessary to promote safer, more predictable code.\n    ```kotlin\n    val maxConnections = 10    // immutable reference\n    var currentUsers = 0       // mutable, try to avoid if possible\n    ``` \n3.\tLimit the scope of variables to where they are actually used—inside functions or smaller blocks—to avoid accidental misuse and make code easier to follow.\n4.\tFormat your code consistently using 4-space indentation, proper spacing around operators and commas, and short, focused functions to improve clarity and maintainability.\n5.\tWrite clear and expressive code instead of clever one-liners; break complex logic into intermediate variables or well-named functions to improve readability.\n6.\tName classes, functions, and variables descriptively to convey intent, and avoid vague suffixes like '-Manager' or '-Helper' that don’t add meaning.\n7.\tKeep property getters and setters simple and free of heavy logic; if complex behavior is needed, move it into a separate method to keep property access predictable.\n\n## Idiomatic Kotlin Usage\n\n1.\tUse data class to define DTOs and entities so you get useful methods like `equals()` and `copy()` without writing boilerplate code.\n2.\tReplace overloaded constructors with default and named parameters to simplify function calls and make them more expressive.\n    ```kotlin\n    // Kotlin – use default parameters\n    fun createConnection(host: String, secure: Boolean = true) { … }\n\n    createConnection(\"example.com\")                      // uses default secure=true\n    createConnection(host = \"test.com\", secure = false)  // named arg for clarity\n    ``` \n3.\tUse `when` expressions instead of long `if-else` chains to write cleaner, more readable conditional logic that clearly handles each case.\n4.\tCreate extension functions instead of utility classes to add reusable behavior to existing types in a more natural and readable way.\n    ```kotlin\n    fun String.capitalizeFirst(): String = replaceFirstChar { it.uppercaseChar() }\n\n    println(\"kotlin\".capitalizeFirst())  // prints \"Kotlin\"\n    ```\n5.\tUse scope functions like `apply`, `let`, `also`, `run`, and `with` to reduce repetition and clearly express object configuration or null-safe operations.\n6.\tDeclare variables as nullable only when necessary, and handle them using safe-call operators (`?.`) and the Elvis operator (`?:`) to avoid runtime crashes.\n7.\tAvoid using the not-null assertion (`!!`) and instead provide fallback values or explicit null checks to write safer and more predictable code.\n8.\tHandle platform types from Java APIs immediately by explicitly casting them to `String` or `String?` to avoid spreading nullability uncertainty in your Kotlin code.\n9.\tUse Kotlin’s functional collection operations like `filter`, `map`, and `forEach` instead of manual loops to write concise and expressive data transformation logic.\n    ```kotlin\n    // Imperative approach\n    val activeUsers = mutableListOf<User>()\n    for (user in users) {\n        if (user.isActive) activeUsers.add(user)\n    }\n\n    // Idiomatic functional approach\n    val activeUsers = users.filter { it.isActive }\n    ``` \n10.\tConvert simple functions into single-expression functions when the logic is clear, to eliminate unnecessary syntax and improve code brevity.\n    ```kotlin\n    fun toDto(entity: User) = UserDto(name = entity.name, email = entity.email)\n    ``` \n11.\tBuild strings using string templates (`$var` or `${expression}`) instead of concatenation, and use triple-quoted strings for clean multi-line text.\n\n## Implementation Patterns and Design\n\n1.\tInject dependencies via constructor parameters using `val` to keep them immutable and to align with Spring and Kotlin idioms.\n    ```kotlin\n    @Service\n    class OrderService(\n        private val orderRepo: OrderRepository,\n        private val notifier: Notifier\n    ) {\n        // ...\n    }\n    ``` \n2.\tKeep classes `final` by default, and let Spring’s 'all-open' plugin handle proxy generation so you don’t need to manually add the open modifier.\n3.\tUse Kotlin’s `object` declaration for true singletons or stateless utility holders instead of static methods or Java-style singletons.\n4.\tFavor composition by combining small, focused classes or using higher-order functions instead of relying on deep inheritance hierarchies.\n5.\tDefine sealed classes when a type has a limited, closed set of variants to enforce exhaustive handling and improve type safety in `when` expressions.\n    ```kotlin\n    sealed class Result<out T>\n    data class Success<T>(val data: T): Result<T>()\n    data class Error(val exception: Throwable): Result<Nothing>()\n    ``` \n6.\tUse enum class to model fixed sets of constants that may contain logic, avoiding magic strings or raw values in business logic.\n7.\tReturn nullable types, sealed classes, or result wrappers instead of throwing exceptions for expected scenarios like “not found” or “invalid input”.\n8.\tAlways `use` the use function to safely manage and close resources like streams and file handles, ensuring they are closed even if an exception occurs.\n    ```kotlin\n    FileInputStream(\"data.txt\").use { stream ->\n        // read from stream \n    } // stream is automatically closed here\n    ``` \n9.\tMinimize visibility of your components by using `private` or `internal` where possible, and only expose what’s truly necessary as public.\n10.\tUse Kotlin coroutines with suspend functions and coroutine builders like `launch` or `async` to write clean, asynchronous backend code without callback hell.\n11.\tLeverage Kotlin’s standard library features like `lazy`, `observable`, `infix`, and operator overloading to write concise, expressive, and idiomatic code.\n12.\tUse immutable data class entities with `val` fields and Kotlin’s JPA plugin to satisfy JPA requirements while keeping your models safe and thread-friendly.\n13.\tWrite unit tests for your business logic using dependency injection and pure functions to make testing straightforward and independent from Spring’s context.\n"}