{"id":231620,"date":"2023-01-04T13:23:00","date_gmt":"2023-01-04T10:23:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=231620"},"modified":"2023-01-04T13:24:37","modified_gmt":"2023-01-04T10:24:37","slug":"desacoplamiento-de-la-logica-de-dominio-en-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/desacoplamiento-de-la-logica-de-dominio-en-wordpress\/","title":{"rendered":"Desacoplamiento de la l\u00f3gica de dominio en WordPress"},"content":{"rendered":"\n<p>Recuerda que WordPress usa el <a href=\"https:\/\/en.wikipedia.org\/wiki\/Event-driven_architecture\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">patr\u00f3n de dise\u00f1o dirigido por eventos<\/a> y aunque a menudo nos referimos a acciones y filtros, el concepto se reduce a ganchos. El flujo de control a trav\u00e9s del programa es algo as\u00ed:<\/p>\n<ol>\n<li>Ejecutar el programa,<\/li>\n<li>Cada vez que el programa se encuentra con un gancho (en WordPress, veremos <code>do_action<\/code>o <code>apply_filters<\/code>), itere a trav\u00e9s de todos los ganchos registrados,<\/li>\n<li>Regrese el control al programa,<\/li>\n<li>Ejecutar hasta el final.<\/li>\n<\/ol>\n<p>Esto no es completamente diferente del patr\u00f3n de publicador\/suscriptor (o <a href=\"https:\/\/en.wikipedia.org\/wiki\/Publish%E2%80%93subscribe_pattern\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">PubSub<\/a>, para abreviar), pero hay una diferencia clave: el patr\u00f3n controlado por eventos simplemente indica que algo sucedi\u00f3 y, si hay ganchos, se activar\u00e1n. El Patr\u00f3n PubSub le dir\u00e1 a un suscriptor registrado que haga algo.<\/p>\n<p>De todos modos, volvamos a los ganchos en WordPress. Mantener los dos conceptos de ganchos que tenemos se puede hacer m\u00e1s f\u00e1cilmente si se piensa en ellos de esta manera:<\/p>\n<ul>\n<li>Las acciones son para hacer algo,<\/li>\n<li>Los filtros son para procesar datos.<\/li>\n<\/ul>\n<p>Si est\u00e1 buscando abordar el desarrollo de WordPress de una manera orientada a objetos, no es una buena idea acoplar estrechamente su c\u00f3digo al n\u00facleo de WordPress mediante el registro de sus clases a trav\u00e9s de enlaces a la aplicaci\u00f3n central.<\/p>\n<p>En otras palabras, no registre su l\u00f3gica de negocios con WordPress. Mant\u00e9ngalos separados. Aqu\u00ed hay una prueba de fuego para saber si su trabajo est\u00e1 estrechamente relacionado con WordPress: si no puede ejecutar una prueba unitaria contra su clase sin cargar WordPress, est\u00e1 estrechamente relacionado.<\/p>\n<p>Entonces, \u00bfcu\u00e1l es la soluci\u00f3n? Delegaci\u00f3n.<\/p>\n<h2>L\u00f3gica de dominio en WordPress<\/h2>\n<p>La l\u00f3gica de dominio y la l\u00f3gica de negocios son intercambiables en lo que a m\u00ed respecta, por lo que si ha le\u00eddo publicaciones anteriores sobre esto y he hablado de ellas de diferentes maneras, sabe por qu\u00e9.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-158738-61e6e493ec777.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-158738-61e6e493ec777.png\" alt=\"Desacoplamiento de la l\u00f3gica de dominio en WordPress\"><\/a><\/p>\n<p><a href=\"https:\/\/unsplash.com\/photos\/guiQYiRxkZY\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Cr\u00e9dito<\/a><\/p>\n<p>A continuaci\u00f3n, la idea de delegar la l\u00f3gica de WordPress a una clase para la l\u00f3gica de dominio en WordPress la realiza una clase intermediaria que es responsable de lo siguiente:<\/p>\n<ol>\n<li>Suscribi\u00e9ndote a un gancho,<\/li>\n<li>Delegar el trabajo a una clase.<\/li>\n<\/ol>\n<p>S\u00e9 que se supone que las clases deben hacer &quot;una cosa bien&quot;, pero \u00bfy si esa \u00fanica cosa es la delegaci\u00f3n?<\/p>\n<blockquote>\n<p>comprometer (poderes, funciones, etc.) a otro como agente<\/p>\n<p><a href=\"https:\/\/www.dictionary.com\/browse\/delegate\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">el diccionario<\/a><\/p>\n<\/blockquote>\n<p>Y para asignar correctamente la funcionalidad a otro agente o, en nuestro caso, a una clase, debe tener la capacidad de saber lo que est\u00e1 delegando. A veces, para hacer una cosa necesitas saber varios datos.<\/p>\n<p>Entonces, \u00bfc\u00f3mo se ve esto pr\u00e1cticamente hablando? Imagina que tienes un <code>[AbstractSubscriber](https:\/\/github.com\/tommcfarlin\/remove-empty-shortcodes\/blob\/master\/src\/Subscriber\/AbstractSubscriber.php)<\/code>to tomar\u00e1 el nombre de un gancho en su constructor:<\/p>\n<pre><code>&lt;?php\n\n\/*\n * This file is part of Remove Empty Shortcodes.\n *\n * (c) Tom McFarlin &lt;tom@tommcfarlin.com&gt;\n *\n * This source file is subject to the GPL license that is bundled\n * with this source code in the file LICENSE.\n *\/\n\nnamespace TomMcFarlinRESCSubscriber;\n\nuse TomMcFarlinUtilitiesRegistry;\n\n\/**\n * An abstract implementation of a subscriber that requires a hook and the ability to\n * start the class.\n *\/\nabstract class AbstractSubscriber\n{\n    \/**\n     * @var string a reference to the hook to which the subscriber should be registered\n     *\/\n    protected $hook;\n\n    \/**\n     * @var Registry a reference to the simple container used to maintain plugin objects\n     *\/\n    protected $registry;\n\n    \/**\n     * @param string $hook the hook to which the subscriber is registered\n     *\/\n    public function __construct(string $hook)\n    {\n        $this-&gt;hook = $hook;\n        $this-&gt;registry = apply_filters('rescRegistry', null);\n    }\n\n    \/**\n     * @return string the hook to which the subscriber is registered\n     *\/\n    public function getHook(): string\n    {\n        return $this-&gt;hook;\n    }\n\n    abstract public function load();\n}<\/code><\/pre>\n<p>Y luego, una vez hecho, la <code>load<\/code>funci\u00f3n enviar\u00e1 el trabajo a una clase responsable de realizar el procesamiento.<\/p>\n<p>Tome, por ejemplo, <a href=\"https:\/\/github.com\/tommcfarlin\/remove-empty-shortcodes\/blob\/master\/src\/WordPress\/PostContentProcessor.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">este c\u00f3digo<\/a> de <a href=\"https:\/\/github.com\/tommcfarlin\/remove-empty-shortcodes\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Eliminar c\u00f3digos cortos vac\u00edos<\/a> :<\/p>\n<pre><code>&lt;?php\n\n\/*\n * This file is part of Remove Empty Shortcodes.\n *\n * (c) Tom McFarlin &lt;tom@tommcfarlin.com&gt;\n *\n * This source file is subject to the GPL license that is bundled\n * with this source code in the file LICENSE.\n *\/\n\nnamespace TomMcFarlinRESCWordPress;\n\n\/**\n * Processes the post content by looking to see if any orphaned shortcode\n * exists and then removes it from displaying it from the user.\n *\/\nclass PostContentProcessor\n{\n    \/**\n     * A reference to the Shortcode Manager for processing orphaned shortcodes.\n     *\/\n    private $shortcodeManager;\n\n    \/**\n     * Initializes the class by setting up a reference to the Registry and the\n     * Shortcode Manager.\n     *\/\n    public function __construct()\n    {\n        $registry = apply_filters('rescRegistry', null);\n        $this-&gt;shortcodeManager = $registry-&gt;get('shortcodeManager');\n    }\n\n    \/**\n     * @param string $content the filtered post content\n     *\n     * @return string $content the filtered post content without the shortcode\n     *\/\n    public function run(string $content): string\n    {\n        return $this-&gt;shortcodeManager-&gt;processShortcodes($content);\n    }\n}<\/code><\/pre>\n<p>Una clase se suscribe a un evento en particular, como <code>[the_content](https:\/\/developer.wordpress.org\/reference\/functions\/the_content\/)<\/code>, y luego delega el trabajo a la clase de procesamiento de contenido posterior.<\/p>\n<p>Esto literalmente permite que el archivo de arranque del complemento cree una instancia del delegado. Luego, el delegado se conecta a WordPress y cuando WordPress llega al punto adecuado de ejecuci\u00f3n, el delegado env\u00eda la responsabilidad a la clase responsable de procesarlo.<\/p>\n<p>Toda esta arquitectura no solo es completamente reutilizable (vea el uso de una clase abstracta arriba), sino que nos permite desacoplar la l\u00f3gica del dominio de WordPress y probarla de forma aislada.<\/p>\n<h2>M\u00e1s sobre separaci\u00f3n de preocupaciones<\/h2>\n<p>He escrito algunas otras publicaciones sobre la separaci\u00f3n de preocupaciones:<\/p>\n<ul>\n<li><a href=\"https:\/\/tommcfarlin.com\/separation-of-concerns-with-wordpress-templates\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Separaci\u00f3n de preocupaciones con plantillas de WordPress<\/a><\/li>\n<li><a href=\"https:\/\/tommcfarlin.com\/separation-of-concerns-with-queries-and-helper-functions\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Separaci\u00f3n de preocupaciones con consultas y funciones auxiliares<\/a><\/li>\n<li><a href=\"https:\/\/wordpress.mediadoma.com\/es\/programacion-de-wordpress-preocupaciones-separadas\/\" title=\"Programaci\u00f3n de WordPress: preocupaciones separadas\">Programaci\u00f3n de WordPress: preocupaciones separadas<\/a><\/li>\n<\/ul>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fuente de grabaci\u00f3n:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recuerda que WordPress usa el patr\u00f3n de dise\u00f1o dirigido por eventos y aunque a menudo nos referimos a acciones y filtros, el concepto se reduce a ganchos. El flujo de control a trav\u00e9s del programa va algo&#8230;<\/p>\n","protected":false},"author":1,"featured_media":158739,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[892,716,831,914,840,861],"tags":[1172],"class_list":["post-231620","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo","category-desarrollador","category-guia-para-principiantes","category-otro","category-tutoriales","category-wordpress-2","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/231620","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/comments?post=231620"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/231620\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/158739"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=231620"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=231620"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=231620"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}