Escribir mejores API y bibliotecas para WordPress

Se siente como que todo lo que tocamos está diseñado cuidadosamente: sitios web, teléfonos, mapas de metro, etc. Incluso las cosas que solíamos dar por sentadas: los termostatos, los detectores de humo y los salpicaderos de los automóviles ahora reciben un tratamiento cuidadoso de la experiencia del usuario.

El diseño no se trata solo de la apariencia: se trata de considerar todas las formas en que un usuario necesita interactuar con nuestro dispositivo / herramienta / pantalla / objeto. 

Esto se aplica a la programación, también.

Programación (des) diseñada

Los lenguajes de programación son mundos grandes y complicados. Incluso PHP, que muchos programadores snobs piensan que es demasiado "fácil", es en realidad una combinación bastante complicada de funciones y clases que se comportan de manera muy inconsistente.. 

La sintaxis, los métodos y los nombres han evolucionado durante muchos años en millones de diferentes usuarios y aplicaciones. La mayoría tiende a reflejar la construcción subyacente de los elementos internos, no necesariamente cómo desea utilizarla.

Grandes momentos en el diseño API: jQuery

Cuando comencé a escribir JavaScript en 2006 o algo así, fue un desastre. Así es como encontraría una etiqueta con una determinada clase y la movería alrededor del DOM en ese entonces:

var uls = getElementsByTagName ("ul"); var classToSearch = "alimentos"; para (var i = 0; i < uls.length; i++)  var classes = uls[i].getClasses(); for (var j = 0; j < classes.length; j++) if (classes[j] == classToSearch) myUL = uls[i];    var $li = document.createElement('li'); $li.innerHTML = 'Steak'; myUL.innerHTML += $li;

Hecho!

jQuery hizo que JavaScript sea divertido otra vez. A fines de la década de 2000, el efecto fue tan dramático que recuerdo que mi padre me preguntó acerca de "algo de jkwery" que leyó en el Wall Street Journal. Pero a pesar de su gran efecto, jQuery no agregó "nuevas características" a JavaScript. Simplemente tomó las cosas que los desarrolladores tenían que hacer y lo dividió en patrones realmente claros..

En lugar de volver a inventar cómo encontrar cosas en la página, aprovecharon lo que la gente ya sabía: los selectores de CSS. Entonces solo era cuestión de recopilar muchas de las acciones comunes y organizarlas en unas pocas docenas de funciones. Probemos nuevamente el ejemplo anterior, ahora con jQuery:

var $ li = $ ('
  • filete
  • '); $ ("ul.foods"). append ($ li);

    En 2006, compré un libro de 680 páginas en Ajax. Con la gran API de jQuery, esto fue reemplazado por esto:

    $ .post ();

    La API de WordPress

    Aunque la API ha llegado a significar "servicio de terceros", simplemente significa la interfaz de programación para hablar con un sistema. Al igual que hay una API de Twitter o una API de Facebook, existe una API de WordPress. No haces consultas de base de datos en bruto para crear una publicación, ¿verdad? Tu usas wp_insert_post.

    Pero muchos agujeros de diseño plagan la API de WordPress. Usted podría utilizar obtener_el_título pero get_the_permalink genera un error, tu usas obtener_permalink. Oye, cuando tienes un proyecto de código abierto de décadas que involucra el código de miles de personas y millones de usuarios: obtendrás algunas peculiaridades.

    Puede ahorrarse mucho tiempo ocultando estos caprichos y escribiendo los hábitos y comportamientos del programador para el que está escribiendo (lo que puede ser ). Aquí es donde puede diseñar la interfaz adecuada para programar los complementos y temas que realiza todos los días..


    La solución

    Para acelerar nuestro trabajo y reducir las tareas repetitivas, he creado bibliotecas para manejar los comandos y las personalizaciones que necesito todo el tiempo..

    1. Atajos para tareas comunes

    Tomemos, por ejemplo, tomando la fuente de la miniatura de una publicación. Resulta que no hay una función de WordPress incorporada para capturar una miniatura basada en la ID de una publicación (solo la adjunto archivo CARNÉ DE IDENTIDAD). 

    Lo que significa que a menudo me encuentro haciendo esto:

    $ thumb_id = get_post_thumbnail_id (get_the_ID ()); $ src = wp_get_attachment_thumb_url ($ thumb_id); eco '';

    Pero tiene que haber una mejor manera.!

    función get_thumbnail_src ($ post) $ thumb_id = get_post_thumbnail_id ($ post); $ src = wp_get_attachment_thumb_url ($ thumb_id); devuelve $ src;  eco '';

    2: Entradas impredecibles, salida predecible

    ¡Mucho mejor! De hecho, se encuentra usándolo todo el tiempo y luego compartiéndolo con otros desarrolladores de su empresa.. 

    Tu amigo está teniendo problemas con eso, por lo que te llama a depurar y verás:

    eco '';

    Así que parece que lo usó accidentalmente get_post en lugar de get_the_ID. Le gritas a él. Pero espera un segundo, Por qué no hazlo mas aceptando? 

    Tal vez podamos ajustar nuestra función para que pueda tomar una WP_Post Objeto y aún le da al usuario lo que está esperando. Volvamos a esa función:

    function get_thumbnail_src ($ post) if (is_object ($ post) && isset ($ post-> ID)) $ post = $ post-> ID;  else if (is_array ($ post) && isset ($ post ['ID'))) $ post = $ post ['ID'];  $ thumb_id = get_post_thumbnail_id ($ post); $ src = wp_get_attachment_thumb_url ($ thumb_id); devuelve $ src; 

    Así que si envían un WP_Post objeto o En una matriz, su función seguirá ayudándoles a obtener lo que necesitan. Esta es una gran parte de una API exitosa: esconder las agallas desordenadas. Podrías hacer funciones separadas para get_thumbnail_src_by_post_id y get_thumbnail_src_by_wp_post_object. 

    De hecho, para transformaciones más complicadas puede ser preferible, pero puede simplificar la interfaz teniendo una ruta de función única a la subrutina correcta. No importa lo que el usuario envíe, la función siempre devuelve una cadena para la fuente de la imagen. 

    Sigamos adelante: ¿Y si lo mandan? nada?

    3. Valores predeterminados sensibles

    función get_thumbnail_src ($ post = false) if (false === $ post) $ post = get_the_ID ();  else if (is_object ($ post) && isset ($ post-> ID)) $ post = $ post-> ID;  else if (is_array ($ post) && isset ($ post ['ID'))) $ post = $ post ['ID'];  $ thumb_id = get_post_thumbnail_id ($ post); $ src = wp_get_attachment_thumb_url ($ thumb_id); devuelve $ src; 

    Hemos simplificado una vez más para que el usuario no tenga que enviar una publicación. o incluso una identificación de correo. Cuando en el bucle, todo lo que se necesita es:

    eco '';

    Nuestra función irá por defecto a la ID de la publicación actual. Esto se está convirtiendo en una función realmente valiosa. Para asegurarnos de que esto funcione bien, envolvámoslo dentro de una clase para que no contamine el espacio de nombres global.

    / * Nombre del complemento: JaredTools Descripción: Mi caja de herramientas para temas de WordPress. Autor: Jared Novack Versión: 0.1 Autor URI: http://upstatement.com/ * / class JaredsTools función estática pública get_thumbnail_src ($ post = false) if (false === $ post) $ post = get_the_ID () ;  else if (is_object ($ post) && isset ($ post-> ID)) $ post = $ post-> ID;  else if (is_array ($ post) && isset ($ post ['ID'))) $ post = $ post ['ID'];  $ thumb_id = get_post_thumbnail_id ($ post); $ src = wp_get_attachment_thumb_url ($ thumb_id); devuelve $ src; 

    Y Por favor no prefijas tu clase con WP. Estoy convirtiendo esto en una función estática pública porque quiero que esté accesible en todas partes, y no cambia: la entrada o la ejecución no cambian la función o el objeto. 

    La llamada final a esta función es:

    eco '';

    Diseño primero, construir más tarde

    Pasemos a una necesidad más complicada. Cuando escribo complementos, siempre tengo que generar diferentes tipos de errores y / o actualizar mensajes. 

    Pero la sintaxis basada en eventos siempre me ha molestado:

    add_action ('admin_notices', 'show_my_notice'); functon show_my_notice () echo '

    Tu cosa ha sido actualizada

    ';

    Hay muchas buenas razones por las que WordPress sigue esta arquitectura basada en eventos. Pero no es intuitivo, a menos que desee sentarse y memorizar diferentes filtros y acciones. 

    Hagamos que coincida con el caso de uso más simple: necesito mostrar un aviso de administrador. Me gusta diseñar esta API primero: donde descubro la mejor manera de referirme a la función en mi código. Me gustaría leer así:

    función thing_that_happens_in_my_plugin ($ post_id, $ value) $ updated = update_post_meta ($ post_id, $ value); if ($ updated) JaredsTools :: show_admin_notice ("Tu cosa se ha actualizado") else JaredsTools :: show_admin_notice ("Error al actualizar tu cosa", "error"); 

    Una vez que tengo el punto final diseñado, puedo cumplir con el requisito de diseño:

    class JaredsTools public static function show_admin_notice ($ message, $ class = 'updated') add_action ('admin_notices', function () use ($ message, $ class) echo '

    '. $ mensaje'.

    '; );

    ¡Mucho mejor! Ahora no necesito crear todas estas funciones adicionales o recordar nombres de ganchos locos. Aquí estoy usando funciones anónimas de PHP (también llamadas "cierres") que nos permiten vincular una función directamente a una acción o filtro. 

    Esto le evita tener un montón de funciones adicionales flotando alrededor de sus archivos. los utilizar comando nos permite pasar argumentos de la función principal al cierre secundario.

    Ser intuitivo

    Ahora otro compañero de trabajo te llama. Ella no sabe por qué su aviso de administrador no se está poniendo rojo:

    JaredsTools :: show_admin_notice ("Error al actualizar tu cosa", "rojo");

    Es porque ella está enviando "rojo" (lo que ella esperaría que la caja se pusiera roja) cuando en realidad debería estar enviando el nombre de la clase ese desencadena rojo. Pero ¿por qué no hacerlo más fácil??

    función estática pública show_notice ($ message, $ class = 'updated') $ class = trim (strtolower ($ class)); if ('yellow' == $ class) $ class = 'updated';  if ('red' == $ class) $ class = 'error';  add_action ('admin_notices', function () use ($ text, $ class) echo '

    '. $ texto. '

    '; );

    Ahora hemos aceptado una mayor tolerancia del usuario que hará que sea más fácil de compartir y para nosotros cuando volvamos a usarlo dentro de unos meses..


    Conclusión

    Después de construir una serie de estos, aquí están algunos de los principios que he aprendido para hacer que estos sean realmente útiles para mi equipo y para mí..

    1. Diseñe primero y deje que la construcción de la función coincida con la forma en que la gente quiere usarla.
    2. Guarde su teclado! Hacer atajos para tareas comunes..
    3. Proporcionar valores predeterminados razonables.
    4. Sea mínimo. Deja que tu biblioteca se encargue del procesamiento..
    5. Perdona en la entrada, pero precisa en la salida.
    6. Dicho uso utiliza la menor cantidad posible de argumentos de función, cuatro es un buen máximo. Después de eso, deberías convertirlo en una matriz de opciones..
    7. Organice su biblioteca en clases separadas para cubrir diferentes áreas (administrador, imágenes, publicaciones personalizadas, etc.).
    8. Documento con código de ejemplo..

    En Upstatement, nuestras bibliotecas para Timber facilitan la creación de temas y Jigsaw proporciona accesos directos que ahorran tiempo para personalizar cada instalación.

    El ahorro de tiempo que proporcionan estas herramientas nos permite dedicar más tiempo a la creación de las partes nuevas e innovadoras de cada sitio o aplicación. Al tomar los comandos que de otra manera son esotéricos (como agregar una columna a las tablas de correos de administración) y crear interfaces simples: cualquier diseñador o desarrollador de nuestra empresa puede personalizar completamente cada sitio con el mismo poder que un desarrollador de WordPress profesional..