Статьи

Не обманывайтесь универсальностью и обратной совместимостью.

Недавно у меня была очень интересная дискуссия с Себастьяном Грубером из Ergon, очень ранним клиентом jOOQ , с которым мы тесно связаны. Разговор с Себастьяном привел нашу команду инженеров к выводу, что мы должны полностью переписать API jOOQ. Прямо сейчас у нас уже есть много генериков для различных целей, например

  • Обобщения для типов столбцов, такие как
    1
    2
    interface Field<T> { ... }
    Field<String> field = BOOK.TITLE;
  • Обобщения для типов таблиц, такие как
    1
    2
    interface Table<R extends Record> { ... }
    Table<BookRecord> books = BOOK;
  • Комбинированные дженерики, в которых используются как <T> и <R>
  • … и многое другое

Иногда вы просто не можете предвидеть, сколько разных универсальных типов вам понадобится для ваших классов и интерфейсов через два года, и проблема с Java заключается в следующем: вы можете генерировать ваши классы только один раз. Давайте предположим, что у вас всегда был такой тип:

1
class Foo {}

Теперь вы знаете, что вам нужны два параметра общего типа прямо сейчас :

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

Это сработает, и весь существующий клиентский код все равно будет скомпилирован с предупреждением rawtype. Но как только вы опубликовали Foo<Bar, Baz> , вы больше не можете добавлять в него другие переменные типа или удалять их. Каждая модификация нарушит код клиента!

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

Решение: общие родовые типы

Мы не хотим возлагать это бремя на наших клиентов, тяжелое бремя обратной несовместимости. Вот почему мы сейчас публикуем наш следующий выпуск jOOQ с новой функцией, которую мы называем универсальными универсальными типами . Как это работает? Это просто. Мы узнали от лучших дизайнеров баз данных, которые уже использовали универсальные типы столбцов. В SQL, если вы столкнетесь с такой проблемой, вы просто напишите:

01
02
03
04
05
06
07
08
09
10
11
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),
    -- [...]
);

Теперь ваша схема SQL безопасна на долгие годы. Мы сделаем то же самое в Java:

01
02
03
04
05
06
07
08
09
10
11
class Foo<
    Bar,
    Baz,
    Fizz,
 
    Generic1,
    Generic2,
    Generic3,
    Generic4,
    // [...]
> {}

Таким образом, мы будем генерировать все наши типы, чтобы иметь ровно 256 параметров универсального типа. 256 было разумным пределом, который MS Access выбрал для числа возможных столбцов. Таким образом, нашим клиентам потребуется только один раз перейти на новую версию jOOQ, и с тех пор обратная совместимость универсального типа будет гарантирована навсегда.

Удачного кодирования!