https://kotlinlang.org logo
Join Slack
Powered by
# codereview
  • g

    Gouri Panda

    12/01/2024, 11:23 PM
    Hi everyone! 👋 I’m excited (and a little nervous!) to share that I’m testing my very first app, WordFlipster, and I need your help to make it better! 🙌 WordFlipster is a fun word game where you reverse words to solve puzzles—it’s simple, challenging, and great for all ages! 🧩 Since I’m new to app development and still learning as I go, your feedback would mean the world to me. Here’s how you can help: 1. Opt-in to the closed test via this link: [https://groups.google.com/g/google-group-closed-testing-2] or [https://forms.gle/1TRSvwqavVzLiFmHA]. 2. Try out the game and explore the features. 3. Share your honest feedback—what you liked, what could be improved, or any bugs you find. The test only takes a few minutes, and you’ll get early access to something I’m truly passionate about creating. 🌟 I’m incredibly grateful for any support or advice you can offer as I learn the ropes of app development. Feel free to DM me if you have any questions. Thanks a ton in advance! ❤️
    🚫 2
  • g

    George Z

    12/03/2024, 7:49 PM
    Hi, I am writing some tests for a ViewModel using Mockk and I'd like to know you opinion. Is this a good way to test the
    isLoading
    state?
    Copy code
    @Test
        fun `loadMovies updates uiState.isLoading`() = runTest {
            coEvery { repository.getMovies(MovieCategory.DEFAULT) } coAnswers {
                delay(600)
                Resource.Success(emptyList())
            }
    
            assertFalse(viewModel.uiState.value.isLoading)
    
            viewModel.loadMovies(MovieCategory.DEFAULT)
    
            advanceTimeBy(200)
    
            assertTrue(viewModel.uiState.value.isLoading)
    
            advanceUntilIdle()
            assertFalse(viewModel.uiState.value.isLoading)
    
            coVerify { repository.getMovies(MovieCategory.DEFAULT) }
        }
    o
    • 2
    • 1
  • g

    groostav

    12/10/2024, 9:32 AM
    annoying problem (maybe actually solved with jvm's loosening of constructor rules in valhalla?): I want to create an exception instance. I already have its stack trace as a variable, so I want to create this exception, and then set its stack trace. I want to create a custom exception type for this purpose. What is the most idiomatic way to do this?
    Copy code
    class MyCustomException(val trace: List<StackTraceElement>): Exception(){
        init {
            stackTrace = trace.toTypedArray()
        }
    
        override fun fillInStackTrace() = this //interrupt call to dump back-trace into stack-trace
    }
    ?
    j
    h
    • 3
    • 5
  • p

    Paulo Cereda

    12/13/2024, 10:24 PM
    Friends, I had a great time trying to implement
    sleepsort
    in Kotlin. 😁 The best I could come up with is as follows (playground link):
    Copy code
    import kotlinx.coroutines.coroutineScope
    import kotlinx.coroutines.delay
    import kotlinx.coroutines.async
    import kotlinx.coroutines.awaitAll
    
    suspend fun main() {
        println(sleepsort(listOf(63, 32, 62, 14, 5)))
    }
    
    suspend fun sleepsort(list: List<Int>): List<Int> = coroutineScope {
        buildList {
            list.map { number ->
                async {
                    delay(number.toLong())
                    add(number)
                }
            }.awaitAll()
        }
    }
    Do you have any suggestions and/or improvements to make it better (or even worse)? Thank you so much, and season's greetings to everyone! 🎄
    j
    r
    • 3
    • 4
  • d

    Daniel Pitts

    12/17/2024, 5:39 PM
    Updated version of my Json building DSL. Feedback requested. README.md
    Copy code
    import com.stochastictinkr.json.*
    
    fun main() {
        val obj = jsonObject {
            "name"("John Doe")
            "age"(25)
            "address" {
                "number"(123)
                "street"("Main Street")
                "city"("Anytown")
                "state"("AS")
                "zip"(12345)
            }
            "phoneNumbers"[{
                add("555-1234")
                add("555-5678")
            }]
            "favoriteColor"(null)
            "averageScore"(85.5)
        }
        println(JsonWriter.Pretty.writeToString(obj))
    }
    Resulting JSON:
    Copy code
    {
      "name": "John Doe",
      "age": 25,
      "address": {
        "number": 123,
        "street": "Main Street",
        "city": "Anytown",
        "state": "AS",
        "zip": 12345
      },
      "phoneNumbers": [
        "555-1234",
        "555-5678"
      ],
      "favoriteColor": null,
      "averageScore": 85.5
    }
    c
    k
    d
    • 4
    • 10
  • e

    Edgar Avuzi

    12/22/2024, 7:45 AM
    Do you think if pipeline programming is good to put everywhere like this? I'm just so obsessed with it. It makes the code so clear, simple and straightforward. IMO. Like this: do steps one, two, three. And that's it. But one can say that the 3 usages of
    .let
    are redundant here (because there is no
    null
    to handle using
    ?.let
    ). Still this disadvantage does not outweight. IMO
    o
    a
    +2
    • 5
    • 7
  • a

    Ahmed

    01/17/2025, 10:04 AM
    For some reason the flow doesn't work as expected for my use case. More in 🧵
    s
    s
    • 3
    • 24
  • a

    arve

    01/21/2025, 1:26 PM
    Given a rather large 3rd party interface, I need to implement only a small handful methods. (for testing, i control the calling code)
    Copy code
    interface Alphabet {
        fun a(): String
        fun b(): String
        // and many more
        fun z(): String
    }
    I thought I had a really bright idea, since the following is valid syntax:
    Copy code
    class A : Alphabet by TODO("NOPE") {
        override fun a() = "a"
    }
    I was hoping the delegation would act as with actual objects, routing calls to the override if they were present, and throwing NotImplementedError otherwise. Unfortunately, the
    TODO()
    is evaluated on instantiation of A() and not during method call 😞
    Copy code
    // Hoping for
    A().a() == "a" // true
    A().b() // NotImplementedError
    
    // but got 
    A() // NotImplementedError
    Does anyone have an elegant way to partially implement an interface and default to NotImplementedError for the rest, without explicitly doing so for every single method?
    e
    d
    • 3
    • 7
  • m

    Mark

    01/22/2025, 3:25 AM
    For producing a
    StateFlow
    from another
    StateFlow
    without requiring a
    CoroutineScope
    (so no new coroutine):
    Copy code
    private class MappedStateFlow<T, R>(
        private val original: StateFlow<T>,
        private val transform: (T) -> R
    ) : StateFlow<R> {
        override val replayCache: List<R>
            get() = original.replayCache.map(transform)
    
        override val value: R
            get() = transform(original.value)
    
        override suspend fun collect(collector: FlowCollector<R>): Nothing {
            original.collect { collector.emit(transform(it)) }
        }
    }
    
    fun <T, R> StateFlow<T>.mapState(transform: (T) -> R): StateFlow<R> {
        return MappedStateFlow(this, transform)
    }
    e
    • 2
    • 28
  • e

    Eugen Martynov

    02/10/2025, 8:11 AM
    Is there way to have method reference for optional receiver?
    Copy code
    customKeyListener?.onCustomKeyPressed()
    something like
    Copy code
    customKeyListener::onCustomKeyPressed
    e
    m
    • 3
    • 7
  • r

    Richard

    03/05/2025, 7:27 AM
    What do you think of that file - having the Extension function right below the enum?
    Copy code
    enum class ToggleValue {
        YES,
        NO,
        UNKNOWN
    }
    
    val ToggleValue.asBoolean: Boolean? // this one
        get() = when (this) {
            ToggleValue.YES -> true
            ToggleValue.NO -> false
            ToggleValue.UNKNOWN -> null
        }
    
    val Boolean?.asToggleValue: ToggleValue
        get() = when (this) {
            true -> ToggleValue.YES
            false -> ToggleValue.NO
            null -> ToggleValue.UNKNOWN
        }
    j
    k
    +3
    • 6
    • 17
  • e

    Edgar Avuzi

    03/07/2025, 1:47 AM
    Hi, I recently started a small Kotlin project for the "Build Your Own Interpreter" challenge. It's purely for practice and has no open-source value. If you have time, I’d appreciate any feedback on Kotlin idioms, readability, and best practices. Tests aren’t fully implemented yet — I'll add them once the overall structure is settled. Thanks!
    k
    • 2
    • 1
  • m

    Mark

    03/08/2025, 2:20 PM
    I know it’s more standard to put
    Density
    as the receiver, but isn’t the API usage cleaner when doing this?
    Copy code
    fun TextUnit.scale(scale: Float, density: Density): TextUnit {
        if (this.isUnspecified) return this
        return with(density) {
            (scale * this@scale.toPx()).toSp()
        }
    }
    e
    z
    c
    • 4
    • 7
  • b

    Ben Madore

    03/11/2025, 1:31 AM
    I’ve got a conventions plugin, that has an extension containing a field:
    val artifactName: Property<String> = project.objects.property(String::class.java)
    that is consumed by maven-publish to set the name of the artifact (jar) to be published. a couple of times, due to copy paste errors, folks have complained about failure to publish to artifactory when in fact they’ve just used the same
    artifactName
    in multiple modules of a project. Does this approach make sense for identifying this case and proactively failing the build and alerting the user? Am i missing something much simpler?
    Copy code
    // Add a plugin to detect duplicate artifact names
    plugins.withId("maven-publish") {
        // Create a simple task that will run on every project to check for duplicate artifact names
        val checkDuplicateArtifactNames =
            tasks.register("checkDuplicateArtifactNames") {
                group = "verification"
                description = "Checks for duplicate artifact names across all projects"
    
                doLast {
                    // Map to store artifact names and their corresponding projects
                    val artifactMap = mutableMapOf<String, MutableList<String>>()
    
                    // Collect all artifact names from all projects
                    rootProject.allprojects.forEach { proj ->
                        val projExtension = proj.extensions.findByType(GDConventionsExtension::class.java)
                        if (projExtension != null && projExtension.artifactName.isPresent) {
                            val artifactName = projExtension.artifactName.get()
                            if (!artifactMap.containsKey(artifactName)) {
                                artifactMap[artifactName] = mutableListOf()
                            }
                            artifactMap[artifactName]?.add(proj.path)
                        }
                    }
    
                    // Find duplicates (artifact names used by more than one project)
                    val duplicates = artifactMap.filter { it.value.size > 1 }
    
                    // If duplicates are found, throw an error with details
                    if (duplicates.isNotEmpty()) {
                        val errorMessage = StringBuilder("\nDuplicate artifact names detected:\n")
    
                        duplicates.forEach { (artifactName, projects) ->
                            errorMessage.append("\n  Artifact name '$artifactName' is used by multiple projects:\n")
                            projects.forEach { projectPath ->
                                errorMessage.append("    - $projectPath\n")
                            }
                        }
    
                        errorMessage.append("\nPlease ensure each module has a unique artifactName in its fooConventions block.\n")
                        errorMessage.append("For example:\n")
                        errorMessage.append("gdConventions {\n")
                        errorMessage.append("    artifactName.set(\"unique-name\")\n")
                        errorMessage.append("}\n")
    
                        throw GradleException(errorMessage.toString())
                    }
                }
            }
    
        // Make sure the check runs as part of the build
        tasks.named("build").configure {
            dependsOn(checkDuplicateArtifactNames)
        }
    }
    • 1
    • 2
  • c

    czuckie

    03/19/2025, 9:21 AM
    What are opinions on extensive use of extension functions/properties in codebases? I've recently started working on a new codebase and it feels like every file I look at has things like:
    Copy code
    private fun String.asDomainSpecificObject(): DomainSpecificObject = ...
    I would prefer a function to handle such things that explicitly took a string. I thought the overwhelming view/opinion was that extension functions and properties were right when they extended the abstraction of the class that was being given an extension. Beyond initial confusion and my own opinion, is there any reason to avoid such use of extension functions/properties, or should I embrace it?
    h
    r
    c
    • 4
    • 11
  • v

    Vivek Modi

    04/04/2025, 9:21 PM
    Hey, I have a Profile UI where, when the user lands on the screen, I want to show a loading indicator while fetching the API response. If the request is successful, I display the user data; if not, I show an error message using a Flow. In the successful response, the user has three available actions: Delete Account, Change Password, and Logout. For Delete Account and Change Password, I need to navigate to another Compose screen, and I’m still using event flow for these actions. For Logout, I need to call an API. While the API call is in progress, I show a loading indicator, and stop it once the process is complete. On success, I clear the token and other relevant user data. In my ViewModel, I’m calling domain layer interfaces for login and profile operations. The data layer handles API requests, and both repositories return a Result. I combine these results using StateFlow.
    p
    • 2
    • 12
  • e

    Emre

    04/07/2025, 4:00 PM
    How can you define a ByteArray value class with a structural equals operator? Kotlin complains that Member with the name 'equals' is reserved for future releases.
    e
    • 2
    • 2
  • a

    Alex Kuznetsov

    04/11/2025, 5:51 PM
    Generally I'd use
    Language
    annotation on a String literal for syntax highlighting and such, for example
    Copy code
    @Language("SQL")
    val sql = "SELECT weight, name FROM boxes"
    But I'm reviewing code where parameters are annotated with it:
    Copy code
    `fun doSomething(@Language("JSON") payload: String) { ...
    why would we want to do that? what does it buy us?
    p
    k
    • 3
    • 5
  • s

    Sam Dukes

    04/16/2025, 8:52 AM
    Hi everyone, I've written an app which is intended to allow players of Tekken 8 to save combos they make in game or found online to allow them to practice while playing the game. I've used RoomDB & Datastore APIs for data persistence. I know there's definitely places I can improve but I would love it if someone was able to have a look at my code and give it a review. https://github.com/Dooques/FightingFlow Thanks in advance
    l
    • 2
    • 2
  • v

    Vivek Modi

    05/01/2025, 8:35 PM
    Hi I'm working on a
    Jetpack Compose
    screen that fetches contact data using a
    ContactViewModel
    . The ViewModel uses
    StateFlow
    , performs API calls through a
    ContactsApi
    , and includes email validation logic using a UseCase. It all works, but I want to refactor this to align more with Kotlin best practices, Jetpack architecture guidelines, and better separation of concerns.
    • 1
    • 11
  • c

    czuckie

    05/02/2025, 12:28 PM
    am I being a dummy? the other local variables shouldn't be considered JSON just because I annotated a single local variable right?
    c
    h
    • 3
    • 6
  • a

    Alex Kuznetsov

    05/06/2025, 12:44 PM
    Is there a reason commonly used
    runCatching
    catches a
    Throwable
    not an
    Exception
    ? Even official documentation states that • The
    Error
    subclass represents serious fundamental problems that an application might not be able to recover from by itself. These are problems that you generally would not attempt to handle, such as
    OutOfMemoryError
    or
    StackOverflowError
    . https://kotlinlang.org/docs/exceptions.html#exception-hierarchy Personally we use a slightly modified version of
    runCatching
    that only catches an
    Exception
    . What am I missing?
    j
    • 2
    • 1
  • d

    dany giguere

    05/25/2025, 3:17 PM
    Hello everyone. I don't have a java/kotlin background but I'd like to get your opinion on theses factory classes (used with the faker library). They are used for creating fake data when testing. I don't know if it makes sens for a kotlin dev. Or is there something better ? But here is the UserFactory: https://github.com/danygiguere/spring-boot-3-reactive-with-kotlin-coroutines/blob/main/src/main/kotlin/factory/UserFactory.kt and how I use it in a test: https://github.com/danygiguere/spring-boot-3-reactive-with-kotlin-coroutines/blob/[…]/kotlin/com/example/demo/factory/integration/UserFactoryTest.kt. Does it make sens or do you think Fixtures are better ?
    c
    e
    • 3
    • 5
  • d

    dany giguere

    06/03/2025, 9:56 PM
    I've created a checkPostOwnershipWebFilter (checkPostOwnership) to check if the Post to be updated or deleted is owned by the logged in user. How does it look to you ? Could I do better ? : https://github.com/danygiguere/spring-boot-3-reactive-with-kotlin-coroutines/commit/ad39b35d255afc55e6279dcae974490fd0838584#diff-c6813[…]94512d8R36
    k
    s
    • 3
    • 4
  • a

    arve

    06/06/2025, 10:17 AM
    What’s the most idiomatic way to attach a reified function to an interface? currently I’m adding an extension function next to the interface in the same file, but it’s not very discoverable: The user has to know about this and import it explicitly before use:
    Copy code
    interface IExample {
      fun <T> something(cls: KClass<T>)
    }
    
    inline fun <reified T> ITest.something() = something(T::class)
    Copy code
    val t: IExample = Example()
    // caller has to manually know about, and import extension function before they can do
    t.something<String>()
    j
    k
    l
    • 4
    • 7
  • z

    zt

    06/07/2025, 5:54 PM
    Im trying to design a DSL style API for ffmpeg filters and I just wanna get some feedback. The main idea is filters have inputs and outputs and can be connected to one another
    Copy code
    val graph = FilterGraph {
        // split input into 2 (default) outputs
        filter("split") {
            // get first output and assign to variable
            val tmp = output {
                filter("crop") {
                    option("out_w", "iw")
                    option("out_h", "ih/2")
                    option("x", 0)
                    option("y", 0)
                }
                // flip vertically 
                filter("vflip")
            }
            
            // get the second output
            output {
                // overlay tmp on top of this output
                filter("overlay", tmp)
            }
        }
    }
  • c

    czuckie

    06/16/2025, 12:54 PM
    apologies for the meta question (no code to show) but is everyone using
    turbine
    for their coroutine testing?
    j
    b
    c
    • 4
    • 4
  • z

    Zyle Moore

    06/26/2025, 6:17 AM
    I have a list containing 4 million ordered elements, but I'd like to extract the first from each group within that list. The list is kind of like a linear tree, the first element is the parent and all following elements (up to a point) are its children. I'm using a sequence, but it's kind of slow on KMP/JS Browser(~20 seconds to pull 200 elements). This is in a KMP react app, but this block is where the iteration happens.
    Copy code
    useEffect(setTopLevel, props.pluginElementMarkers) {
            val last = props.pluginElementMarkers.lastOrNull()
            if (last == null) {
                return@useEffect
            }
            val sequence = props.pluginElementMarkers.asSequence()
            val topLevelList = mutableListOf<PluginElementMarker>()
            var nextMarker = sequence.take(1).single()
            while (nextMarker != last) {
                val skip = nextMarker.skip
                val size = when (nextMarker) {
                    is GroupElementMarker -> nextMarker.elementSize
                    is RecordElementMarker -> nextMarker.elementSize
                    is SubRecordElementMarker -> nextMarker.elementSize.toUInt()
                }.toLong()
    
                topLevelList += nextMarker
                nextMarker = sequence
                    .dropWhile { marker -> marker.skip < skip + size }
                    .take(1)
                    .singleOrNull() ?: last
            }
            console.log("actually done")
            setTopLevel(topLevelList)
        }
    • 1
    • 1
  • p

    Paulo Cereda

    06/27/2025, 3:42 PM
    Hi friends! I have a test that checks whether a
    .properties
    file correctly loads entries as UTF-8 — once the
    reader
    is using the correct charset,
    Properties
    works as expected. Consider this excerpt:
    Copy code
    val expected = mapOf(
        "italian" to "anatra",
        "russian" to "утка",
        "chinese" to "鸭子",
        "japanese" to "アヒル",
        "korean" to "오리",
        "arabic" to "بطه",
        "hindi" to "बत्तख",
        ...
    )
    I was wondering if I should hardcode these strings into the Kotlin file, specially that I have RTL ones in there. Is this okay or there is a better way? Any suggestions are welcome! Thanks!
    e
    l
    • 3
    • 6
  • a

    arve

    06/30/2025, 7:52 AM
    Copy code
    import kotlinx.serialization.StringFormat
    import kotlinx.serialization.json.Json
    
    
    private val format: StringFormat = Json { encodeDefaults = true }
    object MyFormat : StringFormat by format
    When I try to inline
    format
    the expression insists on referring to the class
    Json
    instead of the factory function
    Json
    Any tips to avoid the intermediate
    format
    variable?
    e
    • 2
    • 1