gojuno / koptional

Minimalistic Optional type for Kotlin that tries to fit its null-safe type system as smooth as possible.
Apache License 2.0
289 stars 21 forks source link

Java interop version of toOptional() #17

Closed Egorand closed 6 years ago

Egorand commented 6 years ago

We're sometimes calling toOptional() from Java and it would be more convenient to have Optional.toOptional() instead of OptionalKt.toOptional().

bensandee commented 6 years ago

I'm just a consumer of the API (private repo, would be affected by the breaking change but not in a way I couldn't recover from in 5 minutes), but it seems that the argument can be distilled into two things:

Let me ask a rhetorical question -- when driving, do you use a turn signal when you think nobody is looking? IMO, it's best to do the "right thing" even when nobody's looking.

arturdryomov commented 6 years ago

@tbsandee, I just got some serious 13 Reasons Why vibe.

Still not convinced that renaming can be considered a behavior change though. I’m kind of in, but still consider this case an extreme over pragmatism at its best.

The worst thing I can imagine right now is related to an argument from Artem about Optional being an exchange class between components.

Should we provide an interop then? I need a drink.

vanniktech commented 6 years ago

I sure hope it's a good drink :D

artem-zinnatullin commented 6 years ago

We don't have to provide interop (although we can):

artem-zinnatullin commented 6 years ago

Soooo?

artem-zinnatullin commented 6 years ago

Can I go ahead and:

  1. Merge this PR
  2. Make a PR with groupId and packageName update
  3. Release v2
  4. Provide single cli command in release notes to update imports

?

Pros:

Cons:

I'd like to get this going.

arturdryomov commented 6 years ago

@artem-zinnatullin, I’m in. Still sounds ridiculous for such a small library, but we made a mistake not taking Java into account and we are gonna pay the price of having 2 in the package name. Let’s do it.

artem-zinnatullin commented 6 years ago

Kool, implementing then 👍

artem-zinnatullin commented 6 years ago

@Egorand there is a compilation error (you can see it on CI):

e: /opt/project/koptional/src/main/kotlin/com/gojuno/koptional/Optional.kt: (1, 1): Duplicate JVM class name 'com/gojuno/koptional/Optional' generated from: package-fragment com.gojuno.koptional, Optional
e: /opt/project/koptional/src/main/kotlin/com/gojuno/koptional/Optional.kt: (5, 1): Duplicate JVM class name 'com/gojuno/koptional/Optional' generated from: package-fragment com.gojuno.koptional, Optional
artem-zinnatullin commented 6 years ago

That'd be nice!

artem-zinnatullin commented 6 years ago

@Egorand can you please update PR to make it compile and add few Java test cases?

Egorand commented 6 years ago

Sure, will update the PR tomorrow

Egorand commented 6 years ago

I think I've actually discovered a better solution that won't break existing clients and will improve Java experience: adding a companion object with an extra toOptional() method. Kotlin clients should continue using the top-level extension function, Java clients would have to change from OptionalKt.toOptional() to Optional.toOptional() (the latter still works though). Also:

  1. There's no way to fix compilation with @JvmName since we're ending up with two classes called Optional - one for the sealed class Optional and the other for the top-level function - that's a broken approach.
  2. I added a test in Java, I used plain JUnit, let me know if you'd like me to make it in Spec for Java (never used it, is it even a thing?) or JUnit 5 or anything else.
  3. I thought about documenting the two toOptional() version, but I see that there's no documentation at all in the file - should I add it?
artem-zinnatullin commented 6 years ago
  1. Indeed, I don't see a way to solve this atm
  2. Yep, looks good 👍
  3. I have a stupid idea that seems to work (see below)

So, companion obj + @JvmStatic pretty much hides this 2nd toOptional() from Kotlin code, right.

What if we "hide" the first toOptional() from Java? #yolo

If you add @JvmName("_toOptionalKotlin") to the top-level toOptional() function, this will remove it from autocomplete on Java side

Egorand commented 6 years ago

That would be a breaking change, since Java clients who were using OptionalKt.toOptional() will have to use the new method name. I like the idea in general, and it would be good to implement it for the next major release, for now I think it's fine to document correct usage for Kotlin and Java.

artem-zinnatullin commented 6 years ago

Yeah, we already agreed on 2.x release though.

Would be great to make initial approach with single toOptional function declared properly for both Kotlin and Java work…

Technically it seems okay to have toOptional declared as a static function in Optional class, maybe we should submit a ticket to https://youtrack.jetbrains.com and describe our use case

Another solution is to write Koptional core in Java with proper Kotlin annotations and properly placed functions and see if Kotlin compiler works with that, I mean, that sounds like a fun experiment (not that I have time for it tho…)

Egorand commented 6 years ago

The problem is that extension functions declared inside classes or objects can only be used as extensions inside those classes/objects, hence you'll need to always do Optional.toOptional(), even in Kotlin. Rewriting the core in Java destroys the potential of making the library multi-platform. Opening a discussion on YouTrack sounds like a great idea, I'd love to get more insight on the issue.

arturdryomov commented 6 years ago

Let’s go ahead without hacks and do a 2.x as it was proposed in the first place. We screwed up with Java compatibility and it is OK to acknowledge it.

arturdryomov commented 6 years ago

So, actually, what do we agree on?

Egorand commented 6 years ago

As I mentioned, the change is not breaking, so it'd be fine as a minor update

dmitry-novikov commented 6 years ago

@ming13, @artem-zinnatullin, are you OK to merge it as minor update?

artem-zinnatullin commented 6 years ago

ok, I double checked current version of PR, I think I'm good to merge this as non breaking change 👍

Kotlin:

Java:

@Egorand just couple things:

Egorand commented 6 years ago

Yeah no worries! I'll try to get the changes in today

Egorand commented 6 years ago

@artem-zinnatullin 0dafabb

artem-zinnatullin commented 6 years ago

Sorry for delay, had miscommunication with Artur and was waiting for his review while he was waiting for me to merge heh

Egorand commented 6 years ago

Sweet! Are you planning a release any time soon?

artem-zinnatullin commented 6 years ago

Yep, we can do a release with this PR only or wait for rest

artem-zinnatullin commented 6 years ago

@Egorand 1.4.0 was just released with this change, guys at Juno have some workload backpressure, I'm gonna take care of processes for some time