Olá pessoal!
Este mês, concluímos o primeiro conjunto do curso de
desenvolvedor PHP de back-end e os contratamos com poder e main (o máximo possível durante os feriados). O curso foi reabastecido com outro professor -
Evgeny Volosatov , que muitos provavelmente conhecem. Bem, tradicionalmente compartilhamos coisas interessantes.
Vamos lá
Em qualquer aplicativo, há partes do código que cruzam várias partes da arquitetura ao mesmo tempo.
Esse problema não é tão óbvio ao trabalhar com uma estrutura totalmente funcional. Muito provavelmente, o seu problema será generalizado e haverá uma chance de que a estrutura já o tenha resolvido sacrificando uma divisão de responsabilidades ou fornecendo uma abstração sobre a estrutura. Muitas estruturas usam uma arquitetura orientada a eventos para resolver problemas de funcionalidade de ponta a ponta. Mas sempre chega um momento em que a estrutura não é capaz de fornecer o nível de controle desejado sobre uma parte específica da lógica. Isto é especialmente verdade ao usar microframes ou desenvolvimento com bibliotecas especializadas. Quanto mais seu aplicativo levar em conta os princípios de separação de responsabilidades, maior será o papel da funcionalidade de ponta a ponta em sua arquitetura.

Programação PHP orientada a aspectos
A Aspect Oriented Programming (AOP) é um paradigma de programação focado na organização e modularização da funcionalidade de ponta a ponta. Casos de aplicativos - ACLs, log, manipulação de erros, armazenamento em cache.
As suposições internas (internas) do PHP (quando você define uma função / constante / classe, ela permanece definida para sempre) tornam o paradigma da AOP difícil de implementar.
O Li3 foi o primeiro a resolver o problema da funcionalidade de ponta a ponta usando um mecanismo de filtragem que permite filtrar a lógica de um método por meio de fechamentos. Para tornar o método filtrável, a implementação do Li3 requer a adição manual de código de modelo. Com essas limitações, as técnicas de AOP são limitadas às técnicas de filtragem.
Outras implementações conhecidas de AOP no PHP:
A extensão PECL AOP é uma abordagem interessante, mas ao mesmo tempo arriscada, pois o suporte a extensões PECL não é comum. Outra opção são as bibliotecas Go!, Que são uma implementação de AOP que corrige o código PHP em tempo real, o que possibilita o uso de métodos de AOP.
Existem outras implementações, mas a maioria delas é criada com base em proxies (tanto quanto eu sei), e essa abordagem tem muitas limitações.
Cara novo na área
A geração automática de código existe há muito tempo em PHP e é usada em muitas bibliotecas, por exemplo,
ProxyManager. E, graças à adoção do Composer,
Go! mostra que é possível editar o código rapidamente.
Se a geração de código ainda pode ser considerada simples, a correção do código é um pouco mais complicada. Primeiramente, no PHP não há analisador de código interno e, em segundo lugar, existem muito poucas bibliotecas que resolvem os problemas de análise do código PHP. O mais famoso é a biblioteca
PHP-Parser . O Analisador de PHP é uma ótima ferramenta, mas até ignora a formatação de espaços nas árvores de sintaxe abstrata geradas. O que dificulta a correção do código. De fato, o código que precisa ser corrigido é um código executável real. Portanto, se você deseja que o retorno seja preciso com erros, considere os números de linha no arquivo corrigido.
Para esta tarefa, usamos o
patcher de código Kahlan JIT. Kahlan é a nova estrutura de teste Unit & BDD, graças às técnicas de edição JIT que permitem código de patch de stub e monkey diretamente em Ruby ou JavaScript. Sob o capô, descobrimos que essa biblioteca é baseada no analisador rudimentar de PHP. Mas, no entanto, é rápido o suficiente e estável para nos adequar.
A biblioteca de filtros está disponível em
github.com/crysalead/filter e pode ser usada da seguinte maneira.
Primeiramente, o patcher de código JIT deve ser inicializado o mais rápido possível (por exemplo, imediatamente após ligar o compositor de autoloade):
include __DIR__ . '/../vendor/autoload.php'; use Lead\Filter\Filters; Filters::patch(true);
Observe que a edição de código só é possível para classes carregadas pelo compositor autoload'er. Se uma classe for adicionada usando as expressões require ou include, ela já será carregada antes de chamar Filters :: patch (true) e, portanto, não será corrigida.
Por padrão, todo o código corrigido será armazenado em / tmp / jit, mas você sempre pode alterá-lo por conta própria:
Filters::patch(true, ['cachePath' => 'my/cache/path/jit']);
Os arquivos em cache serão restaurados automaticamente sempre que você alterar um arquivo PHP.
Atenção!
Filters::patch(true)
é a maneira mais fácil de configurar o patcher, lembre-se de que todo o seu código será corrigido. Pode levar muito tempo para agrupar todos os métodos em sua base de código em um fechamento de filtro.
Felizmente, se a funcionalidade de ponta a ponta desempenha um papel crucial em códigos bem projetados, apenas alguns métodos são necessários no projeto. Portanto, a abordagem preferida é corrigir apenas os métodos que serão filtrados:
Filters::patch([ 'A\ClassName', 'An\Example\ClassName::foo', 'A\Second\Example\ClassName' => ['foo', 'bar'], ], [ 'cachePath' => 'my/cache/path/jit', ]);
Assim, você pode optar por corrigir todos os métodos de uma determinada classe, apenas um método ou vários deles.
Filtro de API
Agora que o JIT patcher está ativado, crie um filtro de log:
use Chaos\Filter\Filters; use Chaos\Database\Database; use Monolog\Logger; use Monolog\Handler\StreamHandler; $logger = new Logger('database'); $logger->pushHandler(new StreamHandler('my/log/path/db.log', Logger::WARNING)); Filters::apply(Database::class, 'query', function($next, $sql, $data, $options) use ($logger) { $logger->info('Ran SQL query: ' . $sql); return $next($sql, $data, $options); });
O exemplo acima cria um filtro de log de consulta SQL para a biblioteca de banco de dados do Chaos. Mais informações sobre o filtro da API podem ser encontradas em
github.com/crysalead/filter .
Conclusão
AOP, na minha opinião, é a resposta real para a funcionalidade de ponta a ponta. Todas as outras abstrações são igualmente redundantes e, na maioria dos casos, limitadas a uma determinada estrutura. Não perco a esperança de que um dia o PHP forneça uma API interna para programação orientada a aspectos. Mas agora, penso, o patch de código JIT é a melhor opção, onde as vantagens superam em muito a sobrecarga da CPU, que pode ser praticamente negligenciada quando o patch de código JIT não é aplicado globalmente.
O FIM
Como sempre, esperamos, se houver alguma coisa, perguntas, um desejo e convidamos você para
uma aula aberta, onde você pode ouvir uma palestra interessante e conhecer melhor o novo
professor .