Подтвердить что ты не робот

Свободные интерфейсы и негерметичные абстракции

Что такое свободный интерфейс? Я не могу найти хорошее определение этого, но все, что я получаю, - это примеры длинного кода на языке, с которым я не очень хорошо знаком (например, С++).

Кроме того, что такое нечеткая абстракция?

Спасибо

4b9b3361

Ответ 1

Свободный интерфейс - это API, который позволяет вам писать код, который читается более или менее как обычный английский. Например:

Find.All.Questions(Where.IsAnswered == true);

Метод-цепочка обычно используется как часть реализации, но есть нечто большее, чем это. Чтобы процитировать Fowler:

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

Он также часто называется внутренним DSL, поскольку синтаксис напоминает DSL, но он реализован внутри основного языка вместо обрабатывается парсером.

Ответ 2

Протекающая абстракция - это абстракция, где детали лежащей в основе реальности часто "просачиваются".

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

Простым примером "утечки" в абстракции может быть обычный тип float. Кажется, он представляет общие реальные числа, и вы можете использовать его для выполнения базовых вычислений. Но в какой-то момент вы сталкиваетесь с сценарием, где 1/3 * 3!= 1 или 1 + 10 ^ -20 = 1. То есть, когда фактические данные реализации просачиваются, и абстракция ломается.

Ответ 3

Свободный интерфейс - термин Эрик Эванс, и это просто другое имя для цепочки методов. Мартин Фаулер написал пара статьи по этому вопросу, но это примерно выглядит так:

m_Window = window::with()
    .width(l_Width)
    .height(l_Height)
    .title("default window")
    .left(200)
    .top(200)
.create();

Свободный интерфейс обычно используется для создания именованных параметров на языке, который их не поддерживает (например, Идиома именованного параметра в С++) или на языках домена, чтобы сделать код более плавным.

Я видел, как они использовались для всего, от библиотек обработки изображений, библиотек регулярных выражений, трехмерных библиотек. Другие примеры включают в себя построение древовидных структур, списков или других структур данных. Все, что требует построения сложных объектов (загрузка параметров), может использовать Fluent Interfaces, чтобы сделать его более читаемым. Например, сравните предыдущий пример с вызовом функции CreateWindow:

 ::CreateWindow(
      "Window class", 
      "Window title", 
      dwStyle, X, Y, 
      nWidth, nHeight, 
      hWndPant, hMenu, 
      hInstance, NULL
 );

Ответ 4

Здесь обычный ежедневный интерфейс:

public interface NotFluent
{
  void DoA();
  void DoB();
  void DoC();
}

И здесь свободный интерфейс:

public interface Fluent
{
  Fluent DoA();
  Fluent DoB();
  Fluent DoC();
}

Наиболее очевидным отличием является то, что когда мы возвращаем пустоту, мы вместо этого возвращаем экземпляр типа интерфейса. Понятно, что возвращенный интерфейс является CURRENT INSTANCE, а не новым экземпляром того же типа. Конечно, это не подлежит исполнению, а в случае неизменяемых объектов (например, строка) это другой экземпляр, но может рассматриваться как один и тот же экземпляр, только обновленный.

Вот примеры их использования:

NotFluent foo = new NotFluentImpl();
foo.DoA();
foo.DoB();
foo.DoC();

Fluent bar = new FluentImpl();
bar.DoA().DoB().DoC();

Обратите внимание, что свободный интерфейс легче использовать при соединении разных вызовов. IRL, проверьте методы расширения Linq и как каждый вызов предназначен для потока в другой. Ни один из методов не возвращает void, даже если это будет действительный результат.

Ответ 5

Объектно-ориентированный интерфейс свободен, если методы, выполняемые для возврата побочных эффектов self, так что такие методы могут быть соединены вместе.

В 1990 году я впервые столкнулся с плавными интерфейсами, когда Полиция интерфейса Modula-3 (я этого не делаю) потребовала, чтобы все методы инициализации возвращали объект, инициализированный. Я считаю, что это использование предшествует монетам термина "свободный интерфейс".

Ответ 6

В свободном интерфейсе объектные методы возвращают ссылку на объект, так что вы можете объединить вызовы метода.

Например, в NValidate я сделал это, чтобы упростить проверку параметров:

public City GetCity(string zipCode)
{
   zipCode.Assert("zipCode").IsNotNullOrEmpty().HasLength(5,10).Matches("\\d[5]-\\d[4]");
   // Continue processing
}

Я не могу говорить с просачивающимися абстракциями.

Ответ 7

Спасибо, ребята.

Отличное описание.

Моя мысль о беглых интерфейсах, где они были для читаемости. Я всегда мог прочитать цепочку методов и как один из них связан с предыдущим/следующим методом.

например. как плакат, который разместил пример проверки (я уже написал код, похожий на предыдущий).

Ответ 8

Neal Ford неплохо объясняет и дает примеры Fluent Interface в своей книге "Productive Programmer".

Традиционный объект или "bean" с геттерами/сеттерами:

Car car = new CarImpl();
MarketingDescription des = new MarketingDescriptionImpl();
desc.setType("Box");
desc.setSubtype("Insulated");
desc.setAttribute("length", "50.5");
desc.setAttribute("ladder", "yes");
desc.setAttribute("lining type", "cork");
car.setDescription(desc);

Познакомьтесь с той же потребностью в свободном интерфейсе:

Car car = Car.describedAs()
  .box()
  .length(50.5)
  .type(Type.INSULATED)
  .includes(Equipment.LADDER)
  .lining(Lining.CORK);