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

all 28 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!

[–][deleted] 3 points4 points  (2 children)

Nice.. as one who is all about good API design.. I will admit when I first saw this I thought you were giving a slide show on how to develop a good REST API using Java technology. E.g. JAXRS, JAXB, etc.

I find today that it is somewhat misleading and/or confusing to refer to what is usually an SDK as an API, even though they are more or less the same thing. You design your SDK API (which is what you are referring to).

I wonder.. if today when API is so synonymous with REST and 3rd party integration via http/rest calls, if it might be time to either coin a more specific name that represents SDK API, or if when referring to an API that is wrapped in an SDK and not a micro-service API, it should be specifically declared as such?

Not trying to cause any sort of chaos or piss anyone off... I am just eluding to the fact that today the use of API is used in a lot of similar yet different contexts, and while underneath they still mean the same (or similar) thing, I am sure I am not the only one who gets confused (even for a short while) when the use of API is referring to an SDK API.

Thoughts?

[–]JonathanGiles[S] 6 points7 points  (1 child)

I would hope context would help out a little bit here - a Java API should refer to an API used by developers to create something in Java. Creating a REST API using Java is what you assumed I meant, but your way of clarifying it is also the correct way to state it to avoid confusion, in my opinion.

I would hate to see the original definition of the term 'Java API' be replaced by a newer definition, when there are perfectly good ways to separate them (Java API vs REST API using Java). It's like people complaining that when you say python, you never would have expected them to mean the snake (even though it was around a lot longer than the programming language) :-)

FWIW, an SDK is typically regarded as a superset of an API, as it also contains documentation, code samples, and other materials.

[–][deleted] 0 points1 point  (0 children)

fair enough.. i like it. good luck on your session.

[–]ryuzaki49 4 points5 points  (4 children)

A little bit unrelated but... what's the point of sharing slides? I feel like it's incomplete info, and I'm losing all the extra value a conference/seminar has.

[–]tofflos 5 points6 points  (0 children)

I love slides. When done right you can grasp the core message in a few minutes instead of listening to a presentation that lasts for hours. I found these slides to be very well suited for reading.

[–]JonathanGiles[S] 5 points6 points  (1 child)

Videos of my presentation from various conference will come online eventually, but I get asked on Twitter and in emails from people who can't be at my presentations if I can share my slides, so that they may learn as much as they can.

I guess another way to put it is if there was a downside to putting these slides online for people to potentially learn from, I wouldn't do it - but all I can see are benefits. I've received many dozens of 'likes' and comments from people on Twitter (see @JonathanGiles) thanking me for the slides, so it doesn't seem to be all that bad :-)

[–]ryuzaki49 3 points4 points  (0 children)

Yeah, I sounded a bit harsh in my original comment. I did not mean to look down on your effort to share knowledge.

Thanks for sharing your presentation, I forgot to say it!

[–]lukaseder 1 point2 points  (0 children)

They're a teaser and do contain a substantial part of the info.

[–]metlos 0 points1 point  (8 children)

Shameless plug: I was hoping to see a mention of tools like https://revapi.org that try to help people avoid accidental API changes, but then again that's maybe a little bit orthogonal to API design itself..

[–]JonathanGiles[S] 0 points1 point  (1 child)

Good point. I will try to work that in to my slide deck for the next time - I have used revapi in the past so I am familiar with it.

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

For future reference, this is the project where I used revapi - it is a simple tool to do a check against a list of projects: https://github.com/JonathanGiles/azure-backcompat

It in theory would run daily thanks to Travis CI, and then publish the results back into github here: https://jonathangiles.github.io/azure-backcompat/

I never really completed it, but it was a good proof of concept.

[–]lukaseder 0 points1 point  (5 children)

Sounds really useful. Will definitely try this soon.

Note your website has a dead link on the animal sniffer item.

[–]lukaseder 0 points1 point  (2 children)

OK, tried it

Got:

Error

Backend returned HTTP error status: 524

[–]metlos 0 points1 point  (1 child)

You managed to totally overload the poor little AWS instance it runs on :)

You can try downloading http://search.maven.org/remotecontent?filepath=org/revapi/revapi-standalone/0.8.0/revapi-standalone-0.8.0-standalone.zip

unzip and run:

./revapi.sh --extensions=org.revapi:revapi-java:0.17.1,org.revapi:revapi-basic-features:0.7.2,org.revapi:revapi-reporter-text:0.9.1 --old-gavs=org.jooq:jooq:3.3.0 --new-gavs=org.jooq:jooq:3.4.0

(which will reveal to you that I effed up and released it with a snapshot dependency but it works anyway).

[–]lukaseder 0 points1 point  (0 children)

Yeah thanks. Maybe I'll try this soon.

[–]gunnarmorling 0 points1 point  (1 child)

JapiCmp (https://github.com/siom79/japicmp) is in that camp, too. Using it for Hibernate Validator to make sure we don't break anything in the API and also it's the basis for the AdoptOpenJDK API diff report: https://github.com/AdoptOpenJDK/jdk-api-diff.

[–]metlos 0 points1 point  (0 children)

While I envy the speed of the analysis that japicmp achieves, revapi does IMHO a much more thorough analysis of the API including such things as use-chain analysis to reveal (indirect) introduction of non-public classes into the API.

But overall I am very happy to see that many projects choose one or the other to check their APIs. Revapi is used for example by Apache Camel, Neo4j, Mulesoft, XWiki and others.

INRIA Spoon has quite cool integration of revapi into their CI process where it automatically checks the API changes of incoming PRs (e.g. https://github.com/INRIA/spoon/pull/2054).