writeline ver variable programa imprimir example ejemplos datos consola c# design-patterns fluent-interface

ver - summary example c#



Consejos para escribir interfaces fluidas en C#3 (8)

Estoy buscando algunos buenos consejos para interfaces fluidas en C #. Solo estoy aprendiendo sobre esto pero estoy ansioso por escuchar lo que otros piensan fuera de los artículos que estoy leyendo. En particular, estoy después:

  1. cuando es demasiado fluido?
  2. ¿Hay algún patrón fluido?
  3. qué hay en C # que hace que las interfaces fluidas sean más fluidas (p. ej., métodos de extensión)
  4. ¿Es una interfaz fluida y compleja aún fluida?
  5. refactorización para llegar a una interfaz fluida o refactorización de una interfaz fluida existente
  6. ¿Hay buenos ejemplos con los que hayas trabajado o que puedas recomendar?

Si pudieras publicar un consejo o pensamiento, o lo que sea por publicación. También quiero ver cómo se votan.

Gracias de antemano.


El mayor desafío que he experimentado como consumidor de interfaces fluidas es que la mayoría de ellas no son realmente fluidas, sino que son ejemplos de lo que suelo denominar como "interfaces legibles".

Una interfaz fluida implica que su objetivo principal es facilitar su HABLAR, mientras que una interfaz legible implica que su objetivo principal es ser fácil de LEER. La mayoría de las interfaces fluidas solo tienden a ser ridículamente difíciles de codificar, pero a la inversa, es increíblemente fácil de leer más tarde por otros.

Assert().That().This(actual).Is().Equal().To(expected). Except().If(x => x.GreaterThan(10));

... ¡es mucho más fácil de leer más tarde de lo que realmente es componer en código!


En tu 4º punto;

Sí, creo que una interfaz fluida y compleja puede ser fluida.

Creo que las interfaces fluidas son algo así como un compromiso. (¡Aunque es una buena idea!) Se ha investigado mucho sobre el uso del lenguaje natural para la programación y, en general, el lenguaje natural no es lo suficientemente preciso como para expresar programas.

Las interfaces fluidas se construyen para que escriban como un lenguaje de programación, solo se permite un pequeño subconjunto de lo que se puede expresar en un lenguaje natural, pero se leen como un lenguaje natural.

Si nos fijamos en el rinoceronte se burla, por ejemplo, la parte de escritura ha sido complicada en comparación con una biblioteca normal. Me tomó más tiempo aprender principalmente debido a la interfaz fluida, pero hace que el código sea mucho más fácil de leer. Debido a que los programas generalmente se escriben una vez y se lee mucho más de una vez, esta es una buena compensación.

Entonces para calificar mi punto un poco. Una interfaz fluida que sea compleja de escribir pero fácil de leer aún puede ser fluida.


Hace un tiempo tuve las mismas dudas que tienes ahora. Investigué un poco y ahora escribo algunas publicaciones para ayudar en esos temas.

Compruébalo en mi blog:

Directrices para el diseño de interfaz fluida en C # parte 1

Y en los siguientes mensajes voy a cubrir cada uno de los puntos que mencionas.

Saludos cordiales André Vianna


Moq oculta los métodos no relejados como equals, ToString , etc. para hacer que su interfaz fluida sea aún más fácil de usar.

Ocultar el objeto del sistema es un artículo que explica el beneficio de hacer esto.


Tocarás un ladrillo cuando uses herencia junto con interfaces fluidas porque el uso de métodos polimórficos rompe tus cadenas de llamadas y definitivamente no deseas que tus interfaces no sean fluidas mediante el uso de feo casting y paranthesis donde no sean necesarios. Escribí un artículo sobre un patrón que le proporciona una solución mediante el uso de constructores genéricos y métodos de extensión genéricos con restricciones genéricas: http://liviutrifoi.wordpress.com/2009/02/16/fluent-interfaces-constraints-at-compile-time/


Una cosa es que tenga que dar cuenta de la morfología de la sintaxis en inglés y asegurarse de que no haya introducido el acoplamiento secuencial no documentado debajo.

// Snarky employees get a raise. employees.WhereSnarky().GiveRaise();

vs.

// Depending on implementation, everyone may get a raise. employees.GiveRaise().WhereSnarky();


Y en su segunda y tercera pregunta;

Tres patrones fluidos que he notado

El primero usa la instrucción using (C # 2.0) para ejecutar código en un contexto determinado, por ejemplo:

using(var transaction = new Transaction()) { // .. // .. }

Esto usa el constructor y el eliminador de transacciones para configurar una transacción y luego ejecuta el código en este contexto.

El segundo hace casi lo mismo pero con lambda, esto se usa mucho en Rhino Mocks, por ejemplo.

(new Transaction()).Run( () => mycode(); );

La interfaz fluida más conocida es usar tipos de devolución para llamadas de método de cadena. La mayoría de los métodos devuelven esto para que pueda encadenar llamadas en el mismo objeto. Pero también puede devolver diferentes objetos para cambiar el contexto según el método llamado. Si tiene un objeto que solo puede ejecutarse en una transacción (lo siento, no puedo pensar en otro ejemplo), puede darle un método StartTransaction que devuelve una transacción inicializada donde puede ejecutar la ejecución de la llamada y detener la transacción, en un seudocódigo:

class Runner { Transaction StartTransaction() { return new Transaction(this); } } class Transaction { Transaction Run() Transaction StopTransaction() }

donde se ve la llamada

var runner = new Runner(); runner .StartTransaction() .Run() .StopTransaction();

Por supuesto, debe agregar todo tipo de manejo de errores, etc.


Yo también estoy aprendiendo a escribir una interfaz fluida para una pequeña aplicación en el trabajo. He preguntado un poco e investigado un poco y descubrí que un buen enfoque para escribir una interfaz fluida es usar el "Patrón de generador", leer más sobre esto here .

En esencia, así es como comencé el mío:

public class Coffee { private bool _cream; private int _ounces; public Coffee Make { get new Coffee(); } public Coffee WithCream() { _cream = true; return this; } public Coffee WithOuncesToServe(int ounces) { _ounces = ounces; return this; } }

Aquí hay una publicación cruzada de una pregunta similar que tengo para implementar un cierre en una interfaz fluida.