Technical Tuesday: Implementing the Singleton design pattern in Scala


For today’s edition of dataxu’s Technical Tuesday series, Javier Buquet, a Software Engineer, discusses how Singletons are implemented in Scala here at dataxu and a method for generalizing the solution.

How we implement Singletons in Scala at dataxu

At dataxu, we have been using Scala for a while now, and in our journey we have perfected our best practices. Among these best practices, we have refined our implementation of the Singleton design pattern in Scala. In implementing this pattern there are some aspects that require significant attention to detail to increase its ease of use, especially when testing.

The Singleton design pattern, according to Wikipedia, is a software design pattern that restricts the instantiation of a class to one object. This means that this pattern promises to be handy when dealing with a class that we want to instantiate once, and only once, across a system (or, more generally, a subsystem), and have that same instance shared by every potential user of the class. For example, think about a DatabaseConnection class that handles the connection between the system and its database, it is reasonable to have only one instance of the class and make any database client use that same connection.

But the question is, how do we implement this Singleton design pattern in Scala?

Implementing the Singleton design pattern in Scala

If you have already given Scala a try, you are probably familiar with Scala’s Singleton Objects. These are Scala’s approach to the static keyword in Java. Any function or variable defined in a Scala Object can be used statically, as there is one and only one instance of an object, which is not instantiated by any consumer, but just exists.

Our first hunch when implementing the Singleton design pattern in Scala was to make use of the Singleton Objects.

Let’s say we actually want to implement the DatabaseConnection class we mentioned above following the Singleton design pattern. This will allow different consumers to share the same DatabaseConnection instance for running commands on our application’s database. Using Scala’s Singleton Objects we can achieve this by doing:

object DatabaseConnection {
  def establishConnection(): Unit = ???
  def isConnectionEstablished: Boolean = ???
  def runCommand(command: DatabaseCommand): DatabaseCommandResult = ???
  def terminateConnection(): Unit = ???

And that’s all. We can now support different consumers running commands on a shared DatabaseConnection instance implementing the Singleton design pattern. For example, we could have a function somewhere else that retrieves all the Users in the database, as follows:

def retrieveAllUsers(): Seq[User] = {
  if (!DatabaseConnection.isConnectionEstablished) {
  val commandResult = DatabaseConnection.runCommand(DatabaseCommand.retrieveAllUsers)

As you can see, there’s no need to instantiate a new DatabaseConnection nor to somehow keep a reference to it—we have direct access to the one and only DatabaseConnection instance just as if it was a static call in Java.

As we started using this approach in our code, we found it had some limitations that were important to note:

  • There’s no way one can easily swap the implementation being used. The fact that the user does not control the creation of this singleton instance—as it exists naturally in the program—makes it impossible to easily swap the implementation being used. It is common for us at dataxu to need a different implementation of our DatabaseConnection class when running our unit tests so that we don’t connect to the actual database but instead use an in-memory implementation of the class which is faster and cheaper. Using the Singleton Object does not allow us to swap the implementation of DatabaseConnection we want to instantiate as the singleton, but instead we would need to modify each and every consumer of the class to point to a different Object.
  • Can’t be instantiated lazily. It might be the case that we need our singleton instance to be created lazily—only instantiate it once it has been requested for the first time by a consumer, not before. Again, as we don’t control the creation of this singleton instance, there’s no way we can do so lazily—it will be instantiated upon program execution.

These limitations are a consequence of the fact that these Scala Singleton Objects are not meant to be used this way. These Objects are not a built-in implementation of the Singleton design pattern, but instead are Scala’s approach to Java’s static. Hence, we should not include in these Objects code that is intended to be used as non-static code accessed through a singleton instance, but instead we should only include static code.

To read more about dataxu’s strategy for implementing Singletons in Scala read the full post here.