Fluent API: что такое и зачем нужен



Fluent API набирает популярность последние лет 5 и часто вызывает вопросы:

🤔 В чём его польза?

🤔 Чем он отличается от билдера?

🤔 Когда нужен, а когда нет?



В этом и следующем посте постараюсь ответить на эти вопросы.



Основная задача Fluent API — улучшить читаемость кода. Для этого:



🔸 Несколько методов объединяются в цепочку и вызываются друг за другом. Получается логический блок, который воспринимается как единое целое

🔸 Названия методов не ограничиваются глаголом



Пример:

CompletableFuture.runAsync(…).thenRun(…).exceptionally(…);




Fluent API не всегда уместен и не всегда реализован удачно. Список формальных условий определить сложно, на практике такой формат часто выбирается интуитивно. Поэтому рассмотрим побольше примеров!



Хороший пример из AssertJ:

assertThat(str).startsWith(…).contains(…);




За раз пишем несколько проверок для строки str. Без Fluent API кода будет больше



Хороший пример из Мокито:

when(mock.method()).thenReturn(…).thenReturn(…).thenThrow(…);



Читается как одно предложение. Мне даже сложно представить, как это написать в “традиционном” стиле:)



Прекрасный пример из Spring JDBC:

List<User > users = jdbcClient.sql(…)

.param("rating", 5, Types.INTEGER)

.query(mapper)

.list();




Почему пример прекрасен? Потому что Fluent API скрывает работу с объектом PreparedStatement. Код получается не только короче, но и проще🔥



😐 Так себе пример из Spring Data:

ExampleMatcher matcher = ExampleMatcher.matching()

.withIgnorePaths(…)

.withStringMatcher(StringMatcher.ENDING);




Приставка with у методов лишняя, название последнего метода неудачное



Плохой пример из SLF4J:

logger.atInfo().log(…);




Классический logger.info(…) короче и удобнее



Плохой пример из популярного джава канала:

Person person = new Person().setName(…).setAge(…);



Тоже никакой пользы от Fluent API, ни по читаемости, ни по удобству использования.



Итого



Fluent API подойдёт, когда работа с объектом проходит в несколько шагов, но единым логическим блоком. Основная цель — улучшить читаемость. Высший пилотаж — повысить с помощью Fluent API уровень инкапсуляции.



Чтобы сделать удобно и красиво, нужен опыт, насмотренность и немножко вдохновения:)



Отдельный случай — Fluent API при создании объектов. Здесь часто возникает путаница с билдером, и непонятно, что когда использовать. Этот вопрос я разберу отдельно в следующем посте🔥