Что такое свободный интерфейс? Я не могу найти хорошее определение этого, но все, что я получаю, - это примеры длинного кода на языке, с которым я не очень хорошо знаком (например, С++).
Кроме того, что такое нечеткая абстракция?
Спасибо
Что такое свободный интерфейс? Я не могу найти хорошее определение этого, но все, что я получаю, - это примеры длинного кода на языке, с которым я не очень хорошо знаком (например, С++).
Кроме того, что такое нечеткая абстракция?
Спасибо
Свободный интерфейс - это API, который позволяет вам писать код, который читается более или менее как обычный английский. Например:
Find.All.Questions(Where.IsAnswered == true);
Метод-цепочка обычно используется как часть реализации, но есть нечто большее, чем это. Чтобы процитировать Fowler:
Я также заметил распространенное заблуждение - многие люди, кажется, приравнивают плавные интерфейсы с помощью метода Chaining. Конечно, цепочка - это обычная техника для использования с плавными интерфейсами, но истинная беглость намного больше.
Он также часто называется внутренним DSL, поскольку синтаксис напоминает DSL, но он реализован внутри основного языка вместо обрабатывается парсером.
Протекающая абстракция - это абстракция, где детали лежащей в основе реальности часто "просачиваются".
Все абстракции лежат более или менее, но иногда абстракции настолько плохо подходят для основной реальности, что наносит больше вреда, чем это помогает.
Простым примером "утечки" в абстракции может быть обычный тип float. Кажется, он представляет общие реальные числа, и вы можете использовать его для выполнения базовых вычислений. Но в какой-то момент вы сталкиваетесь с сценарием, где 1/3 * 3!= 1 или 1 + 10 ^ -20 = 1. То есть, когда фактические данные реализации просачиваются, и абстракция ломается.
Свободный интерфейс - термин Эрик Эванс, и это просто другое имя для цепочки методов. Мартин Фаулер написал пара статьи по этому вопросу, но это примерно выглядит так:
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
);
Здесь обычный ежедневный интерфейс:
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, даже если это будет действительный результат.
Объектно-ориентированный интерфейс свободен, если методы, выполняемые для возврата побочных эффектов self
, так что такие методы могут быть соединены вместе.
В 1990 году я впервые столкнулся с плавными интерфейсами, когда Полиция интерфейса Modula-3 (я этого не делаю) потребовала, чтобы все методы инициализации возвращали объект, инициализированный. Я считаю, что это использование предшествует монетам термина "свободный интерфейс".
В свободном интерфейсе объектные методы возвращают ссылку на объект, так что вы можете объединить вызовы метода.
Например, в NValidate я сделал это, чтобы упростить проверку параметров:
public City GetCity(string zipCode)
{
zipCode.Assert("zipCode").IsNotNullOrEmpty().HasLength(5,10).Matches("\\d[5]-\\d[4]");
// Continue processing
}
Я не могу говорить с просачивающимися абстракциями.
Спасибо, ребята.
Отличное описание.
Моя мысль о беглых интерфейсах, где они были для читаемости. Я всегда мог прочитать цепочку методов и как один из них связан с предыдущим/следующим методом.
например. как плакат, который разместил пример проверки (я уже написал код, похожий на предыдущий).
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);
Вы можете найти хорошее определение и основные понятия свободного интерфейса этого сообщения:
Рекомендации по свободному дизайну интерфейса в части С# 1
Я надеюсь, что это поможет.