“Подскажи где можно почитать про Fluent API” - такой вопрос мне задал один из коллег, когда увидел в нашем проекте, модуль, API которого был реализован с применением Fluent подхода. Немного покопавшись на различных ресурсах я, к своему удивлению, понял что информации на эту тему не так много, если не сказать “ох как мало”.  И в основном это success story использования той или иной библиотеки. Но вот что касается того как проектировать такой интерфейс и писать код, его реализующий - практически ничего кроме тривиальных примеров.

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

Сразу отвечу на невысказанный пока вопрос - Кто этот человек, который решил что имеет право на то чтобы писать на эту тему и почему собственно он так решил?

Всем привет, меня зовут Саша и я программист (в ответ нестройный хор коллег по клубу анонимных программистов - здравствуй Саша). Программист я хронический, история зависимости насчитывает не один десяток лет и множество языков программирования. Но последние лет 10 моим основным языком разработки является Java. 

Лет 12 назад я для себя открыл Fluent API, надо сказать открыть я хотел совсем другое, но как часто случается в нашей индустрии в статье про TDD была описана реализация модуля с Fluent API и если в части TDD ничего полезного я оттуда не вынес, то подход к написанию кода в виде почти человеко читаемого текста меня зацепил.

С тех пор я реализовал великое множество неудачных Fulent API и некоторое количество вполне приемлемых, так что точно могу поделиться опытом того как делать не надо (что иногда важнее чем best practice) и возможно подсказать несколько полезных моментов тем, кто только начинает пробовать “на зуб” данный подход.

Прежде всего хочется осветить следующие вопросы:

  • Что такое Fluent API? (эта статья)

  • Зачем он нужен (и нужен ли вообще)?

  • Чем мы платим за ту самую Fluent-ность нашего кода?

  • В каких случаях имеет смысл применять данный подход?

  • Как подходить к проектированию Fluent API?

  • Какие подходы можно использовать для реализации спроектированного API?

  • Как его тестировать? И что более интересно как тестировать код, использующий зависимости с Fluent API?

  • Ну и потренируемся на кошках конечно. Реализуем несколько проектов, максимально приближенных к жизни.

Слона, как принято в приличном обществе, будем есть по кусочкам - каждому вопросу из списка выше выделим отдельную статью чтобы каждую можно было прочитать за время пока компилируется и запускается сервис на Spring Boot =)

Примеры в статьях приведены на Java, но подходы, описанные в них, универсальны для многих современных языков программирования. Итак, поехали!

Что же такое этот ваш Fluent API? 

Это подход к проектированию API позволяющий писать код в виде цепочек вызовов (method chaining), в идеале читающихся как предложения на естественном языке. Принято считать что он даден нам в ощущениях ни кем-нибудь а такими уважаемыми людьми как Эрик Эванс и Мартин Фаулер. На самом деле они дали емкое название подходу, который существовал с 70-х годов прошлого века, там самым популяризировав его для широких масс.

Основная суть - создание специализированного DSL под конкретную задачу, позволяющего с одной стороны сделать более читаемым код в контексте задачи, а с другой уменьшить порог входа для написания кода c использованием такого DSL.

Отлично! Cловесный фоторобот зверя по имени Fluent API составили, но возникает законный вопрос - существует ли он в дикой природе или это чисто мифическое создание? 

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

    var person = Person.id(3)
                       .name("Игорь")
                       .age(27)
                       .gender(Gender.MALE)
                       .buld();

Но даже если вы никогда не писали на Java, но знакомы с другими языками программирования, для вас не составит труда понять что делает этот код.

Это пример того, как Fluent подход используется в реализации паттерна Builder. Каждый из вызовов в цепочке отвечает за один шаг на пути к инициализации полноценного объекта. 

Чем это лучше чем вызов конструктора? - Позволю себе подвесить в данном вопросе интригу и ответить на него в последующих статьях.

Но, как говорится, не билдером единым… 

Мы можем, например:

Реализовать репозиторий для ранее представленной сущности Person:

    PersonRepository respository;

    Person person = repository.person()
                              .withName(“Игорь”)
                              .withAge(27)
                              .withGender(Gender.MALE)
                              .add();

    Person person = repository.person(1).get();

    boolean success = repository.person(1).withAge(28).update();

    boolean success = repository.person(1).delete();

Валидировать значения:

    Optional.ofNullable(value)
            .orElseThrow(() -> new IllegalArgumentException());

Выполнять различные преобразование данных:

    String a = List.of(1,2,3).stream()
                             .map(number -> number.toString())
                             .collect(Collectors.joining(“, “));

Управлять выполнением задач в многопоточной среде:

    CompletableFuture.runAsync(action)
                     .thenApply(function)
                     .get();

Или даже запускать сценарии распределенной обработки:

    Dispatcher.callService(a).with(“hello”)
              .thenCallService(b).with(“world”)
              .thenReturn(success);

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

В последующих статьях будут освещены остальные вопросы из намеченного плана. По мере выхода статей к пунктам плана будут привязываться соответствующие ссылки.

Спасибо за уделенное время.

Комментарии (3)


  1. AlekseyShibayev
    11.12.2025 16:19

    Мне нравится fluent api. Стараюсь делать всякий раз, когда у логики чёткие границы и ожидается частое переиспользование. Однако, классического варианта не всегда хватает. Хочется чтобы в "кишках" был доступ к "магии спринга". Надеюсь, у вас будет про это в следующих статьях. О варианте как я это делаю, я писал статью тут на хабре.


    1. GFIce Автор
      11.12.2025 16:19

      Почитал Вашу статью, отличный пример использования данного подхода.

      Я, если честно, не планировал привязываться к конкретной технологии, а рассказать общие подходы, которые можно применять как в рамках Spring так и без него, в том числе и в других языках. Надеюсь этот факт не сильно расстроит :)


  1. Android1983
    11.12.2025 16:19

    Привет автор.
    Хочу сказать что любой человек работающий над задачей и не важно один или с командой имеет право писать статьи.
    Подытожив можно сказать что статья в той или иной степени будет полезна всем программистам на языке программирования Java.