“Подскажи где можно почитать про Fluent API” - такой вопрос мне задал один из коллег, когда увидел в нашем проекте, модуль, API которого был реализован с применением Fluent подхода. Немного покопавшись на различных ресурсах я, к своему удивлению, понял что информации на эту тему не так много, если не сказать “ох как мало”. И в основном это success story использования той или иной библиотеки. Но вот что касается того как проектировать такой интерфейс и писать код, его реализующий - практически ничего кроме тривиальных примеров.
Так родилась идея подробно рассмотреть тему Fluent API дабы те, кого она интересует имели возможность удовлетворить свое любопытство.
Сразу отвечу на невысказанный пока вопрос - Кто этот человек, который решил что имеет право на то чтобы писать на эту тему и почему собственно он так решил?
Всем привет, меня зовут Саша и я программист (в ответ нестройный хор коллег по клубу анонимных программистов - здравствуй Саша). Программист я хронический, история зависимости насчитывает не один десяток лет и множество языков программирования. Но последние лет 10 моим основным языком разработки является Java.
Лет 12 назад я для себя открыл Fluent API, надо сказать открыть я хотел совсем другое, но как часто случается в нашей индустрии в статье про TDD была описана реализация модуля с Fluent API и если в части TDD ничего полезного я оттуда не вынес, то подход к написанию кода в виде почти человеко читаемого текста меня зацепил.
С тех пор я реализовал великое множество неудачных Fulent API и некоторое количество вполне приемлемых, так что точно могу поделиться опытом того как делать не надо (что иногда важнее чем best practice) и возможно подсказать несколько полезных моментов тем, кто только начинает пробовать “на зуб” данный подход.
Прежде всего хочется осветить следующие вопросы:
Что такое Fluent API? (эта статья)
В каких случаях имеет смысл применять данный подход?
Как подходить к проектированию 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)

Android1983
11.12.2025 16:19Привет автор.
Хочу сказать что любой человек работающий над задачей и не важно один или с командой имеет право писать статьи.
Подытожив можно сказать что статья в той или иной степени будет полезна всем программистам на языке программирования Java.
AlekseyShibayev
Мне нравится fluent api. Стараюсь делать всякий раз, когда у логики чёткие границы и ожидается частое переиспользование. Однако, классического варианта не всегда хватает. Хочется чтобы в "кишках" был доступ к "магии спринга". Надеюсь, у вас будет про это в следующих статьях. О варианте как я это делаю, я писал статью тут на хабре.
GFIce Автор
Почитал Вашу статью, отличный пример использования данного подхода.
Я, если честно, не планировал привязываться к конкретной технологии, а рассказать общие подходы, которые можно применять как в рамках Spring так и без него, в том числе и в других языках. Надеюсь этот факт не сильно расстроит :)