programacion poo polimorfismo metodos mecanismos ejemplo datos abstractos abstraccion oop fluent-interface leaky-abstraction

oop - poo - metodos abstractos php



Interfaces fluidas y abstracciones con fugas (9)

Aquí hay una interfaz regular de todos los días:

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

Y aquí hay una interfaz fluida:

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

La diferencia más obvia es que cuando devolvemos un vacío, volvemos en su lugar una instancia del tipo de interfaz. Lo que se entiende es que la interfaz devuelta es la INSTANCIA ACTUAL, no una nueva instancia del mismo tipo. Por supuesto, esto no es aplicable, y en el caso de objetos inmutables (como cadena) es una instancia diferente, pero se puede considerar que es la misma instancia solo actualizada.

Aquí hay ejemplos de su uso:

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

Tenga en cuenta que la interfaz fluida es más fácil de usar al encadenar llamadas diferentes. IRL, revisa los métodos de extensión de Linq y cómo cada llamada está diseñada para fluir a otra. Ninguno de los métodos vuelve vacío, incluso si sería un resultado válido.

¿Qué es una interfaz fluida? No puedo encontrar una buena definición de esto, pero todo lo que obtengo son largos ejemplos de código en un lenguaje con el que no estoy muy familiarizado (por ejemplo, C ++).

Además, ¿qué es una abstracción con fugas?

Gracias


En una interfaz fluida, los métodos de un objeto devolverán una referencia al objeto, para que pueda encadenar las llamadas al método.

Por ejemplo, en NValidate, hice esto para simplificar la validación de parámetros:

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

Aunque no puedo hablar de abstracciones con goteras.


Gracias chicos.

Gran descripción.

Mi pensamiento sobre las interfaces fluidas era que eran para facilitar la lectura. Siempre pude leer una cadena de métodos y cómo uno está relacionado con el método anterior / siguiente.

Por ejemplo, como el póster que publicó el ejemplo de validación (he escrito un código similar al anterior).


Una abstracción con fugas es una abstracción donde los detalles de la realidad subyacente a menudo "se filtran".

Todas las abstracciones se encuentran más o menos, pero a veces las abstracciones se ajustan tan mal a la realidad subyacente, que causa más daño de lo que ayuda.

Un ejemplo simple de "fuga" en una abstracción podría ser el tipo de flotación habitual. Parece representar números reales generales y puede usarlo para realizar cálculos básicos. Pero en algún momento se encuentra con un escenario en el que 1/3 * 3! = 1 o 1 + 10 ^ -20 = 1. Ahí es cuando se filtran los detalles de la implementación real y se rompe la abstracción.


Una interfaz fluida es una API que le permite escribir códigos que se parecen más o menos al inglés normal. Por ejemplo:

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

El método de encadenamiento generalmente se usa como parte de la implementación, pero hay más que eso. Para citar a Fowler :

También he notado un error común: muchas personas parecen equiparar las interfaces fluidas con Method Chaining. Ciertamente, el encadenamiento es una técnica común para usar con interfaces fluidas, pero la verdadera fluidez es mucho más que eso.

También se le suele llamar DSL interna, ya que la sintaxis se asemeja a la de una DSL, pero se implementa dentro del lenguaje de host en lugar de ser procesada por un analizador.


Una interfaz fluida, un término acuñado por Eric Evans y es simplemente otro nombre para el método de encadenamiento. Martin Fowler escribió un par de artículos sobre este tema, pero se parece más o menos a esto:

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

La interfaz fluida generalmente se usa para crear parámetros nombrados en un idioma que no los admite (la expresión idiomática de parámetros nombrados en C ++, por ejemplo) o en lenguajes específicos de dominio para hacer que el código se lea con mayor fluidez.

Los he visto usar para todo, desde bibliotecas de procesamiento de imágenes hasta bibliotecas de expresiones regulares, bibliotecas 3D. Otros ejemplos incluyen la construcción de estructuras de árbol, listas u otras estructuras de datos. Todo lo que requiere la construcción de objetos complejos (carga de parámetros) puede utilizar interfaces fluidas para hacerlo más legible. Por ejemplo, compare el ejemplo anterior con la llamada a la función CreateWindow:

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


Una interfaz orientada a objetos es fluida si los métodos que se ejecutan para el efecto secundario regresan a self , de modo que dichos métodos se pueden encadenar entre sí.

La primera vez que encontré interfaces fluidas fue en 1990, cuando la Interfaz Modula-3 Police (no lo estoy inventando) requirió que todos los métodos de inicialización devolvieran el objeto inicializado. Creo que este uso es anterior a la acuñación del término "interfaz fluida".


Neal Ford hace un buen trabajo explicando y dando ejemplos de Fluent Interface en su libro el ''Productive Programmer''.

Objeto tradicional o ''bean'' con getters / setters:

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);

Satisfaga la misma necesidad con una interfaz fluida:

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