Closed bopke closed 2 years ago
Code gets lengthy when it's written in a bad way. Switching to another language just to make tests in a minecraft project is useless. You won't be able to tests most of the stuff with automatic tests even if you use tools such as MockBukkit.
I think we should use Java (8 in the shared code for all versions and 8/11/17 in the version specific code), using Kotlin (or Scala or anything like that) doesn't make a big difference for us (things like automatic getters/setters aren't that important and they can be easily auto generated by IntelliJ, null safety also can be easily achieved by Option/Optional and/or @Nullable/@NotNull annotations and we aren't going to make DSLs or anything like that)
I do think that using Kotlin will make a difference. Yes, you are correct null safety and getters/setters are achievable in Java. HOEVER kotlin provides awesome tooling such as schedule and extension functions also kotlin does not require Checked Exceptions. You could argue that this is bad, but I think that it speeds up development and makes code prettier. Another advantage of kotlin is code concise when compared to java. It also supports smart cast - something that will be used quite a bit then dealing with data serialization/deserialization and piping it through event system. Kotlin also does not require explicitly code typing so creating variables is quite easy. Hoever kotlin does have come cons:
I do still think that using it is better for big projects like this one. If you have other opinion please let me know
I do think that using Kotlin will make a difference. Yes, you are correct null safety and getters/setters are achievable in Java. HOEVER kotlin provides awesome tooling such as schedule and extension functions also kotlin does not require Checked Exceptions. You could argue that this is bad, but I think that it speeds up development and makes code prettier. Another advantage of kotlin is code concise when compared to java. It also supports smart cast - something that will be used quite a bit then dealing with data serialization/deserialization and piping it through event system. Kotlin also does not require explicitly code typing so creating variables is quite easy. Hoever kotlin does have come cons:
- Plugin API might be difficult to access from java.
- It has smaller community that would potentially create pull request
I do still think that using it is better for big projects like this one. If you have other opinion please let me know
kotlin provides awesome tooling such as [schedule](https://github.com/okkero/Skedule) and [extension functions](https://kotlinlang.org/docs/extensions.html)
Coroutines are generally considered a bad practice and extension functions aren't life changing, you can just use good old utility classes and the code will look similar (a bit shorter with extension functions, yes but still similar).
kotlin does not require Checked Exceptions.
Yes, Kotlin doesn't require you to handle a checked exception but Java doesn't either, you can just add throws EXCEPTION
to the method signature. It adds only a few characters to the method signature, it doesn't make a big enough difference imo.
It also supports smart cast
Yeah, smart casts are super useful I agree but still it doesn't make a big enough difference, it saves only one line of code per smart cast.
Kotlin also does not require explicitly code typing so creating variables is quite easy.
Some people prefer to use types everywhere even if the language has vars (or something similar) so it's mostly a matter of preference. Plus it still doesn't make a big enough difference.
Speaking of cons:
Coroutines are generally considered a bad practice and extension functions aren't life changing, you can just use good old utility classes and the code will look similar (a bit shorter with extension functions, yes but still similar).
Excuse me, what? It is just a wrapper to make bukkit scheduling easier. Besides, how in the world is coroutines bad practice?
you can just add
throws EXCEPTION
to the method signature.
Yes, but you still need to do try, catch somewhere in the code otherwise code will not compile
It's really easy to write bad, unreadable code in Kotlin as it has a lot of super sugary features (which hide what's really going on) and allows to do the same thing in 5 different ways.
Kotlin is way easier to handle when it comes to codestyle. In java you have a lot of ways to do codestyle. In kotlin there is an official codestyle that is simple (It is official so discussions about it are unnecessary). Also:
val x = Object()
is way nicer then public final Object x = new Object();
It add up quickly.
Coroutines are generally considered a bad practice and extension functions aren't life changing, you can just use good old utility classes and the code will look similar (a bit shorter with extension functions, yes but still similar).
Excuse me, what? It is just a wrapper to make bukkit scheduling easier. Besides, how in the world is coroutines bad practice?
you can just add
throws EXCEPTION
to the method signature.Yes, but you still need to do try, catch somewhere in the code otherwise code will not compile
It's really easy to write bad, unreadable code in Kotlin as it has a lot of super sugary features (which hide what's really going on) and allows to do the same thing in 5 different ways.
Kotlin is way easier to handle when it comes to codestyle. In java you have a lot of ways to do codestyle. In kotlin there is an official codestyle that is simple (It is official so discussions about it are unnecessary). Also:
val x = Object()
is way nicer thenpublic final Object x = new Object();
It add up quickly.
Excuse me, what? It is just a wrapper to make bukkit scheduling easier. Besides, how in the world is coroutines bad practice?
I'm not talking about the library, the library itself doesn't matter, neither does bukkit scheduler. I'm talking only about coroutines. There are many problems with using coroutines:
Yes, but you still need to do try, catch somewhere in the code otherwise code will not compile
No, you do not, you can just add throws
everywhere. Besides, we should not ignore exceptions, no matter in what language we write the code, we should handle them all properly so it won't make a difference at all as the try-catch syntaxes in both languages are... basically the same.
Kotlin is way easier to handle when it comes to codestyle. In java you have a lot of ways to do codestyle. In kotlin there is an official codestyle that is simple
I agree, it's nice that Kotlin has an official code style convention but it doesn't matter, we should in both cases specify code style in the project itself.
Besides, we should not ignore exceptions
We are not ignoring it - we are just not adding explicit code to print the exception
I could understand the downsides of coroutines however I still do think that kotlin does save a lot of code as well as time that could be otherwise spent on further development
I'm going to focus on reasons why I think kotlin is a bad idea
kotlin does not require Checked Exceptions.
I assume this means that we can just omit any trace that exception may be thrown inside our code. When our codebase grow, it may become harder to manage and there is potential problem with discovering exceptions we weren't expecting, because someone else decided to ignore them when he wrote the code. We have to deal with later.
You could argue that this is bad, but I think that it speeds up development and makes code prettier.
If it works as I suggested before, it will initially speed up development, but will create growing problem in the future.
Plugin API might be difficult to access from java.
I think that API should be as easy to use as possible and java is still a king if we talk about minecraft plugin development. We don't want
We are not ignoring it - we are just not adding explicit code to print the exception
I strongly believe that if we do it right, there will not be too much of exceptions we would handle that way, I also believe it's not a good idea to just print the stacktrace and live it be. Every exception should be handled properly, or silenced if it doesn't really matter. Only places where I see it somehow usable is in API module to just print exceptions that are meant to notify plugin developers that something is wrong, and maybe in tests, where every unexpected exception should just be treated as failed test.
Besides, we should not ignore exceptions
We are not ignoring it - we are just not adding explicit code to print the exception
Kotlin doesn't print exceptions automatically if you decide to not handle them, Spigot does that when an exception reaches it's code and when that happens, it disables your plugin because it's obviously not functioning correctly. That's not an exception handling, it's the opposite.
I guess we coudl use java. But do we use lombok?
@WcaleNieWolny: HOEVER kotlin provides awesome tooling such as schedule
Kotlin here provides nothing. Similar tooling is easily achieved with Java.
It also seems, the authors of the project decided scheduled jobs should be written as something that closely resamples plain java/kotlin, whilst more specific instructions do a better job.
Below are some examples of okaeri-tasker. Notice that using it instead of skedule means supporting Polish capital more, and thus greater chances of obtaining grants, due to the lower attractiveness of the region, and therefore higher attractiveness of this innovative project without losing the argument of fopolishness.
// create instance, preferably one per plugin
Tasker tasker = BukkitTasker.newPool(pluginInstance);
// standard access, create new chain
this.tasker.newChain()
// get data from service into chain stack asynchronously
.async(() -> this.playerPersistence.get(event.getPlayer()))
// manipulate the data synchronously
.acceptSync(playerProperties -> {
Instant lastJoined = playerProperties.getLastJoined();
event.getPlayer().sendMessage("Your last join time: " + lastJoined);
playerProperties.setLastJoined(Instant.now());
playerProperties.setLastJoinedLocation(event.getPlayer().getLocation());
})
// asynchronously save the data - you may notice
// that previous method does not need to return value
// because stack data persists between chain parts
.acceptAsync(playerProperties -> {
playerProperties.save();
})
.execute();
Also, with available alternative for cyclic waiting or counters:
this.tasker.newDelayer(teleportDuration, Duration.ofSeconds(1))
// executed every 2nd-arg duration
.abortIfNot(player::isOnline)
.abortIfThen(
() -> startingLocation.distance(player.getLocation()) > 0.5,
() -> this.i18n.get(this.messages.getTeleportationCancelledError()).sendTo(player)
)
// executed once after 1st-arg duration if not aborted before
.delayed(() -> {
this.module.teleportToSpawn(player, true);
this.i18n.get(this.messages.getTeleportationSuccess()).sendTo(player);
})
// run in specific context
.executeAsync();
Let's vote:
I think it is important in programming to "hide" fields/properties behind methods. We should encapsulate and control data in objects. It seems to me that it can be harmful when someone places meaningless setters / getters everywhere. In Kotlin / Java + Lombok, you can easily forget about it :/
I think that's really simple. We just need to create bindings into bukkit in rust-lang. With this simple tricks we'll achieve BLAZING FAST performance and memory safety and most important @thatbakamono will be happy
We're going to use java.
When I pushed for this project creation, I've mostly been thinking about learning good OOP practices in java in this wonderful community. It may be even more valuable, if someone provides arguments for using another JVM language that will be better suited for this task. Java is very robust, well known language, but it's also very verbose and code quickly gets very lengthy. I think that writing all the working code in one language is the best way to go, with the exception of tests which I've heard are easier to handle in other languages like groovy or kotlin.
I'm starting this issue as discussion thread, to encourage everyone interested in project to share his thoughts on this topic. Also, I think that important thing will be to support java 8 jvm version, because it makes up more than a half of java version used with FunnyGuilds-enabled servers, as we can see at FunnyGuilds bStats