Si, hay inconvenientes
El código que es fácil de leer es bueno, pero también tenga cuidado con lo que el código comunica . Cuando los métodos de un objeto siempre devuelven el objeto, comunica un par de cosas:
- Necesito una configuración avanzada que no sea necesariamente obvia en qué orden se deben configurar o configurar las cosas
- Cada llamada de método posterior se basa en el último
Caso de uso válido: consultas de base de datos ad hoc
Las bibliotecas de clases existen en la mayoría de los idiomas que le permiten consultar una base de datos sin recurrir a SQL codificado. Tome el Entity Framework para .NET como ejemplo:
DBContext db = new DBContext();
List<Post> posts = db.Posts
.Where(post => post.Title.Contains("Test"))
.OrderBy(post => post.DateCreated)
.ToList();
Esta es una interfaz fluida donde cada llamada de método posterior se basa en la anterior. Leer estas llamadas lógicamente tiene sentido en el contexto de consultar una base de datos.
Caso de uso no válido: azúcar sintáctico para establecer propiedades
Ahora usemos el mismo patrón con la Post
clase:
public class Post
{
public string Title { get; set; }
public DateTime DateCreated { get; set; }
public string Body { get; set; }
public Post SetTitle(string title)
{
Title = title;
return this;
}
public Post SetDateCreated(DateTime created)
{
DateCreated = created;
return this;
}
public Post SetBody(string body)
{
Body = body;
return this;
}
}
Ahora veamos cómo usarías esta clase:
Post post = new Post()
.SetTitle("Test")
.SetDateCreated(DateTime.Now)
.SetBody("Just a test");
Cuando veo este código, inmediatamente hago esta pregunta: "Después de llamar SetBody
, ¿consulta la base de datos? ¿Necesito llamar a otro método para decir 'Ya terminé?'"
¿Qué comunican las llamadas al método encadenado al código usando la Post
clase?
- Tengo una configuración complicada
- Cada llamada al método se basa en la anterior
¿Es esto realmente cierto? No. La Post
clase no tiene una configuración complicada. Establecer el título, la fecha de creación y el cuerpo no complementan entre sí hacia un objetivo final más complicado. Has machacado una clavija cuadrada en un agujero redondo.
El inconveniente del encadenamiento de métodos autorreferencial es que usted comunica que se requieren múltiples llamadas a métodos para hacer algo, y que cada llamada se basa en la última. Si esto no es cierto, entonces el encadenamiento de métodos podría estar comunicando lo incorrecto a otros programadores.
Cuando tus compañeros de trabajo dijeron:
Las interfaces fluidas no deben implementarse solo por conveniencia, sino también por semántica
Eran absolutamente correctos. Una interfaz fluida, o encadenamiento de métodos, comunica algo en sí mismo que podría no ser cierto.