Método estático de obter – é esta prática ruim?

Tivemos uma discussão com um colega sobre isso, isto é má prática ou não. Agora não consigo encontrar exemplos imediatos deste online.

Nós temos muitos mapeadores de objects de database e chamamos suas funções assim

(exemplo) – o método setId é a linha do database e configura-o para propriedades pré-definidas

class Person { public static function get($id) { $object = new Person; $object->setId($id); return $object; } } 

Usando isso, podemos usar construções simples como esta: (onde obtivemos o id de, por exemplo, um post)

 $person = Person::get($id); 

ao invés de

 $person = new Person; $person->setId($id); 

Agora, meu instinto me diz que isso é uma má prática. Mas não posso explicar isso. Talvez alguém aqui possa explicar por que isso é, ou não é má prática

Aqui estão alguns outros exemplos de como o usamos. Nós usamos principalmente para getters. (apenas os nomes, não o código. Quase todos eles apenas executam uma consulta, que pode retornar 1 object e, em seguida, use o id do resultado para usar o método setId)

 class CatalogArticle { public static function get($id) { } public static function getByArticlenumber($articlenumber) {} //$articlenumber is unique in the database public static function getRandom() {} //Runs a query returning a random row } 

Esta não é uma perseguição horrível . É uma implementação de um padrão de design do método Factory . Não é ruim, em princípio.

No entanto, em seu exemplo específico, na verdade não está fazendo nada significativo, então não tenho tanta certeza se for necessário. Você poderia eliminar a necessidade, tomando um parâmetro (talvez opcional) para o construtor para o id. Então, qualquer pessoa poderia chamar $foo = new Person($id); em vez de precisar de uma fábrica explícita.

Mas se a instanciação é complexa ou você quer a capacidade de criar vários tipos de pessoas diferentes que só podem ser determinadas pela lógica, um método de fábrica pode funcionar melhor. Por exemplo, digamos que você precisa determinar o tipo de pessoa a ser instanciada por algum parâmetro. Então, um método de fábrica em Person seria apropriado. O método determinaria o “tipo” para carregar, e então instanciaria essa class.

A estática em geral é difícil de testar e não permite mudanças polimórficas como seria uma instância. Eles também criam dependencies rígidas entre classs no código. Eles não são horríveis , mas você realmente deve pensar sobre isso se você quiser usar um. Uma opção seria usar o Builder ou a Abstract Factory . Dessa forma, você cria uma instância do construtor / fábrica e, em seguida, deixe essa instância determinar como instanciar a class resultante …

Uma outra nota. Eu renomei esse método de Person::get() para algo um pouco mais semanticamente apropriado. Talvez Person::getInstance() ou algo mais apropriado.

Esta postagem no blog deve dizer-lhe por que as pessoas não gostam de methods estáticos melhor do que eu poderia:

http://kore-nordmann.de/blog/0103_static_considered_harmful.html

A questão que me parece mais sobre o seu fragment de código atual: uma pessoa está autorizada a NÃO ter um ID?

Eu acho que isso deve ser um argumento de construtor se representar uma Persona real. Se você usar essa class para criar novas pessoas, o ofc pode não funcionar.


A diferença entre as 2 chamadas é menor. Ambos criam uma class Pessoa e definem a Id para que você não esteja ganhando / perdendo nada lá quando se trata de “dependencies com fio rígido”.

A vantagem só mostra quando você quer passar uma Pessoa em outro object e esses objects precisam mudar a ID (como um exemplo, a postagem do blog deve explicar isso melhor do que eu fiz aqui).

Estou apenas adicionando a publicação de Edorian, mas usei methods de busca estática no passado, onde há um mecanismo de cache no lugar, e (por exemplo) eu poderia ter um determinado object Pessoa em memcache e preferiria recuperá-lo do cache do que para o database.

Por exemplo:

 class Person { public static function get($id) { if(Cache::contains("Person", $id)) { return Cache::get("Person", $id); } else { //fictional get_person_from_database, basically //getting an instance of Person from a database $object = get_person_from_database($id); } return $object; } } 

Desta forma, todo o tratamento do cache é feito pela class em questão, em vez do chamador, recebendo uma pessoa ligada para ter que se preocupar com o cache.

longa história curta, sim, são má prática:

Um bom motivo de tudo é que você deveria testar seu código. Os methods estáticos causam problemas, então você tem um bom motivo:

  • se você quiser seguir boas práticas, teste seu código
  • Ergo, se estática provoca problemas de teste, estática evita testes de escrita, portanto evita seguir boas práticas 🙂