Programación PHP Orientada a Aspectos

Hola a todos!

Este mes completamos el primer conjunto del curso Backend PHP Developer y los estamos contratando con might and main (tanto como sea posible durante las vacaciones). El curso se reponía con otro maestro: Evgeny Volosatov , a quien probablemente muchos conocen. Bueno, tradicionalmente compartimos cosas interesantes.

Vamos

En cualquier aplicación, hay partes del código que "cruzan" varias partes de la arquitectura al mismo tiempo.

Este problema no es tan obvio cuando se trabaja con un marco completamente funcional. Lo más probable es que su problema sea generalizado, y habrá una posibilidad de que el marco ya lo haya resuelto sacrificando una división de responsabilidad o proporcionando una abstracción sobre el marco. Muchos marcos utilizan una arquitectura orientada a eventos para resolver problemas de funcionalidad de extremo a extremo. Pero siempre llega un momento en que el marco no puede proporcionar el nivel deseado de control sobre una pieza particular de lógica. Esto es especialmente cierto cuando se utilizan microframes o desarrollo con bibliotecas especializadas. Cuanto más tenga en cuenta su aplicación los principios de separación de responsabilidades, mayor será el papel de la funcionalidad de extremo a extremo en su arquitectura.



Programación PHP Orientada a Aspectos


La Programación Orientada a Aspectos (AOP) es un paradigma de programación enfocado en organizar y modular la funcionalidad de extremo a extremo. Casos de aplicación: ACL, registro, manejo de errores, almacenamiento en caché.

Los supuestos integrados (internos) de PHP (cuando define una función / constante / clase, permanece definida para siempre) hacen que el paradigma AOP sea difícil de implementar.

Li3 fue el primero en resolver el problema de la funcionalidad de extremo a extremo utilizando un mecanismo de filtrado que permite filtrar la lógica de un método a través de cierres. Para que el método sea filtrable, la implementación de Li3 requiere la adición manual de código de plantilla. Con tales limitaciones, las técnicas de AOP se limitan a las técnicas de filtrado.

Otras implementaciones de AOP bien conocidas en PHP:


La extensión PECL AOP es un enfoque interesante pero al mismo tiempo arriesgado, ya que el soporte para extensiones PECL no es común. Otra opción es Go! Libraries, que es una implementación de AOP que corrige el código PHP sobre la marcha, lo que hace posible el uso de métodos AOP.

Hay otras implementaciones, pero la mayoría de ellas se basan en servidores proxy (hasta donde yo sé), y este enfoque tiene muchas limitaciones.

Chico nuevo en la zona


La generación automática de código ha estado durante mucho tiempo en PHP y se usa en muchas bibliotecas, por ejemplo ProxyManager. Y gracias a la adopción de Composer, Go! muestra que es posible editar código sobre la marcha.

Si la generación de código todavía puede considerarse simple, entonces corregir el código es algo más complicado. En primer lugar, en PHP no hay un analizador de código incorporado, y en segundo lugar, hay muy pocas bibliotecas que resuelvan los problemas de analizar el código PHP. La más famosa es la biblioteca PHP-Parser . PHP-Parser es una gran herramienta, pero incluso ignora el formato de espacios en los árboles de sintaxis abstracta generados. Lo que hace que sea difícil arreglar el código. De hecho, el código que debe corregirse es un código ejecutable real. Por lo tanto, si desea que el seguimiento sea preciso con los errores, debe tener en cuenta los números de línea en el archivo corregido.

Para esta tarea, usamos el parcheador de código Kahlan JIT. Kahlan es el nuevo marco de prueba de Unit & BDD, gracias a las técnicas de edición JIT, que permiten el código de parche de código auxiliar y mono directamente en Ruby o JavaScript. Debajo del capó, encontramos que esta biblioteca se basa en el analizador rudimentario de PHP. Pero, sin embargo, es lo suficientemente rápido y estable como para adaptarse a nosotros.

La biblioteca de filtros está disponible en github.com/crysalead/filter y se puede usar de la siguiente manera.

En primer lugar, el parcheador de código JIT debe inicializarse lo antes posible (por ejemplo, inmediatamente después de encender el compositor de carga automática):

include __DIR__ . '/../vendor/autoload.php'; use Lead\Filter\Filters; Filters::patch(true); 

Tenga en cuenta que la edición de código solo es posible para las clases cargadas por composer autoload'er. Si se agrega una clase usando las expresiones require o include, ya está cargada antes de llamar a Filters :: patch (true), y por lo tanto no será reparada.

De forma predeterminada, todo el código corregido se almacenará en / tmp / jit, pero siempre puede cambiarlo por su cuenta:

 Filters::patch(true, ['cachePath' => 'my/cache/path/jit']); 

Los archivos en caché se restaurarán automáticamente cada vez que cambie un archivo PHP.

Atencion Filters::patch(true) es la forma más fácil de configurar el parche, tenga en cuenta que todo su código será reparado. Puede llevar mucho tiempo envolver todos los métodos en su base de código en un cierre de filtro.

Afortunadamente, si la funcionalidad de extremo a extremo juega un papel crucial en un código bien diseñado, solo se necesitan un par de métodos en el proyecto. Por lo tanto, el enfoque preferido es arreglar solo los métodos que se filtrarán:

 Filters::patch([ 'A\ClassName', 'An\Example\ClassName::foo', 'A\Second\Example\ClassName' => ['foo', 'bar'], ], [ 'cachePath' => 'my/cache/path/jit', ]); 

Por lo tanto, puede elegir arreglar todos los métodos de una determinada clase, solo uno o varios de ellos.

Filtro API


Ahora que el parche JIT está habilitado, cree un filtro de registro:

 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); }); 

El ejemplo anterior crea un filtro de registro de consultas SQL para la biblioteca de la base de datos Chaos. Puede encontrar más información sobre el filtro API en github.com/crysalead/filter .

Conclusión


AOP, en mi opinión, es la respuesta real para la funcionalidad de extremo a extremo. Todas las demás abstracciones son igualmente redundantes y, en la mayoría de los casos, limitadas a un determinado marco. No pierdo la esperanza de que algún día PHP proporcionará una API incorporada para la programación orientada a aspectos. Pero ahora, creo, el parcheo de código JIT es la mejor opción, donde las ventajas superan con creces la sobrecarga de la CPU, que puede ser prácticamente ignorada cuando el parcheo de código JIT no se aplica globalmente.

El fin

Como siempre, esperamos, en todo caso, preguntas, un deseo y lo invitamos a una lección abierta donde podrá escuchar una conferencia interesante y conocer mejor al nuevo maestro .

Source: https://habr.com/ru/post/es415713/


All Articles