Eu adorava classes utilitárias preenchidas com métodos estáticos. Eles fizeram uma grande consolidação de métodos auxiliares que, de outra forma, ficariam por aí causando redundância e manutenção no inferno. São muito fáceis de usar, sem instanciação, sem descarte, apenas esquecem. Eu acho que essa foi minha primeira tentativa involuntária de criar uma arquitetura orientada a serviços - muitos serviços sem estado que apenas fizeram seu trabalho e nada mais. À medida que o sistema cresce, os dragões estão chegando.
Polimorfismo
Digamos que temos o método UtilityClass.SomeMethod que felizmente vibra. De repente, precisamos alterar ligeiramente a funcionalidade. A maior parte da funcionalidade é a mesma, mas precisamos alterar algumas partes. Se não fosse um método estático, poderíamos criar uma classe derivada e alterar o conteúdo do método conforme necessário. Como é um método estático, não podemos. Claro, se precisarmos adicionar funcionalidades antes ou depois do método antigo, podemos criar uma nova classe e chamar a antiga dentro dela - mas isso é nojento.
Problemas de interface
Os métodos estáticos não podem ser definidos por meio de interfaces por razões lógicas. E como não podemos substituir métodos estáticos, as classes estáticas são inúteis quando precisamos transmiti-las pela interface. Isso nos torna incapazes de usar classes estáticas como parte de um padrão de estratégia. Podemos corrigir alguns problemas passando delegados em vez de interfaces .
Testes
Isso basicamente anda de mãos dadas com os problemas de interface mencionados acima. Como nossa capacidade de trocar implementações é muito limitada, também teremos problemas para substituir o código de produção pelo código de teste. Novamente, podemos agrupá-los, mas isso exigirá que alteremos grandes partes do nosso código apenas para poder aceitar wrappers em vez dos objetos reais.
Promove blobs
Como os métodos estáticos são geralmente usados como métodos de utilidade e métodos de utilidade geralmente têm finalidades diferentes, acabaremos rapidamente com uma classe grande preenchida com funcionalidade não coerente - idealmente, cada classe deve ter uma única finalidade no sistema . Prefiro ter cinco vezes mais aulas, desde que seus objetivos sejam bem definidos.
Creep do parâmetro
Para começar, esse método estático bonitinho e inocente pode ter um único parâmetro. À medida que a funcionalidade cresce, alguns novos parâmetros são adicionados. Em breve, são adicionados parâmetros opcionais, portanto criamos sobrecargas do método (ou apenas adicionamos valores padrão, nos idiomas que os suportam). Em pouco tempo, temos um método que leva 10 parâmetros. Somente os três primeiros são realmente necessários, os parâmetros 4-7 são opcionais. Mas se o parâmetro 6 for especificado, é necessário preencher também de 7 a 9 ... Se tivéssemos criado uma classe com o único objetivo de fazer o que esse método estático fazia, poderíamos resolver isso incorporando os parâmetros necessários no construtor e permitindo que o usuário defina valores opcionais por meio de propriedades ou métodos para definir vários valores interdependentes ao mesmo tempo. Além disso, se um método cresceu para essa quantidade de complexidade,
Exigindo que os consumidores criem uma instância de classes sem motivo
Um dos argumentos mais comuns é: por que exigir que os consumidores de nossa classe criem uma instância para invocar esse método único, sem ter utilidade para a instância posteriormente? Criar uma instância de uma classe é uma operação muito barata na maioria dos idiomas; portanto, a velocidade não é um problema. Adicionar uma linha de código extra ao consumidor é um custo baixo para estabelecer as bases de uma solução muito mais sustentável no futuro. E, finalmente, se você deseja evitar a criação de instâncias, basta criar um wrapper singleton da sua classe que permita uma reutilização fácil - embora isso exija a exigência de que sua classe não tenha estado. Se não for apátrida, você ainda poderá criar métodos de empacotamento estático que lidam com tudo, enquanto ainda oferece todos os benefícios a longo prazo. Finalmente,
Apenas um Sith lida com absolutos.
É claro que há exceções ao meu desagrado por métodos estáticos. As verdadeiras classes de utilidade que não apresentam nenhum risco de inchaço são excelentes casos para métodos estáticos - System.Convert como exemplo. Se o seu projeto é único, sem requisitos para manutenção futura, a arquitetura geral realmente não é muito importante - estática ou não estática, não importa - a velocidade de desenvolvimento, no entanto.
Padrões, normas, normas!
O uso de métodos de instância não o impede de usar métodos estáticos e vice-versa. Desde que haja um raciocínio por trás da diferenciação e seja padronizado. Não há nada pior do que examinar uma camada de negócios que se estende a diferentes métodos de implementação.
this
, você precisa gerenciar o estado global etc. se você gosta de programação procedural, faça isso. Mas saiba que você perde muitos dos benefícios estruturais do OO.Eu prefiro o caminho estático. Como a Classe não está representando um objeto, não faz sentido fazer uma instância dele.
Classes que existem apenas para seus métodos devem ser deixadas estáticas.
fonte
Se não houver motivo para criar uma instância da classe para executar a função, use a implementação estática. Por que fazer com que os consumidores dessa classe criem uma instância quando não é necessária.
fonte
Se você não precisar salvar o estado do objeto, não será necessário instancia-lo em primeiro lugar. Eu usaria o método estático único para o qual você passa parâmetros.
Eu também alertaria contra uma classe gigante de Utils que possui dezenas de métodos estáticos não relacionados. Isso pode ficar desorganizado e pesado com pressa. É melhor ter muitas classes, cada uma com poucos métodos relacionados.
fonte
Eu diria que o formato do método estático seria a melhor opção. E também tornaria a classe estática, para que você não precise se preocupar em criar acidentalmente uma instância da classe.
fonte
Realmente não sei qual é a situação aqui, mas gostaria de colocá-la como método em uma das classes às quais arg1, arg2 ou arg3 pertencem - Se você puder dizer semanticamente que uma dessas classes seria dona do método método.
fonte
Eu sugeriria que é difícil responder com base nas informações fornecidas.
Minha intuição é que, se você tiver apenas um método e jogar a classe fora imediatamente, faça dela uma classe estática que aceita todos os parâmetros.
Obviamente, é difícil dizer exatamente por que você precisa criar uma única classe apenas para esse método. É a situação típica da "classe Utilitários", como a maioria está assumindo? Ou você está implementando algum tipo de classe de regra, da qual pode haver mais no futuro.
Por exemplo, faça com que essa classe seja plugável. Em seguida, você deseja criar uma interface para o seu método único e, em seguida, todos os parâmetros passados para a interface, e não para o construtor, mas não deseja que seja estático.
fonte
Sua turma pode se tornar estática?
Nesse caso, eu a tornaria uma classe 'Utilities' na qual colocaria todas as minhas classes de uma função.
fonte
Se esse método for sem estado e você não precisar contorná-lo, faz mais sentido defini-lo como estático. Se você precisar repassar o método, considere usar um delegado em vez de uma de suas outras abordagens propostas.
fonte
Para aplicativos e
internal
ajudantes simples , eu usaria um método estático. Para aplicativos com componentes, estou adorando o Managed Extensibility Framework . Aqui está um trecho de um documento que estou escrevendo para descrever os padrões que você encontrará nas minhas APIs.I[ServiceName]Service
interface.Como um exemplo artificial:
fonte
Eu faria apenas tudo no construtor. igual a:
ou
fonte
Uma questão mais importante a considerar é se o sistema estaria em execução em um ambiente multithread e se seria seguro para threads ter um método ou variáveis estáticas ...
Você deve prestar atenção ao estado do sistema.
fonte
Você pode evitar a situação todos juntos. Tente refatorar para que você obtenha
arg1.myMethod1(arg2, arg3)
. Troque arg1 por arg2 ou arg3 se fizer mais sentido.Se você não tem controle sobre a classe arg1, decore-a:
O raciocínio é que, em OOP, dados e métodos de processamento desses dados pertencem um ao outro. Além disso, você obtém todas as vantagens que Mark mencionou.
fonte
Eu acho que, se as propriedades da sua classe ou a instância da classe não serão usadas nos construtores ou nos seus métodos, não será sugerido que os métodos sejam projetados como padrão 'estático'. O método estático deve ser sempre pensado da maneira 'ajuda'.
fonte
Dependendo se você deseja fazer apenas algo ou fazer e retornar algo, você pode fazer isso:
fonte