Revisión de código, parte 2: mejora de la legibilidad y el rendimiento de la clase FilterWPQuery

Índice
  1. Make shouldFilter Decide si debemos filtrar o no
    1. Paso 1: Mueva el comprobador de valores nulos
    2. Paso 2: Invierta el orden de verificación para mejorar el rendimiento
    3. Paso 3: Abstraer el verificador REST para mejorar la legibilidad
    4. Paso 4: Simplemente devuelva la decisión del condicional
    5. Paso 5: Actualizar la interfaz
  2. Omitir la tarea y simplemente regresar
  3. La devolución de llamada es demasiado genérica. Haga que nos diga qué hace.
  4. Utilice la propiedad Nivel de prioridad
  5. Vamos a repasar
  6. ¿Que sigue?
  7. Vamos a discutirlo

En elúltimo artículoTe guié a través del problema de dejar que las condiciones de “no pasar” fluyan a través de tu código. Te mostré cómo refactorizar el código para resolver el problema y hacer que el código sea más legible. En este artículo, tú y yo continuaremos haciendo una revisión y refactorización del código FilterWPQueryenEl complemento de Josh Pollock.

EnParte 3 de POO avanzado para WordPressJosh te explica cómo refactorizó la FilterWPQueryclase para que sea más fácil de probar. Usemos su última versión de la clase para nuestro proceso de revisión de código.

?phpespacio de nombres CalderaLearnRestSearch;/** * Clase FilterWPQuery * * Cambia el objeto WP_Query durante las solicitudes de API REST * * @paquete CalderaLearnRestSearch */La clase FilterWPQuery implementa FiltersPreWPQuery{/** * Prioridad para el filtro * * @var entero */estático protegido $filterPriority = 10;/** * Demuestra cómo utilizar una forma diferente de configurar las publicaciones que devuelve WP_Query * * @uses "consulta previa de publicaciones" * * @param $publicacionesONulo * @return WP_Post[] */devolución de llamada de función estática pública ($postsOrNull){//Se ejecuta solo durante las solicitudes de API de WordPresssi (static::shouldFilter()) {//Evitar recursiones//No ejecutar si las publicaciones ya fueron enviadassi (es_null($postsOrNull)) {//Obtener datos simulados$postsOrNull = estático::getPosts();}}//Siempre devuelve algo, incluso si no ha cambiadodevuelve $postsOrNull;}/** @hereditardoc */función estática pública shouldFilter() :bool{devolver did_action('rest_api_init');}/** @hereditardoc */función estática pública addFilter() : bool{devolver add_filter('posts_pre_query', [FilterWPQuery::class, 'callback'], 10);}/** @hereditardoc */función estática pública removeFilter() : bool{devolver remove_filter('posts_pre_query', [FilterWPQuery::class, 'callback'], 10);}/** @hereditardoc */función estática pública getFilterPriority() : int{devuelve static::$filterPriority;}/** @hereditardoc */función estática pública getPosts() : matriz{//Crea 4 publicaciones simuladas con títulos diferentes$Publicaciones simuladas = [];para ($i = 0; $i = 3; $i++) {$post = nuevo WP_Post((nuevo stdClass()));$post-post_title = "Publicación simulada $i";$post-filter = 'sin procesar';$mockPosts[$i] = $publicación;}//Devuelve una matriz simulada de publicaciones simuladasdevuelve $mockPosts;}}

Para comenzar, refactorizaré rápidamente las condiciones de apertura aplicando la misma estrategia de “retorno temprano” que usted y yo usamos en el último artículo:

devolución de llamada de función estática pública ($postsOrNull){// Salir si no es una solicitud REST de WordPress.si ( ! static::shouldFilter()) {devuelve $postsOrNull;}//Salir si las publicaciones ya fueron enviadas.si ( ! es_null($postsOrNull)) {devuelve $postsOrNull;}// Obtener datos simulados$postsOrNull = estático::getPosts();devuelve $postsOrNull;}

Ahora podemos comenzar nuestra revisión de código.

Make shouldFilter Decide si debemos filtrar o no

Tenga en cuenta que Josh creó un nuevo método llamado shouldFilter(). El nombre de este método nos indica que decide si la devolución de llamada debe filtrar la consulta previa o no.

Al revisar el código de devolución de llamada, esa decisión debe basarse en dos condiciones:

  1. WordPress está procesando actualmente una solicitud RESTful.
  2. El valor entrante es nulo, lo que significa que debemos buscar las publicaciones.

Hay un problema. En el diseño actual, el shouldFilter()método no decide si filtrar o no, sino que solo realiza una de las comprobaciones.

¿Cómo podemos solucionar este problema? Podemos mover el comprobador de valores nulos al método.

Vamos a recorrerlo juntos paso a paso.

Paso 1: Mueva el comprobador de valores nulos

El primer paso es reubicar el verificador de valores nulos del callback()método y colocarlo en el shouldFilter()método. Es bastante fácil cortarlo de un método y pegarlo en otro.

Pero espere, el verificador de valores nulos depende de la entrada dada. Eso significa que lo declaramos $postsOrNullcomo parámetro de un método.

función estática pública shouldFilter($postsOrNull) :bool{// Comprobador de solicitudes REST.si ( ! did_action('rest_api_init')) {devuelve falso;}// Comprobador de valores nulos.si ( ! es_null($postsOrNull)) {devuelve falso;}devuelve verdadero;}

Paso 2: Invierta el orden de verificación para mejorar el rendimiento

Déjame hacerte una pregunta. ¿Qué sucede si el método recibe algo distinto de null? Mira el código. ¿Qué sucede?

Sí, vuelve falsey hace su trabajo. Pero observe el flujo de control. Primero, tiene que pasar por el verificador de solicitudes REST.

Piense en el orden de los comprobadores. ¿Deberíamos realizar la comprobación de la solicitud REST antes de comprobar lo que recibimos?

La respuesta a esa pregunta depende de la complejidad del código. En este caso, es más eficiente (más rápido) invertir el orden y hacer primero el verificador de valores nulos.

¿Por qué? Observa el código. La función PHP is_nulles muy rápida, mientras que la función WordPress did_action()tiene más código que procesar.

Al invertir el orden, podemos hacer primero la comprobación más rápida. Luego, si falla, el código se retirará más rápidamente y regresará antes.

función estática pública shouldFilter($postsOrNull) :bool{// Comprobador de valores nulos.si ( ! es_null($postsOrNull)) {devuelve falso;}// Comprobador de solicitudes REST.si ( ! did_action('rest_api_init')) {devuelve falso;}devuelve verdadero;}

Paso 3: Abstraer el verificador REST para mejorar la legibilidad

En este momento, el verificador REST requiere un comentario en línea para que podamos comprender rápidamente su propósito (es decir, qué está haciendo). Eliminemos ese comentario y le haré una pregunta.

if (did_action('rest_api_init')) {}

¿Puedes entender rápidamente cuál es la intención de esta comprobación? No, no puedo. ¿Estás de acuerdo? Entonces, tenemos que refactorizar este código paraHaz que nos lo diga.

Consejo sobre el código: haz que nos lo cuente. Hazlo legible para humanos.

Quiero detenerme aquí por un momento y compartir un consejo de código con ustedes.

El código debe ser expresivo y muy legible para las personas. Debe decirnos qué está sucediendo para que podamos realizar nuestro trabajo rápidamente.

Cuando el código necesita un comentario, eso suele ser una pista. La forma de saber si es necesario refactorizarlo es leer el código sin el comentario y preguntarse: “¿Puedo entender rápidamente qué está pasando?”. Si la respuesta es no, entonces refactorice.

“El código limpio es simple y directo. Se lee como si fuera prosa bien escrita. El código limpio nunca oculta la intención del diseñador, sino que está lleno de abstracciones claras y líneas de control sencillas”.

Grady Booch,Código limpio: un manual de desarrollo ágil de software

Volver a Refactorización

Refactoricemos este verificador creando un método privado:

función estática pública shouldFilter($postsOrNull) :bool{si ( ! es_null($postsOrNull)) {devuelve falso;}si ( ! static::doingREST()) {devuelve falso;}devuelve verdadero;}/** * Comprueba si WordPress está realizando una solicitud REST. * * @return booleano */función estática privada doingREST() : bool{devolver did_action('rest_api_init');}

Tenga en cuenta que elEl nombre del método describe el comportamiento de este verificador.Ya no necesitamos los comentarios en línea. Cuando vuelvas a consultar este código la próxima semana o el próximo año, el código te transmitirá su mensaje más rápidamente.

Recordar,La legibilidad es un pilar fundamental de un código de calidad. Haz que sea claro. Haz que sea legible para los humanos.

Paso 4: Simplemente devuelva la decisión del condicional

A menudo veo este patrón de código:

si ( ! static::doingREST()) {  devuelve falso;}devuelve verdadero;

¿Por qué necesitamos devolver de forma explícita verdadero o falso? Piénsalo.

La condición ya está devolviendo su decisión en formato booleano. Eso significa que la decisión ya se tomó. ¿Por qué no devolver simplemente su decisión?

return static::doingREST();

¿Por qué es mejor esta estrategia?

  1. Es menos código para leer y mantener.
  2. Tiene mayor rendimiento (es más rápido) porque solo hay una línea de código para que PHP la procese.

Aquí está nuestro código refactorizado hasta este punto:

devolución de llamada de función estática pública ($postsOrNull){si ( ! static::shouldFilter($postsOrNull)) {devuelve $postsOrNull;}// Obtener datos simulados$postsOrNull = estático::getPosts();devuelve $postsOrNull;}función estática pública shouldFilter($postsOrNull) :bool{si ( ! es_null($postsOrNull)) {devuelve falso;}devolver static::doingREST();}/** * Comprueba si WordPress está realizando una solicitud REST. * * @return booleano */función estática privada doingREST() : bool{devolver did_action('rest_api_init');}

Paso 5: Actualizar la interfaz

El último paso es actualizar el método en la interfaz para declarar la entrada entrante:

/** * Comprueba si la solicitud debe filtrarse o no. * * @param array|null $postsOrNull Matriz de WP_Posts o nulo. * @return booleano */función estática pública shouldFilter($postsOrNull) :bool;

Ahora la interfaz y la implementación coinciden.

Omitir la tarea y simplemente regresar

Veamos estas dos líneas de código:

// Obtener datos simulados$postsOrNull = estático::getPosts();devuelve $postsOrNull;

¿Qué observas? Piensa en lo que hacen estas líneas de código.

La matriz de publicaciones devuelta por el getPosts()método se asigna primero a una variable antes de devolverse al evento de filtro. ¿Por qué? No se utiliza en ningún lado.

Este código es un ejemplo de una asignación innecesaria. Aquí, podemos devolver lo que se devuelva desde getPosts().

devolución de llamada de función estática pública ($postsOrNull){si ( ! static::shouldFilter($postsOrNull)) {devuelve $postsOrNull;}devolver static::getPosts();}

Esta refactorización es mejor porque:

  1. Es menos código para leer y mantener.
  2. Tiene mayor rendimiento (es más rápido) porque:
    1. PHP no tiene que crear la variable en su tabla de símbolos.
    2. No es necesario vincular esa variable a la ubicación de memoria de la matriz.
    3. Evita una búsqueda de variable antes de regresar.
    4. Solo hay una línea de código para que PHP la procese.

Puede obtener más información sobre cómo PHP administra su memoria leyendo elLibro sobre los aspectos internos de PHP.

La devolución de llamada es demasiado genérica. Haga que nos diga qué hace.

Ya me di cuenta de lo importante que es que el código nos diga qué está pasando. Eso empieza por cómo nombramos nuestras funciones y métodos. Estos son nuestros trabajadores. Hacen cosas. Por lo tanto, deberían empezar con un verbo y luego ser descriptivos y expresivos sobre su comportamiento.

El nombre “callback” es genérico. Esa palabra significa que el método está vinculado a algo que lo invocará, pero no nos dice nada sobre lo que sucederá.

¿Qué hace este método?

  1. Es un filtro que cambia la entrada dada para el ’posts_pre_query’evento.
  2. Maneja o gestiona la obtención de la matriz de publicaciones que utilizará la consulta.

Por lo tanto, en esencia, es un filtro que cambia la consulta previa. Vamos a cambiarle el nombre a filterPreQuery. ¿Qué opinas?

Para realizar este cambio de nombre, tendremos que cambiarlo en la interfaz y en cada una de las pruebas que creó Josh. Esto es bastante fácil con una búsqueda y reemplazo global.

Utilice la propiedad Nivel de prioridad

Eche un vistazo a los métodos addFilter()y removeFilter(). Observe que el nivel de prioridad está codificado. ¿Por qué? Siga conmigo mientras explico el proceso de pensamiento.

La clase tiene una propiedad que contiene el valor del nivel de prioridad. Hay un método para obtener esa propiedad.

Imagina que quisieras cambiarlo de 10 a, digamos, 99. Para hacer ese cambio, ¿cuántos lugares en la clase tienes que recordar cambiar? 3.

¿Qué ocurre si se olvida reemplazar uno de ellos? Podría producirse un error.

Usando elPrincipio DRYNos esforzamos por eliminar el código redundante. Una de las razones es eliminar el problema que acabo de explicar.

¿Cómo solucionamos este problema? Podemos usar la propiedad al agregar o quitar el gancho de filtro:

/** @hereditardoc */función estática pública addFilter() : bool{devolver add_filter('posts_pre_query', [FilterWPQuery::clase, 'filterPreQuery'], static::$filterPriority);}/** @hereditardoc */función estática pública removeFilter() : bool{devolver remove_filter('posts_pre_query', [FilterWPQuery::clase, 'filterPreQuery'], static::$filterPriority);}

Vamos a repasar

En este artículo hablé de muchas cosas. Juntos, recorrimos el proceso de revisión de código para mejorar la FilterWPQueryclase. Aunque esta clase es pequeña, hubo bastantes mejoras en la calidad del código.

Veamos lo que hicimos para mejorar la legibilidad y el rendimiento:

La mejora Legibilidad Actuación
Hizo que el shouldFiltermétodo decidiera si la clase debería filtrar o no.
Se invirtió el orden de las fichas.
Se creó un nuevo método privado para indicarnos la intención de verificar si WordPress está procesando una solicitud RESTful.
Devolvió la decisión del condicional.
Se omitió la asignación de variable para simplemente devolver la matriz de getPosts().
Le dimos al método de devolución de llamada un nombre más expresivo para indicarnos qué hace. Hicimos que ese nombre comenzara con un verbo, ya que los métodos funcionan.

Además, hicimos que el código sea más fácil de mantener:

  1. Se utilizó la propiedad del nivel de prioridad para reemplazar los números enteros codificados en los métodos agregar y eliminar.

Todas estas mejoras están diseñadas para aumentar la calidad del código de la clase.

¿Que sigue?

¿Qué tal el código del generador de publicaciones en el getPosts()método? Creo que ya hemos hecho suficiente en este artículo. ¿No crees? Continuemos.Proceso de revisión y mejora del código en la Parte 3.

El código final y cada paso de refactorización están documentados en elSolicitud de extracción en GitHubTe invito a explorarlo.

Vamos a discutirlo

¿Qué opinas? ¿Tiene sentido cada una de estas mejoras para ti? No, en serio, quiero saber lo que piensas.

A partir del tutorial paso a paso, ¿ve cómo implementar cada una de estas estrategias en su propio código?

Espero poder hablar contigo sobre este proceso de revisión y refactorización. No dudes en hacerme cualquier pregunta y compartir tus opiniones en los comentarios a continuación.

SUSCRÍBETE A NUESTRO BOLETÍN 
No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion