Как называется идиома, использующая цепочку методов для построения объекта?

21

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

Пример:

new Menu().withItem("Eggs").withItem("Hash Browns").withStyle("Diner");

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

Гарретт Холл
источник
3
Свободный интерфейс - это вопрос стиля. Если вы пишете API, предоставьте ему альтернативные формы.
Одед
1
Для дальнейшего обсуждения взгляните на этот вопрос: programmers.stackexchange.com/questions/69519/…
Эрик Кинг,
@Oded Можно использовать такой API без цепочки, просто сделав каждый вызов отдельным оператором, или у вас была другая идея для альтернативы?
Гаррет Холл
@GarrettHall - Конечно, это возможно, но тогда вы в конечном итоге называете вещи menu.withStyle("")без контекста. Вам нужно два API в таком случае.
Одед
2
@GarrettHall Точкой «свободного интерфейса» является цепочка методов, которая должна читаться как предложение. В этом смысле длинная цепочка методов не считается плохой. Но, и здесь я согласен с Одедом, было бы лучше также обеспечить ту же функциональность в более обычном синтаксисе. Таким образом, разработчик может выбрать, какой метод использовать.
Эрик Кинг,

Ответы:

37

Свободный интерфейс

Я всегда слышал о том, чтобы этот метод назывался « беглым интерфейсом », как его придумали Эрик Эванс (из известной доменно-управляемой разработки ) и Мартин Фаулер (из известной гибкой манифесты ).

Основными недостатками являются удобочитаемость (которую некоторые люди любят, а некоторые ненавидят), а также тот факт, что в некоторых случаях отладку может быть сложнее, потому что вся цепочка действий может рассматриваться как одно утверждение при ее прохождении.

Я, конечно, не считаю это анти-паттерном, хотя сам использовал эту технику всего несколько раз.

Эрик Кинг
источник
4
Обратите внимание, что сторонники довольно настаивают на том, что свободный интерфейс включает в себя гораздо больше, чем просто цепочку методов, хотя часто неясно, что еще подразумевается под этим термином.
Килиан Фот
Принято ли считать всю цепочку одним утверждением? Это звучит как плохо продуманная проблема отладчика для меня.
черничные
Я не сталкивался с отладчиком, который рассматривает цепочки как одно утверждение, но он все еще может быть болезненным, если вас интересует только один из методов в конце цепочки, в одной конкретной цепочке.
vaughandroid
1
Я работаю в C #, и отладчик .NET позволяет мне шагать в отдельные методы. На других языках я не так уверен.
Эрик Кинг,
1
@KilianFoth Как отмечалось в комментариях к вопросу, цепочечные методы в свободном интерфейсе должны читаться почти как предложение. Иногда это означает, что отдельные методы должны иметь имена, отличные от тех, которые считаются хорошей практикой
Izkata
5

Подобный метод цепочки обычно называется плавным интерфейсом, когда в цепочке есть какой-то поток или обнаруживаемость. В качестве альтернативы, вы можете думать о API, подобном jQuery, который в значительной степени опирается на цепочку методов, как о «не беглом», потому что акцент не делается на обнаружении - он больше для удобства.

Для вашего примера (с использованием withx, withy) вы можете рассматривать это как вариант шаблона Builder, потому что у вас есть специализированный класс, который, учитывая некоторое состояние (вызовы методов), знает, как вернуть правильно сконфигурированный объект.

Это не анти-паттерн, если используется правильно.

pfries
источник
Что такое открытость? Возможность найти нужные вам методы через автозаполнение API?
Иосия Йодер
Я не знаком с JQuery. Как их метод цепочки только для удобства, а не для обнаружения? Потому что есть так много способов связать, что это подавляет даже с автозаполнением?
Джозия Йодер
3

считается ли это анти-паттерном,

определенно не анти-шаблон. JQuery, вероятно, наиболее хорошо используемая реализация этого.

потому что, хотя он может читать более бегло, это может привести к длинным цепочкам методов

Да, может, но какова альтернатива? Вы можете закончить почти простым английским предложением, с api, направляющим вас к тому, что доступно и уместно.

ним чимпский
источник
... и вы получаете то, что вы хотите в 1 строке вместо 8 - 10. Что хорошо, если вы пишете только один вкладыш в терминале. Проще вызвать 1 команду, чем 10. Поскольку она свободно и методы имеют описательные имена, ее также легче читать. К сожалению, многое из этого в Python2 больше не может быть сделано в Python3 / Python4.
mckenzm
-3

Это называется «крушение поезда».

(Это анти-шаблон и против чистого кода)

Паттерн «крушение поезда» нарушает закон Деметры .

Марк
источник
3
Это не то же самое, что метод цепочки в статье, на которую вы ссылаетесь, где пример a.getB().getC().doSomething(). Этот пример плох, потому что «Ваш метод может вызывать методы непосредственно в своих собственных полях (но не в полях полей)». Здесь есть только 1 объект, который создается, и «вы можете играть с игрушками, которые вы сделали сами».
Nic