Plugin de WordPress: ¿Cómo puedo evitar "acoplamiento apretado"?


Estoy trabajando en un plugin de WordPress y estoy tratando de garantizar las mejores prácticas. Tengo dos clases, mi clase de plugin " Jargonaut "que se requiere y luego otra clase llamada" Diccionario " que se incluye con require_once() en mi archivo de plugin principal.

La mayor parte del código en la clase Jargonaut aborda la inicialización y proporciona una funcionalidad similar a la del controlador, pero gran parte de ella depende en gran medida del uso del objeto Dictionary (es decir, estrechamente acoplado desde mi comprensión del término). Me deseo mantener la clase de Diccionario separada, ya que está actuando más como un modelo (en arquitectura MVC) e interactúa con mi base de datos.

Veo una gran cantidad de área gris en el acoplamiento apretado vs. suelto y estoy teniendo dificultades para decidir cuánto es demasiado?

Author: Jeremy Harris, 2011-12-31

1 answers

Si tu plugin necesita el objeto dictionary, tiene que pedirlo:

class MyPlugin
{
    /**
     * @var Dictionary
     */
    private $dictionary;
    private function __construct(Dictionary $dictionary)
    {
        $this->dictionary = $dictionary;
    }

Ahora tiene acoplado libremente su plugin con el Dictionary, la clase plugin ya no es responsable de crear el Diccionario por sí misma, porque se inyecta. Toma lo que necesita.

Entonces, ¿cómo funcionaría eso? El plugin necesita ser creado en algún lugar, por lo que esto necesita una fábrica. El método de compilación de fábrica sabe lo que su plugin necesita:

class MyPluginFactory
{
    public static function build($pluginName)
    {
        $plugin = NULL;
        switch($pluginName)
        {
            case 'MyPlugin':
                $dictionary = new Dictionary();
                $plugin = new MyPlugin($dictionary);
        }
        return $plugin;
    }
}

Como esto es wordpress sabemos que la el arranque del plugin se realiza incluyendo el archivo del plugin. Así que al principio, el plugin necesita ser creado. Como incluye se hacen en el ámbito global queremos preservar el objeto plugin en la memoria, pero sin estar disponible como una variable global probablemente. Esto no le impide crear más de una instancia de plugin, pero se asegurará de que cuando wordpress inicialice su plugin (carga su plugin), solo hará uso de esa sola instancia. Esto se puede hacer haciendo la fábrica del plugin alguna función adicional:

class MyPluginFactory
{
    ...
    public static $plugins;
    public static function bootstrap($pluginName)
    {
        $plugin  = self::build($pluginName);
        self::$plugins[] = $plugin;
        return $plugin;
    }

Tenga cuidado aquí, que el único uso de la variable miembro de clase estática es solo para asegurarse de que el plugin permanece en memoria. Técnicamente es una variable global que normalmente queremos evitar, sin embargo, la instancia debe almacenarse en algún lugar, así que aquí está (Cambié esto a público porque es una variable global y no debería ser tímido al respecto. Tener un público puede ayudar en algunas circunstancias en las que privado o protegido son demasiado restrictivos. Tampoco debería ser un problema. Si es un problema, hay otro problema que debe solucionarse primero).

Esto básicamente desacopla el código del plugin de wordpress. Es posible que desee también crear una clase que ofrece e interfaz a cualquier función de Wordpress que está haciendo uso de, por lo que no está vinculado a estas funciones directamente y su código de plugin se mantiene limpio y libremente acoplado a Wordpress sí mismo.

class WordpressSystem
{
    public function registerFilter($name, $plugin, $methodName)
    {
        ... do what this needs with WP, e.g. call the global wordpress function to register a filter.
    }
    ...
}

Luego añádelo como una dependencia de nuevo si su plugin necesita el WordpressSystem para realizar tareas (que normalmente es el caso):

class MyPlugin
{
    ...
    public function __construct(WordpressSystem $wp, Dictionary $dictionary)
    ...

Así que para terminar esto, solo se necesita el archivo php plugin:

<?php
/*
 * MyPlugin
 * 
 * Copyright 2010 by hakre <hakre.wordpress.com>, some rights reserved.
 *
 * Wordpress Plugin Header:
 * 
 *   Plugin Name:    My Plugin
 *   Plugin URI:     http://hakre.wordpress.com/plugins/my-plugin/
 *   Description:    Yet another wordpress plugin, but this time mine
 *   Version:        1.2-beta-2
 *   Stable tag:     1.1
 *   Min WP Version: 2.9
 *   Author:         hakre
 *   Author URI:     http://hakre.wordpress.com/
 *   Donate link:    http://www.prisonradio.org/donate.htm
 *   Tags:           my
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
Namespace MyPlugin;

# if your file is named 'MyPlugin.php' this will be 'MyPlugin'.
return PluginFactory::bootstrap(basename($plugin, '.php'));

class PluginFactory
{
    private static $plugins;
    public static function bootstrap($pluginName)
    {
        $plugin = self::build($pluginName);
        self::$plugins[] = $plugin;
        return $plugin;
    }
    public static function build($pluginName)
    {
        $plugin = NULL;
        switch($pluginName)
        {
            case 'MyPlugin':
                # Make your plugin work with different Wordpress Implementations.
                $system = new System\Wordpress3();
                $dictionary = new Dictionary();
                $plugin = new Plugin($system, $dictionary);
        }
        return $plugin;
    }
}

class Plugin
{
    /**
     * @var System
     */
    private $system;
    /**
     * @var Dictionary
     */
    private $dictionary;
    private function __construct(System $system, Dictionary $dictionary)
    {
        $this->system = $system;
        $this->dictionary = $dictionary;
    }

...

El método bootstrap también puede encargarse de registrar un cargador automático o hacer los requisitos.

Espero que esto sea útil.

 59
Author: hakre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-25 21:32:37