Just be decent

Everyone has regrets or moments they wish they could redo. My big redo moment came sometime in the first two months of 2019.

To set the scene: I sat and worked alongside a contractor on our team for two months and we clashed. We had contrarian views on anything we talked about; I didn’t believe that was possible, but it is. We are both software engineers who write code. Our differences would often come to head in my code reviews. I’d disagree with an approach taken and it would often result in long, and very exhausting discussions.

One day it came to head, a disagreement on some code, some code so insignificant I can’t recall what it was. Whether it was the fatigue of long winding conversations to nowhere or just pent up frustration, I snapped. Saying something along the lines of “you aren’t writing good code, we are having to spend time correcting mistakes”.

I said this in an open office environment, surrounded by colleagues in our team. I apologised shortly after; even if the criticism I had leveled were founded in truth, no one deserves to be belittled or spoken to how I did.

That one moment of overflown anger has been on my mind for almost 18 months now. I constantly replayed the few minutes of disagreement in my head and over time my replays have transitioned from words to just how I felt.

I mostly felt: embarrassment and guilt.

Embarrassment, I think of myself as a calm person, I don’t yell or become frustrated at other people and it embarrassed me that I let it happen.

Guilt, it isn’t right to attempt to make someone feel bad for doing their job, a job at which they were trying at isn’t an acceptable way to treat someone.

Everyone should know that treating another person poorly is one of the worst traits a human can exhibit. It isn’t hard to treat everyone you interact with decency. It makes me cringe to see people do the opposite and knowing I did that makes me cringe at the thought of it.

This small incident took up a lot of headspace for a while, but I’ve since used to to inform how I act towards other people.

If I ever find myself in a difficult relationship, I’ll always take a minute before replying; try to understand how we got into this situation and find an amicable way out of it. A sprinkle of humour helps too.

Some people will say that yelling and aggression toward other people is a way of asserting dominance. I disagree, it is embarrassing to witness or do. I think every interaction with another person forms a small part of how that person will remember you going forward. So, just be decent.

Some thoughts on use cases in Kotlin

Originally published here on Medium: https://medium.com/@jordanfterry/some-thoughts-on-use-cases-in-kotlin-6ac8021cbcf1

Recently at the Guardian we’ve started to apply the use case pattern to our business logic. A high level overview of a use case is a class that will encapsulate a particular piece of business logic, or behaviour in your app. You may know of this as an interactor pattern as advocated for by Robert Martin in Clean Architecture. They are easy to interpret and test, which will in turn increase both developer productivity and confidence in the quality of a team’s code.

I like to call our use cases “functional use cases”? Why? Well, we make use of operator overloading to override the invoke function to make execution look like a function. Pretty simple really! Here is an example of how this might look:

class FunctionalUseCase() {
   operator fun invoke() {
       // Do something snazzy here.
   }
}

And when we invoke it:

val useCase = FunctionalUseCase()
useCase() // Not a function, but calling overloaded invoke function

It isn’t revolutionary but I like writing our use cases like this. Here are some reasons, and some other musings I have on the topic of use cases.

Overloading the invoke function is straightforward and flexible and allows you to make use of a great Kotlin feature. It is, as you might say, more idiomatic!

It is straightforward because you only have to implement the invoke function and you are good to go. Anyone with knowledge of operator overloading should be able to look at our code and know what is happening.

It is flexible as you can add parameters whatever parameters you like to the invoke function to suit the needs of the particular use case. I think this is great as we can provide any class dependencies as a constructor parameters and provide contextual information as function parameters.

One thing I’ve learned from use case “efforts” in the past is creating an opinionated use case such as one that uses RxJava to handle threading could be a mistake. It might look like this:

abstract class SingleUseCase<T>(
private val observeOn: Scheduler,
private val subscribeOn: Scheduler
) {
    fun execute(): Single<T> {
return Single
.fromCallable { doTheUseCase() }
.observeOn(observeOn)
.subscribeOn(subscribeOn)
}
    abstract fun doTheUseCase(): T
}

This could lead to some sneaky misdirection making it hard for developers to find usages of their implementation of the abstract class, as generically wrapping some behaviour in another type will require an abstract function to fill in that behaviour. A developer won’t be able to find all usages of their implementation as their implementation will always be used in the super class.

This is Rx specific, but you may have to implement multiple classes to handle Observable, Flowable, Completable or Maybe . This just adds a bit of extra complexity to your use cases.

Something I think about regularly is the single responsibility principle (I need more hobbies). It says aclass should only ever have a single reason to change. But in the above implementation, your use case can change if your business rules change or if you decide to stop using RxJava. It breaks SRP in a very subtle way!

Talking of developer experience, there is a particularly annoying gotcha with overloading the invoke function in Kotlin, it relates more to some behaviour in Android Studio/IntelliJ. But lets look at this class:

class AViewModel(private val useCase: UseCase) {
    fun start() {
useCase()
}
}

If you wanted to go to the source of useCase you would be forgiven for thinking you could click on useCase within the start function but you would be wrong. You will actually be taken to the definition of the property. To be taken to the source you’ll have to carefully aim your cursor on the final bracket: useCase(). This is very frustrating if you are trying to quickly navigate through some code!

This quickly turned into me complaining about some old code I have written and applauding some code I’m currently writing. I expect I’ll change my mind on this in the next year or so, but I hope some of these thoughts will be useful to someone!