re: Kotlin - The Good, the Bad and the Ugly VIEW POST

FULL DISCUSSION
 

Nice post, thanks for that!

I somehow understand how you got to your "bad/ugly" points, but it feels like it's written from a Java devs point of view.

But Kotlin is a programming language on its own and not a simple java substitute!

Here's my take:

Static functions

"This causes some annoyance in case you just want to define that one utility method"

I disagree. You can have top level functions (like you mentioned) or nicely scoped extension functions. Imho, you never really want a static function to begin with. It leads to procedural, rather than object-oriented, thinking.

open vs final

"If you write a class that potentially breaks when it is subclassed, you wrote a bad class."

I really think that this is impossible. Not even the original Java Developers were able to achieve that. Consider e.g java.util.Stack, which should most definitely have been final.
There's a reason that Effective Java Item 17. is "Design and document for inheritance or else prohibit it." and is not written the other way round. Also "Favor composition over inheritance" has been advice since forever for the same reasons.

By the way, I rarely run into problems with final vs open because I usually use interfaces and rarely even consider extending non-abstract classes.
The fact that the Spring Framework chose to work with subclassing is the Framework's problem, not the language's. That's why spring boot takes care of that for you by automatically applying the all-open compiler plugin.

constructors
I don't understand what your problem with constructors is. If the problem is that it's on the same line, then put it on a different line? Otherwise Java's got the same problem - the reason is too many parameters.

Data classes
I kinda agree with your data class opinion, but want to add that it might be a bad idea to use data classes for JPA since, JPA is... special. (vladmihalcea.com/how-to-implement-...)

Additionally, the keyword vs annotation thing is discussed here (blog.jetbrains.com/kotlin/2015/08/...)

Thanks for giving you thoughts! :-)

 

But Kotlin is a programming language on its own and not a simple java substitute!

I disagree on this one. The Kotlin language has been advertised by its creators from the very beginning to have excellent interoperability with Java. Therefore it should also play nicely with existing libraries and frameworks from the Java universe. My point is: the Kotlin devs must have seen those issues coming from miles away, and chose to deliberately ignore them, for the sake of forcing a design choice down people's throats (closed keyword) which isn't even that good in my opinion. Feel free to disagree, but to me this a big disadvantage of Kotlin.

JPA is... special.

Indeed it is. A lot more special than I would like it to be, honestly. There's so many things you can do wrong with JPA without even realizing that you made a mistake, until it is way too late to rectify it properly. It would have been nice to have a framework where you can model your data easily and have dedicated support to ease the mapping of those data models. Data classes would have been a good fit.

Additionally, the keyword vs annotation thing is discussed here

I've yet to read the entire article (thanks for linking it), but @inline doesn't seem so bad to me. A lot better (and less scary) than a magical "sometimes I'm a keyword" inline, in fact. The ability to use annotations without a leading @ that distinguishes them from keywords makes my neck hair stand up in terror. Good thing that didn't happen.

I don't understand what your problem with constructors is.

I like my code to be structured in blocks: declare the class name, declare the superclass, declare the fields, declare the constructor. This isn't possible with primary constructors. It's all mixed up into one Gordian Knot. Also, there's the lock-in effect when using primary constructors. You can't rely on a secondary constructor in a subclass. Overall, data classes aside, I simply don't see the need for primary constructors. They just increase the mental efforts required for parsing the source code of a class. Where are my fields? They are not listed... oh, right, they might be listed in the constructor... argh I like to have things organized, and find them always in the same place. Now I have to look at least in two places until I find all the fields of a class. It's mixing what doesn't belong together.

I rarely run into problems with final vs open because I usually use interfaces

Then you are not using frameworks such as Spring or JPA. I don't say that I like dynamic bytecode generation at runtime (quite the opposite...) but it is a hard fact that those are the primary frameworks we work with on the server side. Apparently, Spring 5 got dedicated support for Kotlin, I've yet to look into that, maybe they fixed this particular issue somehow. As stated above, the Kotlin devs must have seen this coming.

Imho, you never really want a static function to begin with.

I often do, because I like to have named constructors that take different arguments, so I create factory methods (e.g. User.createFromDTO(userDTO) instead of new UserImpl(userDTO)). The nice thing about these is that they can be placed directly into the interface (Java 8+), the code which uses it doesn't even have to be aware of UserImpl. If I wanted to do the same thing in Kotlin, I need a companion object that holds the factory method. The companion object construction as such (as stated in the blog post) is something that I feel wasn't necessary to begin with, and it has become a syntactic hurdle for cases that actually matter.

Just my 5 cents, as I said: feel free to disagree. If you use Kotlin in a different environment (e.g. Android), your experiences with Kotlin may vary drastically from mine.

 

Data classes are very useful when declaring POJOs for processing JSON, with some extensions. For example, I can have the below setup to fetch a JSON that contains a user's data and convert it into the App's user model to remember locally in my app:

data class UserResponse(id: String, email: String, name: String){
    fun asAppUser() = AppUser(name, id, email) // Convert to App's model.
    val isVerified: Boolean
        get() = id.endsWith("-unverified") // for example, id="37823-unverified"
}

// Somewhere in code,
val jsonString = fetchUserDataFromServer()
val user = Gson().fromJson(jsonString, UserResponse::class)

if(user.isVerified){
    rememberUser(user.asAppUser())
}
 

But Kotlin is a programming language on its own and not a simple java substitute!

I could not agree more. When I picked up kotlin for the first time, I saw it as simply a replacement for Java, and did a lot of the things Lombok did. The more I use it, the more I've come to realize that I really do approach solving problems in Kotlin differently (and better) than I would in Java. In fact, new libraries I write in Kotlin, I'm trying to make sure they are multiplatform, so that I can't just treat it like a cleaner Java.

code of conduct - report abuse