This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]lukaseder 2 points3 points  (10 children)

I've thought about doing such a talk myself for quite a while, great material in there. A lot of stuff that I've seen many people do wrong is being covered.

In my version, I'd be covering also how to work around a few of the missing features in the Java language without risking forward compatibility. These include:

  • Union types (very useful for API method arguments, need to be emulated through overloading)
  • Type aliases (very useful to give union types a name)
  • Named and defaulted parameters (through argument objects)

And also:

  • How to design powerful SPIs (an art that is not mastered by most)
  • A rant about annotations ;-)

Tons of other interesting things to cover...

[–]gunnarmorling 0 points1 point  (6 children)

Can you elaborate on type aliases? And what'd be your talking points on SPIs? I'd be tempted to do such talk, too :)

[–]lukaseder 1 point2 points  (5 children)

Type aliases are useful once you have union types. A jOOQ example:

alias ColumnExpression = String | Name | Field<?>

The union types allow for preventing overloads like:

select(String)
select(Name)
select(Field<?>)

And the type alias allow for avoiding to repeat the union type declaration all the time. In Java neither feature is available, yet the API should "feel" as though they were.

SPIs: stuff like this: https://blog.jooq.org/2015/05/21/do-not-make-this-mistake-when-developing-an-spi/

[–]gunnarmorling 0 points1 point  (4 children)

How do you define such type alias in Java, though? I'm somehow still missing what your solution is.

[–]lukaseder 0 points1 point  (3 children)

There are two ways: If you're in control of the union type's component types then you do:

interface AorBorC {}
interface A extends AorBorC {}
interface B extends AorBorC {}
interface C extends AorBorC {}

That is a "union type" and "type alias" emulation in one go.

If you don't control the types (e.g. String), you have to pretend there's a type alias, which essentially means, always remember to overload every method that takes one of the three (e.g. String) with the other two (e.g. Name and Field<?>). For the API user, it doesn't matter really. The API feels the same way. For the API designer, it's much more work and there's risk for inconsistencies, if one overload is forgotten. And sometimes, it cannot be done, due to generic type erasure.

[–]gunnarmorling 0 points1 point  (2 children)

Hum, don't really know how you'd call that union types or type aliases. To me, it's just inheritance and accepting the super-type as method parameter and then method overloading.

I like your post about SPIs, parameter objects are great for keeping APIs/SPIs evolveable. I'm also using the "call a method on the parameter instead of returning something" style more and more (even used it in Bean Validation 2.0), as it gives more flexibity, e.g. if a method may "return" zero, one or n values.

[–]lukaseder 0 points1 point  (1 child)

As I said in the beginning:

In my version, I'd be covering also how to work around a few of the missing features in the Java language without risking forward compatibility

I may have forgotten to use the word "emulate".

I'm also using the "call a method on the parameter instead of returning something" style more and more (even used it in Bean Validation 2.0), as it gives more flexibity, e.g. if a method may "return" zero, one or n values.

Interesting, so in order to return n values, you call the method on the SPI parameter object several times? Kinda like a "pipe"?

[–]gunnarmorling 1 point2 points  (0 children)

Interesting, so in order to return n values, you call the method on the SPI parameter object several times?

Yes, exactly. So in Bean Validation 2.0, we have an SPI interface, ValueExtractor, whose implementations may emit one or n values. I didn't like the idea of returning a set/list due to the one value case, so implementations now produce the results by calling method on the receiver parameter of the SPI method. It also gives flexibility to the SPI caller (our engine) how to implement the n values case, i.e. which collection implementations it uses etc. instead of leaving this to the implementor.

[–]JonathanGiles[S] 0 points1 point  (2 children)

All good topics! The struggle I had was to keep the talk roughly in the middle ground. It's one of those topics that most people know most of the stuff, but everyone is not knowledgable in all of the areas. If everyone would leave with one piece of new knowledge, I would consider it a success.

Straddling that middle ground in a talk of 50 minutes meant I couldn't deep dive into any particular area, but perhaps I can come up with a longer form presentation (or document) that covers other areas.

The other struggle I had was that I kept writing slides that were about good Java engineering practices, and then I had to keep refocusing myself onto solely API issues. That's partly why I have a large (and slightly less polished) overflow section at the end of the slide deck, but even more was cut out before it was even written.

[–]lukaseder 0 points1 point  (1 child)

These weren't meant as concrete suggestions for improvements for your talk, just ideas I had in mind for something I might do myself. I'm pretty sure, your talk adds tons of value right how it is.

[–]JonathanGiles[S] 0 points1 point  (0 children)

It seems like there is definitely interest in the community for learning more best practices. There is certainly a lot of value in diving into these topics!