Existem desvantagens reais do encadeamento de métodos auto-referenciais?

14

Recentemente, sugeri que um método de encadeamento fosse implementado para uma determinada classe em um determinado projeto, para que a legibilidade do código pudesse ser melhorada. Eu recebi uma resposta "interfaces fluentes não devem ser implementadas apenas por conveniência, mas por semântica" e tive minha sugestão abatida. Respondi que não estava sugerindo uma interface fluente, mas sim o método de encadeamento (ambos podem ser confundidos entre si, lidos na parte inferior) para melhorar a legibilidade e o conforto da codificação. A sugestão foi abatida novamente.

De qualquer forma, isso me fez pensar que talvez eu pudesse estar incorrendo em uma prática ruim, sempre retornando "this" em métodos que não deveriam retornar nada (por exemplo, setters).

Minha pergunta é: a aplicação da convenção anterior pode ser considerada má prática ou abuso ?, por quê? Eu não acho que haja desvantagens de desempenho ou existem?

dukeofgaming
fonte
2
Veja esta pergunta para uma bela discussão programmers.stackexchange.com/questions/48419/…
KeesDijk
@KeesDijk Obrigado, eu editei a minha pergunta um pouco por isso não é para semelhante a esse, como eu estou mais interessado em caso de encadeamento métodos da mesma classe
dukeofgaming
1
na SO, eles me disseram que esse encadeamento não é para C ++ - stackoverflow.com/questions/5760551/… - o que você pensa?
Kagali-san 30/05
1
@mhambra Parece que você só precisa ter cuidado ao implementar o encadeamento de métodos e definir padrões claros para isso.
Dukeofgaming 30/05

Respostas:

10

Não

Como Kent Beck aponta, o código é lido com muito mais frequência do que está escrito.

Se o encadeamento de métodos tornar seu código mais legível, use o encadeamento de métodos.

Steven A. Lowe
fonte
1
Grande livro .. +1
Rein Henrichs 30/05
5
MAS , e se você for o único método de encontrar encadeamento mais legível? Se isso é um problema de ordem sistêmica, você terá que seguir um conjunto de convenções de codificação: isso significa escrever da mesma maneira que o código existente, para obter consistência.
Coredump #
@coredump Parece que o OP já foi dito para fazer isso, mas eu acho que Steven estava apenas dizendo isso para se método de encadeamento torna-lo mais legível.
Panzercrisis
1
Os OP do @ Panzercrisis foram instruídos a abster-se de usar o encadeamento de métodos devido à conveniência versus semântica. A resposta de Steven basicamente diz "faça de qualquer maneira" e considere apenas a legibilidade do código do OP por si só, sem considerar a opinião ou a consistência da equipe. E se o OP quiser reescrever todas as classes existentes no projeto para que ele se adapte ao seu gosto em relação à legibilidade do código? É assim que eu entendo o argumento de conveniência / semântica: deve haver uma razão "técnica" para o encadeamento de métodos (btw, esse argumento também soa como se a outra pessoa estivesse inventando uma desculpa para suas próprias preferências)
coredump
9

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:

  1. Exijo uma configuração avançada que não seja necessariamente óbvia em que ordem as coisas devem ser definidas ou configuradas
  2. 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 Postclasse:

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 Postclasse?

  1. Eu tenho uma configuração complicada
  2. Cada chamada de método se baseia na anterior

Isso é realmente verdade? Não. A Postturma 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.

Greg Burghardt
fonte
Isso pressupõe que o encadeamento de métodos e a configuração complexa sempre andam de mãos dadas. São entidades distintas e a presença de uma não deve fazer você assumir a outra.
Jack
Não é apenas "configuração complexa", é também "chamadas de método subsequentes construídas com base na anterior". O encadeamento de métodos possui uma meta comunicação sobre isso, que nem sempre é verdadeira para o objetivo de uma classe.
Greg Burghardt
1
As chamadas de método subsequentes, construídas com base nas anteriores, também são distintas do encadeamento de métodos, e não acho que tratar a sintaxe do encadeamento de métodos como uma comunicação forte para a semântica de séries dependentes de ordem de operações de efeito colateral seja confiável ou útil. É uma abreviação sintática, nada mais. Use-o onde tornar as coisas mais curtas e mais legíveis.
Jack
1
Eu entendo que você acha método de encadeamento é separado, mas eu estou dizendo que outros programadores que não estavam dentro de sua cabeça e usar outras bibliotecas de classes que não implementam método de encadeamento por estas razões pode acabar fazendo suposições sobre o seu código que não são verdadeiras. Esteja ciente de que o encadeamento de métodos pode implicar algo que você, o autor do código, não pretendia. O código que se comunica claramente é tão importante quanto o código fácil de ler. Não sacrifique um pelo outro.
precisa
1
When an object's methods always return the object, it communicates a couple of things- Eu acho que essa é uma opinião pessoal; é difícil afirmar que todo mundo que olha métodos encadeados assume as mesmas coisas.
Sam Dufel
1

A principal desvantagem é a perda de clareza. Por exemplo:

x.foo();
x.bar();
x.baz();

Como nenhuma dessas instruções retorna um valor (ou, se o fizerem, foi ignorado), elas só podem ser úteis se produzirem efeitos colaterais. Compare isso com:

x.foo()
 .bar()
 .baz();

Primeiro, não está claro isso bare bazopera em objetos do mesmo tipo que x, a menos que você saiba que xa classe de s é a única classe com esses métodos. Mesmo se for esse o caso, não está claro se os métodos operam xou se há novos objetos.

Destacar as partes do código que apresentam efeitos colaterais é útil, pois é necessário rastrear esses efeitos colaterais para refletir sobre o programa. Você deve avaliar a perda potencial de clareza em relação ao ganho potencial na facilidade de escrever código, mas também considere que o código é lido mais do que está escrito.

Doval
fonte
0

Considere todos os elementos estilísticos das linguagens de programação (em oposição à linguagem de máquina de codificação manual) e enfraquece o argumento "semântica, não conveniência".

Muito do que fazemos como engenheiros está fornecendo conveniência em relação à semântica.

Roubar
fonte