Reconozco que utilizar una librería con Fluent Api puede ser cómodo o según como se haga bastante incómodo, como quería dar una nueva cara a una librería que tengo pensé en hacerla con estilo Fluent Api , podía ser interesante de cara a la librería y también a su facilidad de uso.
De la creación de esa librería y de algunas otras llegué a estas conclusiones que indico aquí (sobre todo para que no se me olviden la próxima vez).
Definición
La definición de Fluent Api está clara en la Wikipedia, esto no quita que haya que tener en cuenta algunos elementos o características propias del lenguaje que se vayan a usar, también indicar que se hace una distinción entre Fluent Api y method chaining, en este caso voy a usar las dos juntas indistintamente pero es importante tener esa distinción en cuenta.
También hay que tener en cuenta que el objeto con el que se está trabajando en Fluent Api es interno a la librería y puede estar compuesto a su vez de otros objetos, la idea de Fluent Api es construir ese objeto interno de una forma correcta para su uso.
Nomeclatura
Es importante tener claro como se van a prefijar los elementos y ceñirse a esta nomenclatura, muchas librerías usan los suyos propios indico aquí un estilo de ejemplo que es el que usaré:
- AddXXX: Cuando queremos añadir un nuevo elemento al objeto interno, por ejemplo el objeto interno tiene una lista y queremos añadir un nuevo elemento a esa lista:
- WithXXX: Para añadir una propiedad o establecer un valor al objeto con el que estamos trabajando, puede ser el interno o un objeto dependiente de este.
- IsXXX / HasXXX: Los dos están orientado a valores booleanos, es verdad que podríamos usar también WithXXX pero muchas veces a los valores booleanos se les da un tratamiento especial para remarcarlos. Si buscásemos una diferencia entre IsXXX y HasXXX podríamos hacer lo siguiente:
- IsXXX: Para establecer un valor booleano en una propiedad, por ejemplo IsDeveloper, IsCEO.
- HasXXX: Cuando necesitamos hacer una verificación para obtener esa información o la sacamos de una colección, por ejemplo HasChilds, HasDriverLicense.
- UseXXX: UseXXX se usa generalmente cuando queremos definir un comportamiento, por ejemplo internamente tenemos varias formas de crear el objeto o de guardarlo y queremos usar una en concreto, también es muy útil para establecer configuraciones.
- AndXXX: Cuando vamos a concatenar dos propiedades que se configuran por separado pero deben de ir juntas ya que dependen entre sí.
Estilo
En este sentido también hay algunas sugerencias, por ejemplo si la línea de código es bastante larga puede ser interesante separarla en varias líneas, por ejemplo:
var configuration = Builder.Create()
.AddElement()
.WithProperty()
.AndAnotherOne().Save()
El último método que finaliza se puede colocar también en otra línea aparte o en la misma, lo que interesa remarcar principalmente es cada opción de creación en una línea separada, en este punto puede haber algún problema con los editores de código de cara al formateo y la tabulación pero con un poco de práctica a la hora de generar las líneas o cambiando las opciones de formateo de código es suficiente.
Con los parámetros sucede algo parecido, es posible que los métodos tengan muchos parámetros en ese caso un nivel de indentación adicional ayuda bastante, como se ha comentado dependiendo del editor de código no siempre el formateo de código resulta cómodo así que puede haber variaciones:
var configuration = Builder.Create()
.AddElement(
text: "Hello")
.WithProperty(
description: "big",
color: "green")
.AndAnotherOne().Save()
Por norma general se intenta usar métodos en todos los casos aunque es verdad que a veces pueda resultar más legible usar una propiedad, realmente es raro tener métodos que no usen parámetros así que por homogeneidad es mejor usar siempre métodos.
No debería pero estas configuraciones pueden llegar a ser largas por lo que incluirlas dentro de un método de configuración en una clase de inicio de la aplicación suele ser la opción más cómoda que es básicamente el comportamiento de los métodos de creación de .Net Core.
Estructura de Fluent Api
Primero recordar lo que dice la propia definición de la Wikipedia sobre la creación de las interfaces:
- El método de una interfaz siempre devuelve como parámetro la propia interfaz.
- Siempre hay un método sin contexto final que termina el proceso de creación (Save(), Build(),…)
- Se trabaja siempre sobre el mismo contexto (u objeto interno) que se construirá.
Voy a usar este ejemplo demostrativo, no pretende ser un ejemplo real simplemente está hecho para poder explicar varios conceptos en los siguientes capítulos.

Hay dos interfaces, una se encarga de la gestión de usuarios y la otra de la gestión de la conexión, ambas están conectadas a través de una interfaz que representa la configuración de una base de datos.
