En el tutorial anterior, cubrimos un puñado de conceptos, todos los cuales serán necesarios para comprender completamente lo que estamos haciendo en este tutorial..
Específicamente, cubrimos los siguientes temas:
En algunas series, es fácil omitir los tutoriales que pueden no estar basados en otros; Sin embargo, esta serie no pretende ser así. En su lugar, está pensado para ser leído en orden secuencial, y está pensado para construir en el contenido de cada tutorial anterior..
Dicho esto, estoy asumiendo que todos están atrapados.
Aunque podría haber mencionado esto en el primer tutorial, me gustaría asegurarme de que todos estemos en la misma página con respecto a lo que estamos haciendo en cada tutorial y con el software que va a necesitar..
Así que en este tutorial, el plan es el siguiente:
En definitiva, no estaremos escribiendo. mucho Código en este tutorial, pero vamos a escribir algunos. Sin embargo, es un tutorial práctico en el que estamos realizando análisis y diseño orientados a objetos. Esta es una fase necesaria para muchos proyectos a gran escala (y algo que debería ocurrir para proyectos a pequeña escala).
Si has estado siguiendo esto, deberías tener esto ya configurado. Pero para estar seguro, aquí está la versión corta de todo lo que necesita:
Con todo eso en su lugar, estamos listos para trabajar en el código compartido en el tutorial anterior. Entonces empecemos.
Lo primero que queremos hacer es analizar el estado actual de nuestro autoloader. Puede parecer mucho código para pegar en un solo bloque de código, pero eso en sí mismo nos muestra que tenemos mucho trabajo por hacer..
Dicho esto, aquí está el estado actual de nuestro autoloader:
0; $ i--) // Lea el componente actual de la parte del archivo. $ current = strtolower ($ file_parts [$ i]); $ current = str_ireplace ('_', '-', $ current); // Si estamos en la primera entrada, entonces estamos en el nombre de archivo. if (count ($ file_parts) - 1 === $ i) / * Si 'interface' está contenido en las partes del nombre del archivo, entonces * define $ file_name de manera diferente para que se cargue correctamente. * De lo contrario, simplemente establezca $ file_name igual a la de la estructura de * nombre de archivo de clase. * / if (strpos (strtolower ($ file_parts [count ($ file_parts) - 1]), 'interface')) // Coge el nombre de la interfaz de su nombre completo. $ interface_name = explode ('_', $ file_parts [count ($ file_parts) - 1]); $ interface_name = $ interface_name [0]; $ file_name = "interface- $ interface_name.php"; else $ file_name = "class- $ current.php"; else else $ namespace = '/'. $ actual. $ namespace; // Ahora cree una ruta al archivo utilizando la asignación a la ubicación del archivo. $ filepath = trailingslashit (dirname (dirname (__FILE__)). $ namespace); $ filepath. = $ file_name; // Si el archivo existe en la ruta especificada, inclúyalo. if (file_exists ($ filepath)) include_once ($ filepath); else wp_die (esc_html ("El archivo que intenta cargarse en $ filepath no existe."));
En este punto, recuerde que el principio de responsabilidad única establece lo siguiente:
Una clase debe tener una sola razón para cambiar.
En este momento, ni siquiera tenemos una clase, y mucho menos varios métodos individuales que solo tienen una razón para cambiar.
Y aunque podría tener sentido comenzar dividiendo este método de autocargador en métodos más pequeños e individuales, comencemos desde un nivel superior y comencemos a pensar en un autocargador en términos de una interfaz. Luego profundizaremos en la creación de una clase (o clases).
Recuerde del tutorial anterior que el manual de PHP define una interfaz de la siguiente manera:
Las interfaces de objetos le permiten crear código que especifica qué métodos debe implementar una clase, sin tener que definir cómo se manejan estos métodos.
Dado el código y las definiciones anteriores, pensemos qué debe hacer un autocargador desde una perspectiva más modular. Específicamente, dividámoslo en puntos que representen lo que podría ser suficiente para cambiar. No, es posible que no utilicemos todos estos puntos, pero esta es la razón por la que se llama análisis. Trabajaremos en el diseño más tarde..
El código hace lo siguiente:
$ class_name
es un nombre de variable pobre).Así, el código anterior hace nueve cosas-es decir, tiene al menos Nueve razones para cambiar, antes de que termine de completar su trabajo..
Esto debería ser evidente, pero esta función en particular es un ejemplo perfecto que podemos refactorizar para demostrar el análisis, diseño, interfaces e implementación orientados a objetos..
Y esto plantea una pregunta: ¿Dónde empezamos??
En este punto, es justo decir que podemos comenzar a hacer un análisis orientado a objetos, es decir, ver qué clases potenciales podemos tener y cómo interactúan, dado todo lo que hemos enumerado anteriormente. Recuerde, también queremos que el principio de responsabilidad única nos ayude a guiarnos en nuestra toma de decisiones..
En este punto, no estamos muy preocupados por cómo las clases se comunicarán entre sí. En cambio, estamos más enfocados en crear clases que tienen una sola razón para cambiar.
Dicho esto, voy a proporcionar un conjunto de muestra de clases que creo que podrían funcionar. Antes de continuar, observe lo que hemos hecho e intente crear su propia lista. Entonces podemos comparar notas.
Tenga en cuenta que puede tener una idea mejor que la que figura a continuación, o puede quitar algo de lo que hemos compartido. En cualquier caso, este es un ejercicio de aprendizaje. Estamos intentando mejorar nuestro código, nuestra organización y, en última instancia, convertirnos en mejores programadores..
Teniendo en cuenta lo que he enumerado anteriormente, he encontrado las siguientes clases:
Y eso es. Ahora las clases de terceros en nuestro complemento solo necesitan saber acerca de la clase del autocargador, pero el autocargador necesitará el conocimiento de otra clase, y otras clases necesitarán el conocimiento de otras clases..
Ahí son maneras de manejar esto (usando contenedores de inyección de dependencia, pero eso está fuera del alcance de este proyecto). Pero lo que intentaremos hacer a través de nuestro código es minimizar cuántas clases se conocen unas de otras.
En este punto, diferentes desarrolladores, empresas, agencias y equipos adoptarán un enfoque diferente de cómo diseñan el sistema en el que están trabajando..
Una de las formas más comunes de hacer esto es usar algo llamado diagrama UML. Aunque es útil, no es algo que valga la pena hacer dentro del alcance de este tutorial porque requerirá otro tutorial completo para explicar todas las piezas..
Por lo tanto, para los fines de nuestro tutorial, y dado que estamos trabajando con una cantidad tan pequeña de código, intentaremos descubrir cómo pueden funcionar cada una de las clases anteriores antes de implementarlas. De esta manera, tendremos una idea de cómo podemos organizar nuestro código..
Tenga en cuenta que todavía no vamos a poner espacios de nombre a este código, y todavía no se debe implementar ni probar ninguno de este código en WordPress. Vamos a entrar en eso en el siguiente tutorial..
Comencemos con el Autocargador
y trabajar desde ahi.
Recuerde, esta clase es responsable de incluir el archivo necesario. Este es el archivo que se registrará con el spl_autoload_register
función.
namespace_validator = new NamespaceValidator (); $ this-> file_registry = new FileRegistry (); carga de la función pública ($ nombre de archivo) if ($ this-> namespace_validator-> is_valid ($ filename)) $ this-> file_registry-> load ($ filename);
Tenga en cuenta que esta clase depende de la NamespaceValidator
y el FileRegistry
clase. Veremos cada uno de estos con más detalle en un momento..
Este archivo mirará el nombre de archivo entrante y determinará si es válido. Esto se hace mirando el espacio de nombres en el nombre de archivo.
Si el archivo hace de hecho, pertenecemos a nuestro espacio de nombres, entonces podemos asumir que es seguro cargar nuestro archivo.
FileInvestigator
Esta clase está haciendo bastante trabajo, aunque parte de ella se realiza a través de métodos de ayuda muy simples y muy pequeños. Durante el curso de la ejecución, mira el tipo de archivo que se pasa.
Luego recupera el nombre de archivo completamente calificado para el tipo de archivo.
get_file_name ($ file_parts, $ current, $ i); if (count ($ file_parts) - 1! == $ i) $ filepath = trailingslashit ($ filepath); devolver $ filepath; función privada get_file_name ($ file_parts, $ current, $ i) $ filename = "; if (count ($ file_parts) - 1 === $ i) if ($ this-> is_interface ($ file_parts)) $ filename = $ this-> get_interface_name ($ file_parts); else $ filename = $ this-> get_class_name ($ current); else else $ filename = $ this-> get_namespace_name ($ current); return $ filename; la función privada is_interface ($ file_parts) return strpos (strtolower ($ file_parts [count ($ file_parts) - 1]), 'interface'); la función privada get_interface_name ($ file_parts) $ interface_name = explode ('_', $ file_parts [count ($ file_parts) - 1]); $ interface_name = $ interface_name [0]; return "interface- $ interface_name.php"; función privada get_class_name ($ current) return "class- $ current.php" ; función privada get_namespace_name ($ current) return '/'. $ current;Si hay un archivo que puede ser refactorizado un poco más, entonces este es el archivo. Después de todo, intenta determinar si estamos trabajando con una clase, una interfaz o una clase. Una simple fábrica podría ser más adecuada para esto.
Cuando llegue el momento de implementar nuestro código, tal vez lo refaccionemos más. Hasta entonces, este es un diseño preliminar que puede funcionar lo suficientemente bien..
FileRegistry
Esto usará la ruta del archivo completamente calificado e incluirá el archivo; de lo contrario, utilizará la API de WordPress para mostrar un mensaje de error.
clase FileRegistry private $ investigator; función pública __construct () $ this-> investigator = new FileInvestigator (); carga de función pública ($ filepath) $ filepath = $ this-> investigator-> get_filetype ($ filepath); $ filepath = rtrim (plugin_dir_path (dirname (__FILE__)), '/'). $ filepath; if (file_exists ($ filepath)) include_once ($ filepath); else wp_die (esc_html ('El archivo especificado no existe.'));Otra alternativa a usar la API de WordPress sería lanzar un mensaje de excepción personalizado. De esa manera, podríamos separar o desacoplar completamente nuestro código de WordPress.
Una vez más, este código es un traspaso del autocargador inicial. Durante la implementación, podemos cambiar esto, también.
Conclusión
De acuerdo, hemos examinado el código existente para nuestro autocargador y luego hemos eliminado un código potencial que podemos usar en función de algunos análisis y diseños orientados a objetos..
¿La solución en la que estamos trabajando es más mantenible que la que tenemos? Absolutamente. ¿Esto va a funcionar dentro del contexto de WordPress y nuestro complemento existente? No lo sabremos hasta que comencemos a conectar esto a nuestro complemento..
Como se mencionó anteriormente, hay todavía Algunas áreas en las que posiblemente podríamos refactorizar este código. Si detectamos este tipo de problemas al implementar nuestro código en la versión final de nuestro complemento, analizaremos cómo hacerlo exactamente..
En cualquier caso, el código que tenemos ahora debería ser más legible (aunque todavía tenemos DocBlocks y algunos comentarios en línea para introducir) y más mantenibles y aún más verificables.
Con todo lo dicho, espero que esto le haya dado una idea de cómo tomar un método largo y dividirlo en clases más específicas. Claro, tener varias clases puede parecer extraño al principio, pero eso no significa que sea algo malo. Tener más archivos (y, por lo tanto, clases) con menos código que un archivo con mucho código es mejor.
Abrazar la naturaleza contraintuitiva de la programación orientada a objetos en este sentido. En el siguiente tutorial, volveremos a nuestro complemento y trabajaremos en la implementación de una variación del código anterior. Probablemente también estaremos depurando un poco. Después de todo, rara vez lo hacemos bien la primera vez.
Hasta entonces, si está interesado en leer más sobre programación orientada a objetos en el contexto de WordPress, puede encontrar todos mis tutoriales anteriores en mi página de perfil. Siéntase libre de seguir mi en mi blog o sígueme en Twitter, donde frecuentemente hablo de ambos..
Recursos