FluentInterfaces en C#
El término de FluentInterface es un término acuñado por Martin Fowler y Eric Evans en Diciembre de 2005.
Martin Fowler indica en su sitio web que la mejor forma de ver esto es con un ejemplo, y es que todo lo que tiene que ver con código, se ve y se entiende mejor cuando se mete uno en harina.
Las interfaces fluidas o FluentInterfaces, aumentan un poco la compledidad de código, pero son muy recomendables a la hora de configurar nuestros objetos.
Algunos programadores denominan a las FluentInterfaces como Method Chaining o métodos encadenados.
Pero como dice el mismo Martir Fowler, las FluenteInterfaces son más que eso.
Pero pongámonos manos a la obra.
Imaginemos para hacerlo fácil, que tenemos la siguiente clase:
public class Animal { public int Age { get; set; } public bool IsAlive { get; set; } public int Legs { get; set; } public string Name { get; set; } }
Parece claro que para crear un objeto de tipo Animal, tendremos que hacer una declaración parecida a la siguiente:
var animal = new Animal(); animal.Age(3); animal.Legs(4); animal.Name("Toby");
Desde un punto de vista formal, la instanciación de un objeto Animal y la asignación de sus valores, no es que sea muy fluida.
No es incorrecto, pero no es natural.
Según el contexto en el que nos encontremos, utilizar una forma más natural de declarar nuestro objeto, puede ser una ventaja.
Y es aquí donde entra el concepto de FluentInterface.
Para hacer esto mismo, pero de una forma fluida, deberemos crear una clase Animal, y dentro de ésta, nuestra clase fluida.
public class Animal { private readonly AnimalFluentInterface _with; public AnimalFluentInterface With => _with; public Animal() { _with = new AnimalFluentInterface(this); } public int Age { get; private set; } public bool IsAlive { get; private set; } public int Legs { get; private set; } public string Name { get; private set; } public class AnimalFluentInterface { private readonly Animal _animal; public AnimalFluentInterface(Animal animal) { _animal = animal; } public AnimalFluentInterface SetAge(int age) { _animal.Age = age; return this; } public AnimalFluentInterface IsAlive(bool isAlive = true) { _animal.IsAlive = isAlive; return this; } public AnimalFluentInterface SetLegs(int legs) { _animal.Legs = legs; return this; } public AnimalFluentInterface SetName(string name) { _animal.Name = name; return this; } public Animal Get() { return _animal; } } }
Si observamos nuestra clase, veremos que nuestra clase tiene un constructor que instancia la clase AnimalFluentInterface, que está declarada dentro de nuestra clase Animal.
Dentro de la clase AnimalFluentInterface, asignamos los valores de las propiedades de nuestra clase Animal.
Y finalmente, con el método Get, podemos obtener los valores de nuestras propiedades.
De hecho, la llamada a nuestra clase será ahora de esta manera:
var dog = new Animal().With.SetAge(3).SetLegs(4).SetName("Toby").IsAlive(); var cat = new Animal().With.SetAge(7).SetLegs(4).SetName("Kitty").IsAlive(false); Console.WriteLine($"{dog.Get().Age} => {dog.Get().IsAlive} => {dog.Get().Legs} => {dog.Get().Name}"); Console.WriteLine($"{cat.Get().Age} => {cat.Get().IsAlive} => {cat.Get().Legs} => {cat.Get().Name}");
Como podemos apreciar, las interfaces fluidas o FluentInterfaces, nos permite declarar un objeto de una forma más natural y directa.
Como siempre, dependiendo de nuestras necesidades, podrá resultar útil su uso, o no.
¡Happy Coding!