Campos vs argumentos do método [fechado]

9

Comecei a escrever uma nova classe e me ocorreu que eu estava adicionando muitos argumentos de método que não são estritamente necessários. Isso segue o hábito de evitar ter estado em classes específico para alguma chamada de método, em vez de ser configuração geral ou dependências da classe.

Fazer isso significa que muitos métodos que não poderiam ter argumentos acabam com um, dois ou três.

Gostaria de ouvir suas opiniões sobre o que você acha dessa troca e como decide sobre qual abordagem adotar em que situação?

Como o código geralmente é mais fácil de entender do que o inglês ao descrevê-lo, criei uma pequena essência com as duas variantes: https://gist.github.com/JeroenDeDauw/6525656

Jeroen De Dauw
fonte
Argumentos que são usados ​​apenas como uma variável local (não global durante a vida útil do objeto) só devem estar no escopo, desde que faça sentido ... Acho isso muito irritante quando os desenvolvedores armazenam estado de não instância como estado de instância porque é conveniente ... Apenas minha opinião. Torna difícil ver como o fluxo de execução é realmente.
Max
Usando parâmetros e permitindo que a classe cuide se ela deve ou não mudar de estado durante a execução de um método, agradavelmente vincula-se ao princípio "diga não pergunte" . Basta ter em mente que contam não peça não significa que você não pode consultar um objeto sobre seu estado ( plugue flagrante )
Marjan Venema

Respostas:

2

Como o único método visível externamente do seu exemplo é updateTable, acho que é bom usar campos em vez de parâmetros de método.

Se isso faz parte de uma classe mais genérica (por exemplo TableTools), eu moveria os métodos auxiliares que precisam do estado para uma classe interna oculta.

Exemplo de pseudo-código:

class TableTools {
    ...
    public void updateTable(currentTable, newTable) {
        TableUpdater u = new TableUpdater(schemaModifier, currentTable, newTable);
        u.removeRemovedFields();
        u.addAddedFields();
     }

     private class TableUpdater { ... }
}

Dessa forma, você evita campos que são usados ​​por apenas um método público. Além disso, o código é seguro para threads no sentido de que toda chamada para updateTable usa sua própria cópia do TableUpdater e, portanto, das variáveis ​​de instância do TableUpdater.

Heinzi
fonte
7

O uso de campos coopta a capacidade de ter multithreading disponível para os métodos que usam esses campos.

Usar campos como esse é apenas um pouco melhor do que usar globais do ponto de vista de reutilização e manutenção, o ponto principal aqui é que configurações complexas precisam de documentação cuidadosa e atualizada sobre quais métodos usam e / ou eliminam quais campos; algo que você não precisa fazer ao usar argumentos.

catraca arrepiante
fonte
Multhithreading não é relevante para o meu caso de uso, como é no PHP. Concordo que essa abordagem é ruim se a maneira como os campos são usados ​​não for trivial. Nesse caso, eles são gravados apenas (e sempre gravados) no único método público. Não prevejo que isso esteja causando problemas. Quanto a campos como este serem apenas um pouco melhores que os globais, não sei bem o que você quer dizer. Você pode elaborar?
Jeroen De Dauw 13/09/13
7

Nas palavras dos leigos:

  • métodos devem ter o mínimo de argumentos possível (Código Limpo de Martin)
  • Uma das características dos objetos é que eles podem (e devem) ter um estado
  • métodos não estáticos que não operam no estado do objeto, ou seja, recebem tudo como parâmetros, não são coesos
  • métodos não coesos também podem ser tornados estáticos e agrupados em uma classe de utilidade

Novamente, na minha humilde opinião, os métodos não coesos pertencem a uma classe de utilidade e não a uma classe com um nome de domínio.

Tulains Córdova
fonte
1

Não use campos no caso atual! Dois "threads" usando o objeto ao mesmo tempo confundirão seriamente. Eles não precisam ser reais, separar tópicos também (daí as aspas). Se você configurar o objeto para uma tabela, chame um método que o use para outra tabela e tente usar a configuração original, você terá um problema. Atenha-se aos parâmetros no momento.

O que você deseja fazer aqui é criar uma nova classe de atualizador usada em apenas um caso. A classe original pode ter um método para criar uma instância sempre que necessário. A nova classe teria campos. Você tem o melhor dos dois mundos. Às vezes, é mais simples seguir os parâmetros, mas no seu exemplo você já está chegando onde uma classe separada seria melhor.

RalphChapin
fonte
0

Eu acho que a escolha deve estar de acordo com a situação real, como você vê. Se um item pertence a uma instância, ele deve ser visto como seu campo. Se o item for externo à instância, ele deve ser passado como um parâmetro de método.

Nesse caso, devemos ser guiados não pela efetividade (de qualquer maneira, a diferença é insignificante) ou (Deus salve!) Facilidade de digitação, mas pela compreensibilidade e naturalidade do código.

Gangnus
fonte
0

Na minha opinião, se você estiver escrevendo código que faz algo em algo , deve-se usar parâmetros que definam para quais coisas eles devem ser feitos e seu nome deve definir, tanto quanto possível, o que ele faz com ele.

Se você está escrevendo um código que empacota uma ação a ser executada em algo , você deve agrupar as coisas em que ele deve ser executado em um objeto e passá-las para o que faz alguma coisa .

Essa ação se torna um tipo de meta-descrição das chamadas para os métodos da primeira, que você pode executar posteriormente, enfileirando-a ou até mesmo decidir não fazê-lo por algum motivo.

Então, a sua pergunta traduz em que é uma ação ou de uma função ? Uma Ação pode ser adiada ou cancelada e, portanto, deve resumir aquilo em que atua. Uma Função acontece imediatamente, portanto não é necessário preservar seus parâmetros.

Você pode desfazer e Ação, mas não uma Função .

OldCurmudgeon
fonte