Características foram uma das maiores adições para o PHP 5.4. Conheço a sintaxe e entendo a ideia por trás de características, como a reutilização de código horizontal para coisas comuns, como log, segurança, cache etc.
No entanto, ainda não sei como utilizaria as características de meus projetos.
Existem projetos de código aberto que já usam características? Algum bom artigo / material de leitura sobre como estruturar arquiteturas usando características?
Respostas:
Minha opinião pessoal é que, na verdade, existe muito pouca aplicação de características ao escrever código limpo.
Em vez de usar características para hackear código em uma classe, é melhor passar as dependências pelo construtor ou pelos setters:
A principal razão pela qual acho que melhor do que usar características é que seu código é muito mais flexível removendo o acoplamento rígido a uma característica. Por exemplo, você pode simplesmente passar uma classe de logger diferente agora. Isso torna seu código reutilizável e testável.
fonte
Acho que seria preciso procurar em idiomas que possuam Traits há algum tempo para aprender as Boas / Melhores práticas aceitas. Minha opinião atual sobre o Trait é que você deve usá-los apenas para códigos que precisaria duplicar em outras classes que compartilham a mesma funcionalidade.
Exemplo para uma característica do criador de logs:
E então você faz ( demo )
Eu acho que o importante a considerar ao usar traços é que eles realmente são apenas pedaços de código que são copiados para a classe. Isso pode facilmente levar a conflitos, por exemplo, quando você tenta alterar a visibilidade dos métodos, por exemplo,
O exemplo acima resultará em um erro ( demo ). Da mesma forma, quaisquer métodos declarados na característica que também já estão declarados na classe using não serão copiados para a classe, por exemplo
imprimirá 2 ( demo ). Essas são as coisas que você deseja evitar, pois dificultam a localização dos erros. Você também deve evitar colocar coisas em características que operam nas propriedades ou métodos da classe que a utiliza, por exemplo,
funciona ( demo ), mas agora a característica está intimamente ligada a A e toda a idéia de reutilização horizontal é perdida.
Ao seguir o Princípio de Segregação de Interface, você terá muitas classes e interfaces pequenas. Isso faz da Traits um candidato ideal para as coisas que você mencionou, por exemplo , preocupações transversais , mas não para compor objetos (em um sentido estrutural). No exemplo do Logger acima, a característica é completamente isolada. Não possui dependências de classes concretas.
Poderíamos usar agregação / composição (como mostrado em outro lugar nesta página) para obter a mesma classe resultante, mas a desvantagem de usar agregação / composição é que teremos que adicionar os métodos proxy / delegador manualmente a cada classe, o que deve ser poder fazer logon. As características resolvem isso muito bem, permitindo-me manter o padrão em um só lugar e aplicá-lo seletivamente quando necessário.
Nota: dado que os traços são um novo conceito em PHP, todas as opiniões expressas acima estão sujeitas a alterações. Ainda não tive muito tempo para avaliar o conceito. Mas espero que seja bom o suficiente para lhe dar algo em que pensar.
fonte
:) Não gosto de teorizar e debater sobre o que deve ser feito com alguma coisa. Nesse caso, traços. Mostrarei a você o que acho útil para as características e você pode aprender com ela ou ignorá-la.
Traços - eles são ótimos para aplicar estratégias . Em resumo, os padrões de design da estratégia são úteis quando você deseja que os mesmos dados sejam manipulados (filtrados, classificados etc.) de maneira diferente.
Por exemplo, você tem uma lista de produtos que deseja filtrar com base em alguns critérios (marcas, especificações, qualquer que seja) ou classificados por diferentes meios (preço, etiqueta, qualquer que seja). Você pode criar uma característica de classificação que contenha funções diferentes para diferentes tipos de classificação (numérico, sequência, data etc.). Em seguida, você pode usar essa característica não apenas na sua classe de produto (conforme fornecido no exemplo), mas também em outras classes que precisam de estratégias semelhantes (para aplicar uma classificação numérica a alguns dados, etc.).
Tente:
Como observação final, penso em características como acessórios (que posso usar para alterar meus dados). Métodos e propriedades semelhantes que podem ser cortados das minhas aulas e colocados em um único local, para manutenção fácil, código mais curto e limpo.
fonte
strategies
.Estou empolgado com o Traits, porque eles resolvem um problema comum ao desenvolver extensões para a plataforma de comércio eletrônico Magento. O problema ocorre quando as extensões adicionam funcionalidade a uma classe principal (como o modelo do usuário) estendendo-a. Isso é feito apontando o carregador automático do Zend (por meio de um arquivo de configuração XML) para usar o modelo de usuário da extensão e fazer com que esse novo modelo estenda o modelo principal. ( exemplo ) Mas e se duas extensões substituírem o mesmo modelo? Você obtém uma "condição de corrida" e apenas uma é carregada.
A solução agora é editar as extensões para que uma amplie a classe de substituição de modelo da outra em uma cadeia e, em seguida, defina a configuração da extensão para carregá-las na ordem correta para que a cadeia de herança funcione.
Esse sistema freqüentemente causa erros e, ao instalar novas extensões, é necessário verificar se há conflitos e editar extensões. Isso é doloroso e interrompe o processo de atualização.
Eu acho que usar Traits seria uma boa maneira de realizar a mesma coisa sem esse modelo irritante substituir a "condição de corrida". É verdade que ainda pode haver conflitos se várias características implementarem métodos com os mesmos nomes, mas eu imagino que algo como uma simples convenção de namespace possa resolver isso na maior parte do tempo.
TL; DR Acho que o Traits pode ser útil para criar extensões / módulos / plugins para grandes pacotes de software PHP como o Magento.
fonte
Você poderia ter uma característica para um objeto somente leitura como este:
Você pode detectar se essa característica é usada e determinar se deve ou não gravar esse objeto em um banco de dados, arquivo etc.
fonte
use
essa característica chamariaif($this -> getReadonly($value))
; mas isso geraria um erro se você não tivesseuse
essa característica. Portanto, este exemplo é falho.