Sim, existem desvantagens
O código que é fácil de ler é bom, mas também tenha cuidado com o que o código também comunica . Quando os métodos de um objeto sempre o retornam, ele comunica algumas coisas:
- Exijo uma configuração avançada que não seja necessariamente óbvia em que ordem as coisas devem ser definidas ou configuradas
- Cada chamada de método subsequente se baseia no último
Caso de uso válido: consultas ad hoc ao banco de dados
As bibliotecas de classes existem na maioria das linguagens que permitem consultar um banco de dados sem recorrer ao SQL codificado. Tome o Entity Framework para .NET como exemplo:
DBContext db = new DBContext();
List<Post> posts = db.Posts
.Where(post => post.Title.Contains("Test"))
.OrderBy(post => post.DateCreated)
.ToList();
Essa é uma interface fluente, na qual cada chamada de método subsequente se baseia na anterior. Ler essas chamadas logicamente faz sentido no contexto de consultar um banco de dados.
Caso de uso inválido: açúcar sintático para definir propriedades
Agora vamos usar o mesmo padrão com a Post
classe:
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;
}
}
Agora vamos ver como você usaria esta classe:
Post post = new Post()
.SetTitle("Test")
.SetDateCreated(DateTime.Now)
.SetBody("Just a test");
Quando vejo esse código, faço imediatamente a seguinte pergunta: "Depois de chamar SetBody
, ele consulta o banco de dados? Preciso chamar outro método para dizer 'pronto'?"
O que as chamadas do método encadeado se comunicam com o código usando a Post
classe?
- Eu tenho uma configuração complicada
- Cada chamada de método se baseia na anterior
Isso é realmente verdade? Não. A Post
turma não possui uma configuração complicada. Definir o título, a data de criação e o corpo não se baseia em um objetivo final mais complicado. Você esmagou um pino quadrado em um buraco redondo.
A desvantagem do encadeamento de método auto-referencial é que você comunica que várias chamadas de método são necessárias para fazer algo e que cada chamada se baseia na última. Se isso não for verdade, o encadeamento de métodos pode estar comunicando a coisa errada a outros programadores.
Quando seus colegas de trabalho disseram:
Interfaces fluentes não devem ser implementadas apenas por conveniência, mas por semântica
Eles estavam absolutamente corretos. Uma interface fluente, ou encadeamento de métodos, comunica algo por si só que pode não ser verdade.