Category Archives: Kotlin

Non-trivial constructors in Kotlin

Kotlin really simplifies things such as defining constructors and writing immutable objects for your application. For example, flexible Kotlin constructor definitions eliminate the need of builder classes (you simply don’t need them in 99% of all the possible use cases, if you use Kotlin), thus reducing overhead of having immutable objects in your application, while retaining full flexibility and expressiveness.

However, if you want to define non-trivial constructor (especially for data classes) it might not be as trivial as just writing a function.

For example, when I started playing with Kotlin, I decided to start with something as simple as defining a class that would represent a rational number.

My first brute force (or naive, if you like) attempt to define that class was as follows:

data class Ratio (val numerator : Int, val denominator : Int)

The problems with this class are obvious: you can create ratios like Ratio(1, 2) and Ratio(2, 4) and they won’t be equal to each other. And I wanted exact opposite – whenever the user of this class constructs a ratio it divides a numerator and denominator to their greatest common divisor – to have coprime numerator and denominator in the corresponding fields of the newly constructed instance of Ratio class. Also I wanted to retain nice-to-have features of the data class – I didn’t want to define copy, hashCode and equals myself.

So, at this point you’re welcome to play before reading my solution.


OK, now if you came up with your approach or just would like to see the possible solution – here is the link to the full class definition for those who interested.

In short: you can define custom class constructor (and yet retain call semantics) is to define invoke function in ‘class object’ section of your class that has special semantics: you can define static functions as well as factory function invoke. It may look as follows (simplified):

class Ratio private (val numerator : Int, val denominator : Int) {
  class object {
    val ZERO = Ratio(0, 1) // static member!
    val ONE = Ratio(1, 1) // static member!
    fun invoke(numerator : Int = 1, denominator : Int = 1) : Ratio {
      if (denominator == 0) throw IllegalArgumentException("denominator can't be zero")
      if (numerator == 0) return ZERO
      if (numerator == denominator) return ONE

      val d = gcd(numerator, denominator)
      return Ratio(numerator / d, denominator / d)
    } // <-- end of static function invoke

    fun gcd(a : Int, b : Int) : Int { /*omitted*/ } // static function!
  }

}

The beauty of Kotlin here is that you'll still be able to use 'constructor' semantics whenever you need to create an instance of Ratio, i.e. you can write as follows as if you had ordinary constructor:

val r1 = Ratio(3, 7) // invoke will be called here
val r2 = Ratio(numerator = 1, denominator = 4) // invoke will be called here

This is it, I hope you find it useful.

Try-with resources in Kotlin

If you’re familiar with Java but not that familiar with Kotlin you might have some difficulties with using standard control structures such as try-with resources.

In Kotlin it is also doable but it looks trickier, for example this code

OutputStreamWriter(myOutputStream).use {
    // you can reference `it` value which is a resource you're working on in this lambda:
    it.write('a')
}

Is an equivalent of the following:

try (final OutputStreamWriter it = new OutputStreamWriter(myOutputStream)) {
    it.write('a');
}

It is interesting that even though Kotlin uses lambda construction it doesn’t introduce any overhead – this code is inlined by Kotlin compiler.

Non-AOP based approach for implementing service layer in Kotlin

Usually when you’re adding a service layer in java you have to deal with so-called cross-cutting concerns in your service such as adding uniform logging for your service methods and dealing with exceptions in a uniform way.

This can be done in multiple ways. As any seasonal programmer knows, direct, brute-force approach when you’re writing this code every time for each method just doesn’t work well. If you’re doing it yourself for every method and every service in your application you’re cluttering your code and just making it harder to maintain and extend as for any significant changes in your cross-cutting code you have to rewrite service implementations for every method. Or, simply put, it requires O(n) efforts, where n is a count of methods in your service layer.

More traditional approach to address this problem is to use AOP. Comparing to the previous approach it requires just O(1) efforts. However AOP is viewed as a hack by OOP purists.

In this article I’ll try to describe another approach which doesn’t use anything besides plain old OOP and at the same time will require the same O(1) efforts for implementing cross-cutting concerns in your code.

So, let’s start. We’ll need a some sort of API for that framework that would support cross-cutting concerns. Let’s define it.

Public API for our framework

If we want to deal with input and output data in a uniform way, we can start with the generic Request and Result traits that would define input and output data for our service calls:

trait Result trait Request

These traits will merely designate (or mark) your domain objects that will carry the data that will be needed to make a particular request or will identify your service response.

As a service might return result of a remote call or any lengthy operation we can come up with a trait that will represent a result of asynchronous call:

trait Response {
  fun get(): TResult
}

As you may probably noticed this trait looks like a simplified version of Future interface. The reason why we might not want to use Future here is because usually we just don’t need to deal with its complicated interface: it also has get() method and its more complicated counterpart, but using these methods may not be convenient for application programmer as get() waits for a response indefinitely and we may not want to do that as usually we want to work with service that define certain SLA. And the other get(time, timeUnit) method is just not convenient to call as you need to know and set that time manually. In our Response trait we defined get() method out of an assumption that it will deal with setting service timeouts according to those services SLAs (as well as dealing with retries) and we won’t let the consumers of our service API deal with this operational burden.

Also, for our service implementers we’ll need to provide a convenient way of creating Response objects:

trait ResponseCreator {
  fun create(request : TRequest, calcFun: (TRequest) -> TResult) : Response
}

This trait will provide an interface to the service implementer that will abstract away dealing with cross-cutting stuff such as logging request and responses, measuring execution time etc.

Sample Usage

So, here is how it may look like from the service implementer’s point of view:

//
// Sample Service API
//

trait GetUserProfilesRequest : Request {
  val userIds : List
}

trait UserProfile {
  val id : Long?
  val name : String
  val avatarUrl : String
}

trait GetUserProfileResult : Result {
  val profiles : List
}

trait UserService {
  fun getUserProfiles(request : GetUserProfilesRequest) : Response
}

//
// Sample Service Impl
//

data class UserProfileImpl(override val id : Long?,
                           override val name : String,
                           override val avatarUrl : String) : UserProfile

data class GetUserProfileResultImpl(override val profiles : List) : GetUserProfileResult

data class GetUserProfileRequestImpl(override val userIds : List) : GetUserProfilesRequest

class UserServiceImpl(val responseCreator : ResponseCreator) : UserService {
  override fun getUserProfiles(request: GetUserProfilesRequest): Response {
    return responseCreator.create(request, { (r) -> /* hey mom, look at this amazing type inference! */
      val result = ArrayList(r.userIds.size)
      for (id in r.userIds) {
        result.add(UserProfileImpl(id = id, name = "user#${id}", avatarUrl = "http://avatarUrl_${id}"))
      }
      GetUserProfileResultImpl(profiles = result)
    })
  }
}

Sample Framework Implementation

Sample, synchronous implementation of ResponseCreator is shown below (note, that this code also contains “aspect” behavior which may be common for all the services you’re working with in your application):

/**
 * Sample response, in real applications may use Futures with the default service SLA timeouts/retries
 */
class ImmediateResponse(val result : TResult) : Response {
  override fun get(): TResult = result
}

/**
 * Sample response creator
 */
class ImmediateResponseCreator : ResponseCreator {
  override fun create(request: TRequest,
                                         calcFun: (TRequest) -> TResult): Response {
    // [1] log request
    println(" > request = ${request}")
    // [2] start measuring time
    val startTime = System.currentTimeMillis()
    try {
      val result = calcFun(request)
      // [3] stop measuring time
      val timeDelta = System.currentTimeMillis() - startTime
      // [4] log result and execution time
      println(" > result = ${result}, timeDelta = ${timeDelta}")
      return ImmediateResponse(result)
    } catch (e : Exception) {
      // [3] stop measuring time
      val timeDelta = System.currentTimeMillis() - startTime
      // [4] log exception and execution time
      println(" > error = ${e.getMessage()}, timeDelta = ${timeDelta}")
      throw e // rethrow an exception
    }
  }
}

Full listing may be found in this gist.

Links: