2008-10-22 10 views
43

Estoy buscando algunos buenos consejos para las 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 de:Consejos para escribir interfaces fluidas en C# 3

  1. ¿Cuándo 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 (por ejemplo, los 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 algún buen ejemplo con el que haya trabajado o podría recomendar?

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

Gracias de antemano.

+0

He aquí un consejo: detectabilidad y la sencillez son mucho más importantes que el pequeño legibilidad añadido una API fluida da en la mayoría de los casos. Fluidez en la forma en que lo hace LinQ (los métodos synatax) es excelente, construir una DSL fluida con C# solo crea una API que es imposible de entender. –

Respuesta

18

En su cuarto punto;

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

Creo que las interfaces fluidas son algo comprometedoras. (¡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 observa los simulacros de rinocerontes, 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.

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

+0

Rhino mocks es un buen ejemplo. Además, como su punto de vista sobre lo que es bueno. Creo que las interfaces fluidas, ya sean públicas o no, se trata de proporcionar interfaces fáciles de usar para los usuarios, otros codificadores, etc. Entonces el dolor de complejidad no es del todo malo. –

7

Y en su segunda y tercera pregunta;

patrones

Tres fluidas me he dado cuenta

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

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

Este utiliza el constructor y el eliminador de Transacción 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 mejor interfaz fluida conocida es usar tipos de devolución para llamar al 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 call run y stoptransaction, en pseudocódigo:

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

class Transaction 
{ 
    Transaction Run() 
    Transaction StopTransaction() 
} 

donde la llamada se parece

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

Por supuesto es necesario agregar todo tipo de control de errores, etc.

27

el desafío más grande que he experimentado como consumidor de interfaces fluidas es que la mayoría de ellos no son realmente fl ue intefaces - en cambio, son realmente instancias de lo que suelo referirme 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!

+0

+1 para el consejo real :-) –

+13

¿Es realmente más fácil de leer que simplemente 'real == esperado || actual> 10'? –

+0

noooooooooooooo –

11

Tocará un ladrillo cuando usa herencia junto con interfaces fluidas porque el uso de métodos polimórficos rompe sus cadenas de llamadas y definitivamente no desea hacer que sus interfaces no fluyan usando feísmo y paranthesis cuando no son necesarios . He escrito un artículo acerca de un patrón que le proporciona una solución utilizando constructores genéricos y métodos de extensión genéricos con las limitaciones genéricas: http://liviutrifoi.wordpress.com/2009/02/16/fluent-interfaces-constraints-at-compile-time/

+1

Buen artículo. Lo probaré. –

+1

Parece que el enlace del artículo ha cambiado. Parece estar ahora en: http://liviutrifoi.wordpress.com/2009/02/16/fluent-interfaces-constraints-at-compile-time – dharmatech

8

Moq esconde métodos unreleated como iguales, ToString y así sucesivamente para hacer su interfaz fluida incluso más fácil de usar.

Hiding System Object es un artículo que explica el beneficio de hacer esto.

+1

+1 para el artículo. –

+0

El enlace está muerto :( –

+0

Aquí está la actualización [link] (http://blogs.clariusconsulting.net/kzu/how-to-hide-system-object-members-from-your-interfaces/) –

7

Yo también estoy aprendiendo a escribir una interfaz fluida para una pequeña aplicación en el trabajo. He preguntado e investigado un poco y encontré que un buen enfoque para escribir una interfaz fluida es usar el "Patrón de generador", leer más al respecto aquí: link text

En esencia, así es como comencé la mía:

public class Coffee 
{ 
    private bool _cream; 

    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 profundidad a una pregunta similar que tengo para la implementación de un cierre en una interfaz fluida. link text

+0

buen ejemplo simple – Boinst

2

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

comprobarlo en mi blog:

Guidelines to Fluent Interface design in C# part 1

Y en los siguientes mensajes que cubrirá cada uno de los puntos que usted ha mencionado.

Saludos André Vianna

+0

El enlace está muerto; es un buen ejemplo de por qué no se recomiendan las respuestas de solo enlace. ¿Asumo que es usted ?: http://www.codeproject.com/Articles/99542/Guidelines-to-Fluent-Interface-design-in -C-Parte –

3

Una cosa es que tienes que tener en cuenta la morfología de la sintaxis Inglés y asegurarse de que no haya introducido acoplamiento secuencial indocumentado debajo.

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

vs

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