Static method is bad, or at least, when it’s not pure.

Pure, in this context, means that:

It causes no side-effects, mutates nothing outside of the method scope.

It is referential transparent, meaning any reference must be passed as an argument or else mutation of your referenced value will results in non-deterministic result.

Why is that bad?

Because whoever consumes that impure static method will not be easy to test. If the static method is pure it might be fine since you can predict its behavior and you don’t need to mock them (less mocking is great!), just asserting the return value is enough. But the impure one, it’s a different story.

If the code is under your control, you can and should avoid impure static method. But if you have to use static method from a library or framework and you can’t avoid them, what can you do?

For example, we want to send sms notification using Twillo.

Twillo SDK provides static method Message.creator which is a factory method for constructing MessageCreator . The method that actually makes a request to Twillo to send sms is messageCreator.create(restClient) .

Even though Message.creator is pure, but messageCreator.create(restClient) which is the method of the result of Message.creator is not. So we need to mock the create method by first stubbing return value of Message.creator . But since Message.creator is static, we don’t have our way in.

One might say: we can create a wrapper class around that static method, so that we can mock the wrapper instead.

But testing is all about increasing confidence in your code. Adding another level of indirection just for testing doesn’t increase confidence level in your system under test and adding more complexity to your code base.

So if adding wrapper helps you improving team’s coding experience consuming the API and it is being use a lot then it might worth investment, not just for the sake of testing.

Then, is there a leaner way?

Higher-order function FTW

We want to somehow create a path to replace Message.creator with something else. In Kotlin and a many languages these days treat function as a first-class citizen. The smallest reusable component is no more class but function. So you can pass function around like any other object.

In a strict functional and mathematical sense, function must be pure. But in Kotlin context, seems like function is allowed to be impure.

The difference between method and function in Kotlin is, while method is associated to an object, function doesn’t need to. You can see that the fun keyword which refers to function everywhere regardless of being a method declaration or top-level function declaration, which means function is a super-set of method, at least in this context.

But what is Higher-order function?

Higher-order function is basically means the function that has function as parameter(s) or returns function.

Even though function that does not have function as parameter(s) and not returning function is called first-order function, the term higher-order is being used here instead of second-order or third-order because, in theory, we can nest “function that has function as parameter(s) or returns function” infinitely many level. So that it’s higher than second or third order.