DEV Community

Yonatan Karp-Rudin
Yonatan Karp-Rudin

Posted on • Originally published at yonatankarp.com on

Kotlin Code Smell 23 - Singletons

Problem

  • Coupling

  • Testability

  • Accidental implementation problems

  • Multi-threading issues

  • Static methods polluting

  • Object creation contract violation

  • Bijection mismatch

  • Memory issues

  • Premature Optimization

Solution

  1. Avoid singletons altogether.

  2. Use contextual unique objects instead of relying on a global instance.

  3. Benchmark object creation to ensure performance is not adversely affected.

Examples

  • Database Access

  • Globals

  • Loggers

  • Helper classes

Sample Code

Wrong

// God is the archetypal singleton example
class God {
    // In Kotlin, the companion object is always a singleton
    companion object {
        private var instance: God? = null

        fun getInstance(): God {
            if (instance == null) {
                instance = God()
            }

            return requireNotNull(instance)
        }
    }
}

// Why should we be aware of getInstance when creating an object?
val jewishGod = God.getInstance()

Enter fullscreen mode Exit fullscreen mode

Right

interface Religion {
    // Define behavior
}

class God {
    // There can be as many as you wish
}

class PolytheisticReligion(private val gods: Collection<God>) : Religion
class MonotheisticReligion(private val godAllMighty: God) : Religion

// According to Judaism, there's only one God,
// but this does not hold in other religions.
// Under this context, God is unique. We cannot create or change
// a new one.
val jewishGod = God()
val judaism = MonotheisticReligion(jewishGod)

val jupiter = God()
val saturn = God()
val mythologicalReligion = PolytheisticReligion(listOf(jupiter, saturn))

// Gods are unique (or not) according to context.
// We can create test religions with or without unicity.
// This is less coupled since we break the direct reference to the
// God class.
// The God class has the single responsibility to create gods, not
// to manage them.

Enter fullscreen mode Exit fullscreen mode

Conclusion

The use of singletons is a historical mistake that has already been acknowledged by the community. Nevertheless, lazy developers bring it up again and again. We need to reach a consensus on its drawbacks and strive for better design patterns.


I hope you enjoyed this journey and learned something new. If you want to stay updated with my latest thoughts and ideas, feel free to register for my newsletter. You can also find me on LinkedIn or Twitter. Let's stay connected and keep the conversation going!


Credits

Top comments (0)