Depende se as classes estáticas mantêm estado ou não. Pessoalmente, não tenho nenhum problema com as funções stateless agrupadas em uma classe estática.
Enviei um aplicativo que escrevi para alguns outros arquitetos para revisão de código. Um deles quase imediatamente me escreveu de volta e disse "Não use" static ". Você não pode escrever testes automatizados com classes e métodos estáticos." Static "deve ser evitado."
Eu verifiquei e 1/4 das minhas turmas estão marcadas como "estáticas". Eu uso static quando não vou criar uma instância de uma classe porque a classe é uma classe global única usada em todo o código.
Ele passou a mencionar algo envolvendo técnicas de simulação, IOC / DI que não podem ser usadas com código estático. Ele diz que é lamentável quando bibliotecas de terceiros são estáticas por causa de sua impossibilidade de teste.
Este outro arquiteto está correto?
update: aqui está um exemplo:
APIManager - essa classe mantém os dicionários de APIs de terceiros que estou chamando junto com o próximo tempo permitido. Ele impõe limites de uso da API que muitos terceiros possuem em seus termos de serviço. Eu uso em qualquer lugar que eu estou chamando um serviço de terceiros chamando Thread.Sleep (APIManager.GetWait ("ProviderXYZ")); antes de fazer a chamada. Tudo aqui é thread-safe e funciona muito bem com o TPL em C #.
Depende se as classes estáticas mantêm estado ou não. Pessoalmente, não tenho nenhum problema com as funções stateless agrupadas em uma classe estática.
Ele é muito geral sobre isso. Ele está correto, dificulta o teste. No entanto, static
classes e métodos têm seu lugar e isso realmente depende do contexto. Sem exemplos de código, você não pode dizer realmente.
I use static when I am not going to create an instance of a class because the class is a single global class used throughout the code.
Isso pode ser um cheiro de código severo. Para que você está usando as aulas? Para manter dados? Para acessar um banco de dados? Então ele está correto. Você deve procurar a injeção de dependência nesse caso, já que essa classe estática é efetivamente um singleton implícito.
Se você os estiver usando para métodos de extensão ou ajudantes que não mudam o estado e apenas operam nos parâmetros que você fornece, normalmente eles são bons.
I checked and fully 1/4 of my classes are marked "static". I use static when I am not going to create an instance of a class because the class is a single global class used throughout the code.
A melhor coisa a fazer é tentar testar seu código em unidade. Tente projetar testes que sejam repetíveis, independentes, simples e teste apenas um método por vez. Tente executar seus testes em ordem aleatória diferente. Você pode obter estável "verde" construir?
Se sim, esse é um ponto válido para defender seu código. Se, no entanto, você tiver dificuldades, talvez deva optar por métodos baseados em instância.
Uma das vantagens que você obtém do IoC / DI é que a maioria das interações entre as classes é negociada entre as interfaces. Isso torna o teste de unidade fácil porque as interfaces podem ser reproduzidas automaticamente ou semi-automaticamente e, portanto, cada uma das partes pode ser testada para entradas e saídas. Além disso, além da testabilidade, colocar interfaces entre tudo permite que você tenha o código mais modular possível - você pode facilmente substituir uma implementação sem se preocupar tanto com o fato de estar estragando as dependências.
Como o C # não possui metaclasses, uma classe não pode implementar uma interface usando recursos estáticos; portanto, recursos estáticos de classes terminam com qualquer esforço para implementar um modelo de objeto IoC / DI puro. Ou seja, você não pode criar uma simulação para testá-las e precisa criar dependências reais.
Se a sua empresa / projeto investir muito em IoC, isso obviamente é uma preocupação razoável, e a dor que você está passando é para o benefício de todos. Do ponto de vista arquitetônico, no entanto, eu pessoalmente não acho que qualquer modelo deva ser seguido até o túmulo. Há algumas coisas que fazem sentido implementar usando métodos estáticos - a estratégia de design singleton, por exemplo. Eu sou menos inclinado a classes estáticas porque eu acho que elas tendem a perder as vantagens de OO, mas há momentos em que uma classe de biblioteca é provavelmente uma expressão mais natural de algo do que um mecanismo.
O Commenter me lembra os métodos de extensão, que obviamente devem estar em classes estáticas em C #. Isso é legal, e é um exemplo de como o IoC puro não funciona muito bem em C #, pelo menos se você estiver tentando aproveitar a amplitude do idioma.
As respostas já postadas cobrem muitos pontos realmente bons, mas há uma que parece estar faltando:
Os campos estáticos são nunca coletados como lixo.
Isso é realmente importante se você tiver um aplicativo com muitas restrições de memória, e esse padrão pode ser muito comum quando as pessoas tentam implementar um cache.
Funções estáticas não são tão ruins, mas todo mundo já cobriu isso com detalhes suficientes.
As aulas estáticas são, às vezes, mal utilizadas e devem ser:
Também pode ser uma função chamada 'utilitário' e parte de uma classe de utilitário. Classes de utilitários são classes que contêm apenas métodos estáticos e servem como funções auxiliares sem qualquer contexto.
Métodos estáticos são bons de usar e têm um lugar de direito na programação. Parece que o seu arquiteto tem uma estrutura de teste que não suporta totalmente os métodos estáticos. Se o seu código faz parte de um projeto maior, é importante atender às diretrizes dos arquitetos. No entanto, não deixe que este projeto o impeça de usar métodos estáticos quando for apropriado fazê-lo.
Eu tenho usado propriedades estáticas para coisas que são comuns a todas as instâncias de uma classe. E eu tenho usado métodos estáticos para obter grupos de objetos de classe. Eu não sou de modo algum um especialista, mas isso tem funcionado para mim até agora.
Exemplo do PHP:
class vendorData {
private static $data_table = 'vendor_data'; // static property
private $id; // instance property
private $name; // instance property
public function __construct($vendor_id) {
if(!self::validId($vendor_id) ) { // static method
return false; // id doesn't exist
}
$this->id = $vendor_id; // id has been validated
$this->getProperties(); // object method
}
private static function validId($vendor_id) {
// send db query to find if the id exists
// return true/false;
}
private function getProperties() { // object method
$sql = "SELECT * FROM '{self::$data_table}' // using static property
WHERE 'id' = {$this->id}"; // using object instance property
// get resultset
foreach($result as $property => $value) {
$this->$property = $value; // object instance properties all set
}
}
// and here
public static function getBy($property,$value) { // static method to return object array
$sql = "SELECT 'id' FROM '{self::$data_table}' // using static property
WHERE '$property' = '$value'";
// send query, get $ids array
$obj_array = array();
foreach($ids as $id) {
// create array of current class objects using special static keyword
// meaning of static here is different than in property/method declarations
$obj_array[$id] = new static($id);
}
return $obj_array;
}
}
Eu vou dizer que os princípios que eles têm são bons, mas a afirmação (não use statics) pode estar errada. Quanto custa sua cobertura de código? Se o número for alto e você estiver confortável com o teste de unidade do seu aplicativo, você está bem. Se não, sugiro rever o código. Você pode achar que classes estáticas são a razão ou não, isso dependerá de muitas coisas.
Classes com métodos estáticos abusam dos princípios da POO. Não é uma OOP, é uma programação orientada para a classe COP.
Eles raramente têm "personalidade" clara (eu uso meu favorito metáfora humana aqui), ou identidade. Então eles não sabem quem são. Só esse ponto é suficiente para se livrar desse conceito na OOP, mas há mais deles.
O próximo é uma consequência do primeiro ponto. Como essas aulas não sabem quem são, elas tendem a ser de grandes a grandes.
O terceiro faz o seu código absolutamente não-sustentável. O uso de métodos static introduz dependências ocultas . Eles aparecem em todo o lugar e você nunca sabe o que está acontecendo na sua aula. Você não pode ter certeza disso apenas olhando para a assinatura do construtor.
Lentamente, mas inevitavelmente, seu código está ficando cada vez menos coeso, já que as dependências ocultas são mal controladas. Eles parecem invisíveis. E é tão fácil adicionar outro! Você não precisa modificar a assinatura de qualquer método. Tudo o que você precisa fazer é chamar um método estático. E que código feio segue ...
Ok, você provavelmente já adivinhou. O acoplamento apertado é um assistente de baixa coesão. Se há muitos clientes usando alguma classe, então o acoplamento está ficando mais apertado. E há uma grande sedução em usar uma classe ou método já escrito que requer apenas uma pequena correção. Apenas um parâmetro de parâmetro do método.
O que usar em vez de métodos estáticos? Bem, minha sugestão é OOP. Por que não tentar?