Improve Kotlin support #213
Replies: 17 comments 15 replies
-
Hey there, interesting observations. We do not know how many of our users are Kotlin-based. We occasionally get a Kotlin-related question, and we get much less of those than Java questions, but that is the only data point we have. Wrt. some of your other questions:
Now, to Kotlin support in particular. I am open to considering any change which improves life for both Java users and Kotlin users. However, maintaining any Kotlin-specific bindings or duplicating parts of the codebase with Kotlin-specific code paths is not what I would chose. I would have to be strongly convinced that this brings major benefits, especially if it meant introducing Kotlin to our codebase. As Java continues to evolve, and especially with project Valhalla, I expect we will have to reconsider several of the decisions discussed here. (Mainly nullability and mutability.) When the time comes, we may come with major new APIs, which are going to address the problems for both Java users and Kotlin users. That would be my preferred way of addressing these issues. (And honestly, I can't wait.) In summation: I am open to any pull requests which improve the lives of our users, but those benefits will be weighed on a case-by-case basis against the costs of long-term maintenance. Let's talk about the individual changes you want to propose, and let's discuss them on their merits. (Finally, my personal opinion: I do not consider being able to write nicer code to be of high enough value to offset runtime performance and maintenance considerations. "Nice" is a matter of personal preference, and "idiomatic" is a fancy word for saying "we want it like this because we think it's nice like this".) |
Beta Was this translation helpful? Give feedback.
-
PoCs are always welcome! A Kotlin DSL would probably be the way to go - even if only as a way to see where the pain points are, to know what to address in Timefold directly. |
Beta Was this translation helpful? Give feedback.
-
Thank you for reporting.
|
Beta Was this translation helpful? Give feedback.
-
Thank you both for the quick replies and the useful information!
That sounds like a good plan :)
I can completely understand that and I also wouldn't want that in my own codebase. What I meant with "DSL wrapper" before could maybe be achieved in a different project and wouldn't have to be a part of
I agree to some degree, but I also think "nice" (which I would interpret as readable and robust) code plays an important role not only when expanding a codebase, but especially with maintenance (of programs using timefold) in mind. And that's possible in many programming languages. Regarding "idiomatic" code: My opinion here is that adhering to frequent patterns and conventions found in a programming language makes it easier to integrate new people into a team. So in the end, it's about standards. Still, I can completely understand that from the standpoint of an optimization library developer runtime performance and (library) maintenance outweigh ergonomics of use (especially if the number of Kotlin users is comparatively small).
If there is any assistance wanted here, I'd be glad to open a PR. Also seems like a rather low hanging fruit to me.
I think I'd really like getting rid of no-args-ctors. However, as of now, I don't know nearly enough about internal details of timefold to be helpful here. I still would be willing to try, but no guarantees :) I think, these two changes (Nullable/NotNull annotations and removing no-arg ctors) would already be very convenient to have and the second one would also partially address immutability (in the sense that |
Beta Was this translation helpful? Give feedback.
-
You can try providing a PR adding the annotations in places where you see fit. We can then review the full extent of those changes and discuss if that's something we're willing to maintain upstream in perpetuity.
I've been thinking about that a bit more and I really don't think this applies to the solver; rather, it applies to the examples and quickstarts, which is user code. In other ways - you should be able to do without no-arg-ctors if you choose to write code like that. However, maybe I forgot/did not expect some places. If you list places where we force you to use no-arg constructors, we can discuss what to do about those. |
Beta Was this translation helpful? Give feedback.
-
We've just recently been migrating toward Kotlin to get the syntax a little closer to the rest of our stack which is written in Typescript. We're still mid-migration, but just wanted to add that we are also using Kotlin now and would love to see the PoC @ge0ffrey |
Beta Was this translation helpful? Give feedback.
-
It seems I probably misunderstood @ge0ffrey before. If I just use @JsonCreate (is that from Jackson btw?) to allow proper deserialization, the the no-arg ctor shouldn't be required? That could actually be quite "nice" ;)
I suppose the PoC with nullability annotations would mainly improve the API that interacts with Timefols directly. In the Javadoc, there are already lots of parameters denoted as nullable/non-null - it's just that the annotations required by kotlin to corrctly interpret a type as nullable or non-nullable have never been added |
Beta Was this translation helpful? Give feedback.
-
I think that it would remove part of the pain, yes. But I'm not sure how our cloners would deal with such entities; that remains to be tried. (You can write your own cloners, so that part of the pain can be eliminated too, but writing cloners is a messy business, and definitely boilerplate. Much worse than having to deal with no-arg constructors, in my opinion.) |
Beta Was this translation helpful? Give feedback.
-
For nullable annotations, this approach worked well (very similar to how Spring became Kotlin friendly): |
Beta Was this translation helpful? Give feedback.
-
"We need to get them from JSpecify (credit: Anton at JFokus)" |
Beta Was this translation helpful? Give feedback.
-
Kotlin notebook thread: #384 |
Beta Was this translation helpful? Give feedback.
-
Note on the constructor/immutability part of this discussion: However, I remembered the no-arg gradle plugin for kotlin which for whatever reason I didn't have on my mind when starting this discussion back in August.
Using the following configuration in my
I was able to rewrite something like this
to this:
Which basically checks
It might be worth mentioning this in the documentation or adjusting the kotlin quickstarts. Maybe (don't know if it'd be overkill or if it would be even possible to configure a compiler plugin this way) even something like a separate I'd be glad to help on this when I have some spare time left between work and family - provided adjustments like these would be endorsed by the timefold team. Any thoughts @ge0ffrey @triceo ? |
Beta Was this translation helpful? Give feedback.
-
Good point. This is already a very strong argument for including this in the quickstart; if this is what the ecosystem typically does, who am I to object.
I agree.
It would be interesting to understand what happens when IntelliJ decompiles the class.
Thank you.
Yes, and I subscribe to that opinion myself. :-) That said, Kotlin is clearly here to stay, so it makes sense for us to try to accomodate its users as good as we can.
I think you raised some good points. If you want to introduce this into the Kotlin quickstart, I'll merge your PR. I appreciate you taking the time to go over this with me! |
Beta Was this translation helpful? Give feedback.
-
Peter, yes, we welcome improvements that make it easier to use Timefold Solver from Kotlin :) Thanks for looking into this with Lukas. |
Beta Was this translation helpful? Give feedback.
-
I'm currently looking into adding JSpecify annotations to the IMO, this might be a good way to avoid cluttering the code with too many annotations. However, when I started using this on interfaces in the I guess, it is preferable in the long run to use I would like some opinions on how to proceed here (would be great if one of you could chime in@triceo @ge0ffrey) to save some effort and prevent errors. I suppose there are some options:
I guess I found my preferred solution when writing this (number 1), but it'd still be nice to get a second opinion here. :) |
Beta Was this translation helpful? Give feedback.
-
On this topic, there is one change that I am hoping may be easy for you to do with a timefold-kotlin library or something. I tried to use an IntValueRange provider for work I was doing, but IntValueRange supplies Java integers, while my solution is using Kotlin Int, so I wasn't able to use it. If you made kotlin versions of some of these primitive utility tools that would be handy. I CAN code my app to use java.lang.Integer, but then I lose out on some Int related extensions and infixes. In the end I just use a List as my range provider. I can live with having to use |
Beta Was this translation helpful? Give feedback.
-
Im currently working on my second project (first one in a scheduling domain, second one a VRP) using kotlin as programming language and optaplanner as optimization library.
Generally, being able to use Kotlin feels like a big productivity boost when writing domain logic or application logic. However, when it comes to integrating optaplanner, a few things don't really feel idomatic:
var
slateinit var
s (or alternatively nullableval
s, which theoretically could beval
sI completely understand that most of these issues arise due to optaplanner/timefold being written in Java and performance being a main concern. It still would be pretty nice if there was the possibility to use timefold in a more kotlin-idiomatic way than it was/is possible with optaplanner.
That leads me to some questions:
I'd be interested to contribute to this topic, maybe also start with an external project as POC. Glad about any hints and ideas :)
Beta Was this translation helpful? Give feedback.
All reactions