GitHub Repo

In honor of the occasion, I think I’ll sum up my current thoughts, feelings, notions, regarding Kotlin, IntelliJ IDEA, and all that jazz.

My first Kotlin article was on August 2nd, and I began the DSL game on August 11, so we’re about two months in, and we just passed article 100. Time to assess.

My Current Level of Expertise

If we take my level with whatever language I’m best at as 1.0, I’d say I’m probably around 0.8 with Kotlin. I’m not saying I am 80% perfect: I’m saying I’m about 80% as good with Kotlin as I am with anything. As for real skill with it, given my peers on the Slack, maybe around 50% as adept as the best of them. I don’t expect to be as good as the best of my colleagues are: they spend more time with real code on real teams, and as such, they’re much sharper than I am. Good on them. And good on me: I continue to learn and improve. So mote it be for another hundred years or so.

IDEA is the only real IDE that I’ve used for years. Ages ago I used Eclipse, some .NET thing, and I’ve used RubyMine in the distant past, and the refactoring tools that were available back then. So I come to IDEA with nearly fresh eyes and no active experience with a power tool like it is. As for how much of it I use, let’s make a quick list, using the IDEA key map as a guide to its areas of ability:

  • I know nothing about the debugging tools, and don’t intend to learn. I’ve come to feel that skill in debugging indicates low skill in programming, though of course that’s not always the case. In a large legacy app, debugging can be our only hope of finding things out. In a well-tested decently structured app, the debugging skill is largely covered by tests. OK, I’m probably talking through my hat, but anyway I haven’t run the debugger even once yet.

  • In Search/Replace, I mostly don’t. I use Control-G for multi-cursor editing almost every day, and I use the rename capability rather often. Once in a while I use the Shift-Shift search (which rarely finds anything I want) and Find in Files, whose keystroke I always forget. Twice a week for that one, at a guess.

  • In Editing, I’ve never used Smart Code Completion and don’t know what it does. I’ve typed Control-Space a time or two for basic code completion, and it has never offered me anything memorable. I do take advantage often of IDEA’s guesses that pop up. They are often helpful and only rarely irritating such as when it’ll pop up a long page of things on top of whatever I was typing. I just typed Control-Shift-Space for the first time, and it decompiled my program. I won’t make that mistake again. I don’t use the extend and shrink selection strokes, but probably should learn them. I use a few other keystrokes, just a few. Maybe I cover 25% of Editing.

  • In Refactoring I use the Extract capability a fair amount and often try the Control-T refactoring popup. I’d say I’ve used about 1/2 to 2/3 of the available items on that list, and that more than half the time I get something I wanted. I like this capability a lot and feel that I’d benefit from more practice.

  • In Navigation I use Command-B a lot, to toggle between definition and use of something or other. I don’t even know what some of those things in there are. Method Hierarchy? Dunno.

  • That’s about it. I’ve not tried Code Generation or Live Templates, and don’t know what they are. I use the reformatting and line / block moving up and down a fair amount but always forget the keystrokes until next time.

So in terms of ability with the hot bits of IDEA, I’m not there yet, but am gaining proficiency in the kinds of things that I do. I suspect some of what it offers, I don’t need at this stage.

Assessing Kotlin

I like Kotlin. I’ve used many of the C-like languages extensively. I’ve done some work with LISP. I’ve programmed in FORTRAN and Pascal and Forth. I’ve coded in IPL-V, Slip, SNOBOL, and Simscript. I’ve been pretty adept with Smalltalk, used Ruby for ages, and have avoided Scala and Haskell almost entirely.

I’m not dissing your favorite language: it’s probably great. In that personal experience space, I really like Kotlin. I enjoy using it, it rarely surprises me any more. It’s type inference (part of IDEA) makes its type checking tolerable, and in the rare instances where I miss duck typing, it’s easy to use an Interface instead, and in some ways better.

Kotlin treats functions as first-class objects, and it does this interesting trick where, if the last parameter to a function is a function, you put it outside the parens. An example:

    action("say", "xyzzy") {
        say("Swoosh!")
        response.moveToRoomNamed(R.WoodsNearCave)
    }

The stuff in the {} is the third parameter to action, but when reading it, the syntax makes it easy to express the function, plus makes it clear that it’s something that action is likely to call. It’s a very nice notation and almost always a good one. Once in a while it looks odd:

fun desc(short: descLambda, long: descLambda ) {
        shortDesc = short
        longDesc = long
        theDesc = long
    }

    fun desc(short: String, long: String) {
        desc({ short }, { long })
    }

    fun desc(short: String, long: descLambda) {
        desc({ short }, long)
    }

    fun desc(short: descLambda, long: String) {
        desc(short) { long } // irritating formatting requirement
    }

Here, I’m providing all four ways of passing either a string or a function to desc. The final one required me to make the call with the brackets outside the desc parens, and in this case the symmetry of the calls makes me want it inside. Truth be told, I could leave it inside, but I’d keep getting warnings, so I just accepted the inevitable. Anyway, usually I like that feature.

And in general I like Kotlin’s handling of functions as objects. Usually I use anonymous functions, which I would call lambdas, I hope accurately. These can have parameters or not and Kotlin generates interesting types for them, which I’ve learned mostly to ignore and just use what it says. I’m still not 100% clear on the exact meanings of all these:

(World) -> Boolean
() -> Boolean
(Imperative) -> Unit
Room.() -> Unit

Especially that last one. Is it different from (Room)->Unit or not? Whatever. They all work nicely, and I have used them extensively in the Adventure game DSL.

I like Kotlin’s scope functions, let, run, with, apply, and also. I use with often, which can clean up a series of calls that would otherwise all be saying mumble.this and mumble.that. with(mumble) sorts that right out. And the also is quite nice. You can avoid saving a value and then returning it:

fun something() {
    var save = Something()
    save.doThis()
    save.doThat()
    return save
}

That can become:

fun something() {
    return Something().also {
        it.doThis()
        it.doThat()
    }
}

I like that. YMMV. I know that some folks do not, but I think they might just not be used to it yet.

I like Kotlin’s ability to express simple functions in one line, even though those often require me to fold them here in my articles:

    private fun getVerbPhrase(verb: String): Phrase = lexicon.translate(synonym(verb))

    private fun getVerbPhrase(verb: String): Phrase 
    	= lexicon.translate(synonym(verb))

On my programming screen, the long one is completely visible, and I like that. Here, the folded one is better.

Suffice to say, I like Kotlin enough that my current plans are to continue using it for future articles for quite some time, if only I can get some graphical system running on my machine. I want to do Spacewar! or Asteroids or something.

Assessing IDEA

I very much like IDEA. It is quite solid: I’ve only broken it once, and in my fumbling, I’ve done a lot of things that it must have considered pretty weird. And all I had to do was load an old version and then the current one. I’m told that there is a Rebuild Caches that was probably what I needed.

The type inference is very good. In the case of anonymous functions, I will often just type an example and let the type inference tell me what it is.

The refactoring capability is quite good, though there are things that I do where I think it could help me but, if it can, I’ve not found the incantation. It’s good at extracting and inlining things, and when you extract a method it will usually find all the places where you may want to use the method and fix them up right then and there. Since my usual reason for extracting a method is exactly to eliminate duplication, that’s just what I want.

I’ve just learned that if you select some weird thing like (World)->Unit and Refactor/TypeAlias, it’ll find all the occurrences and replace them. That’s probably useful: I’ll try it for a while. The big problem will be figuring out a name for such a thing. RoomLambda, I think.

IDEA does everything I need and more, but then all I really need is a place to type. It’s pleasing to work with, and despite its many windows, I find that navigation is generally easy enough.

Oh. I should mention that I’m just using the “community edition”, but that I figure I’ll upgrade to some paid version, given that I’ll be using it a lot. Not that my few hundred bucks will matter, but for me, well, I prefer to pay for things that I use and like. It just seems polite somehow.

However

It’s not their fault, but configuring a project, especially with Gradle, is a nightmare. Even the experts upon whom I call when I get in trouble seem not to really understand what’s going on. It’s more like they know that if you kick the printer just so, it will usually start printing again. It seems that to configure a project, you have to make decisions about versions of things you’ve never heard of and would prefer never to hear of again.

Hill, when he’s not grousing, calls it “an unsolved problem”, and it surely is that. The good news is that we only need to set up a new environment rarely. I’d hate for it to be my full-time job, though perhaps it if were, I’d get good at it.

For Me to Learn

I need to settle on the extent to which I’ll use the expression body vs block body format. I like the one-line effect of the expression body, but often the line is really too long to take in at a glance, and I have in the past been briefly confused between a function in this form and a variable.

I need to find ways for IDEA/Kotlin to help me with the habits I need to improve, such as wrapping native objects and collections.

I need to better decide where to keep typealias type definitions, and to decide when they represent a need for a real class, however small.

Probably I’d benefit from exploring some of the more powerful features, the generate capability and so on. Maybe there are even ways to teach it to generate things that I commonly do. First I’d have to want something like that, of course.

I’m sure there’s more … I try to stay alert for opportunities to learn. I also try to stay alert for opportunities to nap. These things come into conflict sometimes.

Bottom Line

I am quite pleased with IDEA and Kotlin. They’re solid, powerful, and contain plenty of useful capabilities. I’ve found the learning curve to be pretty reasonable, with the ability to start slowly and try things as one becomes more comfortable.

I admire good work, and Kotlin and IDEA are good work. Recommended.