DEV Community

Yonatan Karp-Rudin
Yonatan Karp-Rudin

Posted on • Originally published at yonatankarp.com on

Kotlin Code Smells 14 - Anonymous Functions Abusers

TL;DR: Avoid excessive use of closures and functions. Encapsulate them within objects.

Problems

  • Maintainability

  • Testability

  • Code Reuse

  • Implementation Hiding

  • Debugging

Solutions

  • Wrap functions/closures

  • Reify algorithms using a method object / Strategy pattern

Sample Code

Wrong

fun sortFunction(
    list: MutableList<Int>,
    fn: (Int, Int) -> Boolean
) {
    for (i in list.indices) {
        for (j in 0 until list.size - i - 1) {
            if (fn(list[j], list[j + 1])) {
                val temp = list[j]
                list[j] = list[j + 1]
                list[j + 1] = temp
            }
        }
    }
}

fun main() {
    val scores = mutableListOf(9, 5, 2, 7, 23, 1, 3)
    sortFunction(scores) { a, b -> a > b }
}
Enter fullscreen mode Exit fullscreen mode

Right

class ElementComparator {
    fun greaterThen(firstElement: Int, secondElement: Int) =
        firstElement > secondElement

    // This is just an example. With more complex objects,
    // this comparison might not be so trivial...
}

class BubbleSortStrategy(
    private val elements: MutableList<Int>,
    private val comparator: ElementComparator
) {
    // We have a strategy; we can unit test it, change it to a
    // polymorphic implementation, or benchmark different algorithms, etc.
    fun sort() {
        for (i in elements.indices) {
            for (j in 0 until elements.size - i - 1) {
                if (comparator.greaterThen(elements[j], elements[j + 1])) {
                    swap(j)
                }
            }
        }
    }

    private fun swap(index: Int) {
        val temp = elements[index]
        elements[index] = elements[index + 1]
        elements[index + 1] = temp
    }
}

fun main() {
    val scores = mutableListOf(9, 5, 2, 7, 23, 1, 3)
    BubbleSortStrategy(scores, ElementComparator()).sort()
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Humans read code, and while software can handle anonymous functions, maintainability suffers when multiple closures are used. By extracting functionality into objects, we can improve code reuse and maintainability.


Stay updated with my latest thoughts and ideas by registering for my newsletter. Connect with me on LinkedIn or Twitter. Let's stay connected and keep the conversation going!


Credits

Top comments (0)