Kotlin vs. modern Java

I would say that technically, you are still defining an interface either way.

fun <Result> doInTransaction(block: () -> Result): Result is still an interface, it’s just declared inline. :wink:. Just 'cause the compiler hides all the details for you, doesn’t make it not an interface. Especially if you declare the function with a typealias, there is very little difference between a “function” and a single method interface.

By first class citizen, I mean that functions/methods are objects that can be passed around just like any other object.

I think it was not even considered “removing” the ternary operator. After making if ... else an expression, ternary operator simply became redundant, it had exactly the same functionality as if ... else. Also, Python, Rust and Scala don’t have the ternary operator and use “if-else” expressions instead.

4 Likes

I guess, doing a bit of reading, the if statement returning a value is a ternary (thanks for the correct name), but don’t even get me started on python’s version which is, apparently, [on_true] if [expression] else [on_false]. ewww.

Anyways, I just don’t see the point not to have the shorthand ternary operator [condition]?[on true]:[on false] if you are also going to have the shorthand binary operator (elvis) [on not null]?:[on null]

Anyways, overall enjoy writing in kotlin and will leave it at that.

1 Like

In my team, I found a quite interesting fact. We have multiple services; all are configured to use both java and Kotlin.

  • 1st group: the worst developers in my team, they still like to write java code. They don’t see many benefits to move to Kotlin. They usually use Kotlin syntax in the wrong ways. They don’t really understand Kotlin. They don’t see the sh** of Java code and continuing enjoy that sh** with their new java files.
  • 2nd group: the best developers in my team, they want to avoid java as much as possible. If they are developing a new feature, they definitely write it in Kotlin. If they see java code, they try to convert it to kotlin if it doesn’t require too much effort.

When our team shrinks, most of the people in the 1st group are selected to be out. The decision is made by non-technical people, who don’t know the fact above. The decision is made from personal productivity in our team. It’s just funny that, this matches the 2 groups I showed above.

3 Likes

You can’t differentiate developers based on a programming language. You can still be a bad developer if you write bad Kotlin code. Be rational.

2 Likes

For me Kotlin is about being comfortable.

I’ve never seen another programming language (and I did production quality code in about 20 different languages) which provides as much comfort, while being a general purpose language, as Kotlin.

It is my personal taste and area of work, but for me Kotlin is a kind of perfect.

I program mostly full-stack web applications (when I have to go lower I use C++, but that’s because of speed and embedded systems).

For full stack, Java simply cannot beat Kotlin because - as far as I know - there is no Java/JS.

On the server side I could go Java, but why would I? So, I think the right question is not why I use Kotlin instead of Java. But why would I use Java instead of Kotlin?

As I see the Jetbrains team put an immense amount of work into making the language comfortable for the programmers. Not to say that they are without error, there are a few annoying things. :slight_smile:

Also, I cannot stress enough how powerful the new K2 compiler with the IR plugins is. You maybe don’t see it yet, but these two are amazing. Actually, for me this is a dream coming true. I can write the compiler plugins that let me write programs the way I always wanted. No more annotation hell, no more boilerplate.

My only real problem with Kotlin is the lack of identity and the lack of resource visibility. It is pretty hard to find pure Kotlin libraries. Not because they don’t exist, but because you don’t know where to start.

I think it was a good idea to build on the Java compatibility, but now we should forget Java and stand on our own legs.

Kotlin is amazing. It is not a sidekick of Java any more. It should start to act as a grown up.

4 Likes

I didn’t differentiate developers based on a programming language. The main idea I conclude from the example is that the person who doesn’t want to learn new things would usually have issues. If they don’t have the interest in learning, they are not motivated to work in their best performance.
You see that our projects allow both java and kotlin, and they don’t want to change to the better version at all.

And if let’s assume there is a performance distance between a good developer and a bad developer in java. Now, if the good one uses Kotlin and the bad one continues to use java, the distance will be even factored.

2 Likes

I think it is very easy to confuse two situations:

  • Person, who we consider a good developer, uses Kotlin.
  • Person uses the same technology we personally like, so we consider them a good developer.

Over the years there were multiple “better Java” languages: Groovy, Scala, Clojure. I wonder if you learnt them all and if not, if that means you are not motivated to learn and improve your performance. Even if you learnt some of them, is it fair if a fan of Groovy consider you a bad developer simply because you still chose Java for your project and not a “better” alternative?

It is expected from software engineers that they learn new technologies and improve their skills. But that doesn’t mean they have to learn exactly the same things we like.

3 Likes

Exactly what @broot said, there are so many factors and variables why a developer doesn’t have enough time to learn new things. That could be because they prefer more time with hobbies or with family, etc.

Of course, developers who does not want to learn new things exists, but you don’t know the reason.

It would be better to say that good developers strive to improve themselves rather than to let their skills stagnate for the rest of their careers. This concerns not only Java developers as well.

In our case many projects still use Java 8 till this day. Managers and developers frequently don’t see any reason to change. I experienced this myself many times. To that the bigger a potential change is the more resistance will come with its introduction.

That’s why those who want to use Kotlin ofter qualify to a group which want innovation within the project, because they can do things better and easier by just migrating to newer technologies.

So, it’s not like the good developers use Kotlin and the other Java, but simply good developers adapt and experiment to make their lives easier :wink:

1 Like

Could you elaborate more?

Commercial development is tricky because of managing legacy code no one understands and management not providing enough money to upgrade it to the newest shit.
Rather, software is abandoned after time and rewritten completely from scratch.

Would interest me how Kotlin does it instead.
I think the reason Java uses annotations is the lack of multiple inheritance which C++ offers. Instead of annotating a class with Bean you would just extend Bean and calling it’s super constructor when constructing the deriving class such that the resulting object can be registered in the bean framework.

Absolutely agreeing, infer or auto would be a better fit.

Getter and Setter are now regarded as mispatterns.
Brian Goetz wanted to set a sign not to use it anymore with records, and it should also be easier to write it without these clunky methods.

Because for fearless threading.

An advantage would be to use the old alias to call methods you don’t have in the derived class or which are different, but I think this is so a rare use case.

A pro argument of Java from my side:
I think how Java will set up structured concurrency is better than in Kotlin because Kotlin uses function coloring, which is a design smell in my eyes.

It’s not that Kotlin does it differently, it’s that, so far, Kotlin developers do it differently. Consider ktor vs Spring, for example:

In Spring, you manage a set of annotations (and dependencies!) that get recognized by the framework, and through a complicated hidden rules engine, imply the behavior you want for your server.

In ktor, you just write the code that does what you want. Kotlin is a programming language, after all, and a programming language is all about defining behavior.

The Java community has come to accept annotation-based metaprogramming as a preferred way of accomplishing tasks that you could easily just implement without all the nonsense.

1 Like

apply magic with builders is really a nice thing as you don’t really need config files anymore, just plain kotlin.

Afaics, ktor uses a more explicit approach using function composition of higher order functions which are first class entities, which is really nice work.

1 Like

When Kotlin uses colors, Java uses InterruptedException.
Moreover, Java 21 does not solve threading problem: you cannot invoke a blocking function from the GUI thread, therefore you cannot freely mix blocking and non-blocking code.

2 Likes

I don’t believe so. InterruptedException is for failures.
To me it seems Kotlin colors it’s functions probably to mod them to include a hidden context parameter. Normally, you don’t want to know if a function employs concurrency internally or not (function body).
Even marking a function as suspended don’t give a clue if the next statement after a suspended function call will be concurrent to the function call or not.
Whereas in Java every existing function will be seen as suspend function cause it may or may not use virtual threads.

It really feels to me that implementation details of Kotlin’s own virtual threads are lurking into it’s abstraction.
Further, concurrency in Kotlin is not easy to understand in my eyes given all the abstractions it provides (coroutine ,coroutine bridge/builder, suspend function, continuation).
In Java it’s just akin to real threads.

Can’t argue about this, did you have an example?

All subtasks should, therefore, be written in a way that is responsive to interruption (JEP 453)

If a subtask is responsive to interruption, then it have to handle InterruptedException, and when a method has been interrupted it should notify this specific error throwing an InterruptedException, so caller can handle interruption accordly.

Take a look here, the same issue when blocking the Android UI thread and any other event loops (AWT, OpenGL, …).
Kotlin Coroutines can freely switch between dispatchers, instead it isn’t possible do switch between JVM Threads because you have to return response (or throw an error) in the caller thread, so if you invoke a blocking function (like lock.await()) inside an event loop, the entire event loop has been blocked by that lock.

2 Likes

If you’re talking about Java’s virtual threads, then that’s not really “structured concurrency”. Structured concurrency is “I’m going to start some concurrent work and wait for it to finish before I continue.” Virtual threads don’t help with that – it’s still writing threading code, with all the problems associated with that (minus the cost of creating and switching threads). There’s a reason Android devs have used lots of different frameworks (AsyncTasks, loaders, RxJava, and now Kotlin coroutines) to avoid writing threading code.

2 Likes

I think comparing Kotlin coroutines to Loom doesn’t make too much sense. Java has huge advantage in this matter and its implementation has to be “better”. Kotlin implements coroutines on top of other languages/VMs which don’t support them natively, so its implementation is a kind of hack. JVM has full access to underlying OS and can do it properly. This allows Java virtual threads to be easier to use, more powerful and probably more performant as well.

But Kotlin coroutines have their advantages as well. Kotlin provides a full framework, with more features than simply coroutines. It provides structured concurrency (Java will provide it as well, but I guess it will be more clumsy), it provides flows. Kotlin is multiplatform, so we can use the same concurrent code in multiple targets. It also works in old JVMs (I still see Java 11 and even 8 in production use). Kotlin coroutines are scheduled cooperatively, which in some cases is a drawback, but it has its advantages as well.

1 Like

… and then you proceed to do just that, because it actually makes a lot of sense :slight_smile:

These defenses of Kotlin coroutines vs. Loom (not yours specifically) are full of the kind of illogical arguments that engineers use when they’re gaslighting themselves. Experienced engineers that don’t have any skin in the game will recognize this as the signal that Loom’s solution is inherently superior.

I am not very familiar with project Loom, so can you tell me will it enable something like this:

scope.launch{
  val response = withContext(Dispatechers.IO){
    repository.getResponse()
  }
  withContext(Dispatchers.Main){
    uiElement.show(response)
  }
}