Don’t be Fooled by Generics and Backwards-Compatibility. Use Generic Generic Types

I’ve recently had a very interesting discussion with Sebastian Gruber from Ergon, a very early jOOQ customer, whom we’re in close touch with. Talking to Sebastian has lead our engineering team to the conclusion that we should completely rewrite the jOOQ API. Right now, we already have lots of generics for various purposes, e.g.
  • Generics for column types, such as
    
    interface Field<T> { ... }
    Field<String> field = BOOK.TITLE;
    
    
  • Generics for table types, such as
    
    interface Table<R extends Record> { ... }
    Table<BookRecord> books = BOOK;
    
    
  • Combined generics where both <T> and <R> are used
  • … and much more
Sometimes, you just cannot anticipate how many different generic types you’ll need on your classes and interfaces two years down the line, and the problem with Java is: You can generify your classes only exactly once. Let’s assume that you’ve always had a type like this:

class Foo {}

Now you happen to know that you need two generic type parameters right now:

// Still compatible
class Foo<Bar, Baz> {}

That’ll work and all the existing client code will still compile, with a rawtype warning. But once you’ve published Foo<Bar, Baz>, you can no longer add more type variables to it, or remove them. Every modification will break client code!

// Breaking change
class Foo<Bar, Baz, Fizz> {}

The solution: Generic generic types

We don’t want to place that burden upon our customers, the heavy burden of backwards-incompatibility. This is why we’re now publishing our next release of jOOQ with a new feature that we call generic generic types. How does it work? It’s easy. We’ve learned from the best database designers who have already been using generic column types all along. In SQL, if you run into this kind of problem, you’d simply write:

CREATE TABLE foo (
    bar int,
    baz int,
    fizz int,

    generic_1 varchar(4000),
    generic_2 varchar(4000),
    generic_3 varchar(4000),
    generic_4 varchar(4000),
    -- [...]
);

Now your SQL schema is safe for ages to come. We’ll do the same in Java:

class Foo<
    Bar, 
    Baz, 
    Fizz,

    Generic1,
    Generic2,
    Generic3,
    Generic4,
    // [...]
> {}

We’ll thus generify all our types to have exactly 256 generic type parameters. 256 was the sensible limit that MS Access chose for the number of possible columns. That way, our customers will only have to upgrade to the new version of jOOQ once and from then on, generic type backwards-compatibility will be guaranteed forever. Happy coding!

7 thoughts on “Don’t be Fooled by Generics and Backwards-Compatibility. Use Generic Generic Types

      1. Well, unfortunately that was also just cheap humor, sorry. Got a new job and will have to learn some new stuff – MyBatis for the persistence layer, for example – so JOOQ is, while on my list of topics to look into (even before the humor ;-) ) out of interest, not something I will be able to invest time in…

        1. That is too bad. Investing time in jOOQ is like investing money in Google stocks (back in 2003). It is an initial investment, true, but some years later, you wouldn’t look back any longer. Investing time in MyBatis, however, is like investing in Sybase or Informix.

          But we can still talk about these things in a year :)

          1. Well, I consider myself a coding whore, my first priority is getting paid ;-) I’ve got some experience with JPA and Hibernate, now MyBatis is a new concept for me – and as I said, I’ll probably have a look at JOOQ later (a year sounds reasonably), never hurts to know things even if you can’t actively use them. But before that, I really don’t have an opinion about these systems, except that I get money for using one of them but not for the other…;-)

  1. And… JavaCodeGeeks releases the post on April 3rd, making it so it’s a late April Fools joke, which doesn’t really work. You had me fooled (and confused as to how it was a good idea) until you said you’d keep 256 types.

Leave a Reply