Должны ли все плагины быть инкапсулированы в класс?


При разработке плагина следует ли группировать функции в класс, чтобы избежать конфликтов пространств имен?

Создает ли использование классов накладные расходы на производительность PHP?

Если есть снижение производительности, следует ли вместо этого предварительно фиксировать имена функций?

Author: Jamie, 2011-08-17

5 answers

При разработке плагина следует ли группировать функции в класс, чтобы избежать конфликтов пространств имен?

Да, но это только один из второстепенных аргументов. На самом деле это не "истинная" природа класса в OOAD.

Создает ли использование классов накладные расходы на производительность PHP?

Нет, не особенно. Плохой дизайн и/или плохо написанный код или преждевременная оптимизация создают гораздо больше проблем с производительностью, чем фактические языковые особенности.

Если есть снижение производительности, следует ли вместо этого предварительно фиксировать имена функций?

Как написано, никакого снижения производительности нет. Плохо написанный код будет в большей степени снижать производительность, чем хорошо написанный код, который содержит еще несколько строк кода, но не заставляет вас делать плохие вещи.


Итог:

Вы можете по-разному использовать классы для плагинов. Вы можете просто использовать их, чтобы иметь какое-то пространство имен и использовать их "просто" для глобальных функций. Наиболее прямой формой этого являются функции статического класса, в следующем примере кода показаны обе, сначала глобальные функции, затем глобальные функции статического класса:

/* global function */
function myplug_hook()
{
}

add_filter('the_hook', 'myplug_hook');


/* global static function */
class myplug
{
    public static function hook()
    {
    }
}

add_filter('the_hook', 'myplug::hook');

Это всего лишь небольшой пример, показывающий, что вам нужно ввести больше для одного крючка. Кроме того, он показывает, как работает пространство имен: вы можете проще заменить одно имя класса, чтобы переименовать все статические функции, а затем выполнить поиск и заменить myplug::, что может быть сложнее с myplug_ из-за ложные срабатывания. Но в конце концов особой разницы нет.

Ключевым моментом является: статические функции класса Документы на самом деле это не что иное, как глобальные функции Документы.

И этот пример также показывает: Пространство имен в порядке, но в worpdress пространство имен останавливается с использованием крючков: функция обратного вызова жестко закодирована, следовательно, преимущество в пространстве имен с использованием класса (одно место для базового имени, имя класса) не помогает, когда вы вводите свой код в wordpress для имен крючков.

Реальная выгода начинается с использования реальных экземпляров классов и нестатических функций. Это имеет то преимущество, что вы можете начать использовать принципы OO и оптимизировать свой код. Статические функции класса - это скорее проблема, чем решение.

Тогда это больше, чем просто синтаксический сахар.

Ключевой момент: Сделайте что-нибудь, что поможет вам написать код, который вы можете легко разбираться и поддерживать. Не переоценивайте производительность, это распространенная ошибка. Более важно, чтобы вы писали код, который легко читается и понимается, который просто делает то, что вам нужно. Возможно, этот вопрос и ответ полезны для более широкой картины в этом контексте: Справка по нескольким Пользовательским Метабоксам.

Один из распространенных подходов, который я использую даже с небольшими плагинами, заключается в использовании статической вспомогательной функции для создания экземпляра плагина, а остальное находится в экземпляре плагина тогда. Это помогает инкапсулировать основную логику плагина и извлекает выгоду из пространства имен с помощью крючков, а также из того, что частные члены могут быть повторно использованы между крючками, что невозможно при использовании стандартных глобальных функций. Следующий пример кода показывает шаблон:

<?php
/** Plugin Headers ... */

return MyPlugin::bootstrap(); 

class MyPlugin
{
    /** @var MyPlugin */
    static $instance;
    static public function bootstrap() {
        if (NULL === self::$instance) {
            self::$instance = new __CLASS__;
        }
        return self::$instance;
    }
    # ...
}

Это общий шаблон, который я использую для базового файла плагина. Класс плагина, с одной стороны, представляет плагин для wordpress, а с другой стороны, позволяет начать использовать объектно-ориентированные парадигмы для собственного кода который даже может быть полностью объектно-ориентированным (но не обязательно). Это своего рода контроллер, взаимодействующий со всем API wordpress в качестве запроса(запросов).

Как показано в примере, будет создан экземпляр плагина. Это позволяет вам использовать известные общие ресурсы, такие как конструктор Документы (__construct) чтобы инициализировать фактический плагин:

# ...
class MyPlugin
{
    # ...
    public function __construct()
    {
        add_filter('the_hook', array($this, 'hook'));
    }

    public function hook()
    {
    }
    # ...
}

На момент регистрации крючка этот объект плагина уже выигрывает от своего дизайна: вы прекратили чтобы жестко запрограммировать фактическую функцию привязки к конкретному плагину имя класса . Это возможно из-за привязки класса к экземпляру объекта для обратного вызова. Звучит сложно, просто говорю: $this является плагином. Может использоваться в обратных вызовах, сравните Регистрация методов класса в качестве обратных вызовов.

Этот шаблон позволяет упростить интерфейс с wordpress: ввод сводится к именам крючков и данным, которые они обеспечивать. Затем вы можете приступить к реализации непосредственно в этом классе плагинов или к рефакторингу своей реализации по отношению к нему, чтобы поместить код только в класс плагинов, который является минимальным для определения интерфейса ваших плагинов в wordpress, но оставьте общую логику в стороне от worpdress. Здесь начинается самое интересное, и, скорее всего, это то, чего каждый автор плагина хочет достичь в долгосрочной перспективе.

Так что программируйте не с помощью worpdress, а против него. Поскольку worpdress довольно гибкий, существует нет общего или простого в описании интерфейса для программирования. Базовый класс плагинов может взять на себя эту роль, предоставляя вам больше гибкости для вашего собственного кода, что приведет к упрощению кода и повышению производительности.

Таким образом, есть нечто большее, чем просто преимущество для интервалов между именами. Лучшее предложение, которое я могу дать, это: Попробуйте сами. Вы мало что потеряете, только новые вещи, которые нужно открыть.

Вы, скорее всего, заметите различия после того, как пройдете еще несколько крупных обновлений wordpress, в то время как поддержание совместимости вашего плагина.

Предостережение: Если ваш плагин напрямую интегрируется с wordpress для выполнения работы, использование одной или двух общедоступных функций может подойти вам лучше. Возьмите подходящий инструмент для этой работы.

 24
Author: hakre, 2017-04-13 12:37:52

Классы ПРОТИВ набора функций


Производительность

Общие сведения: Afaik, нет никакой разницы в "производительности" между классами и наборами функций.

Деталь:

  • Есть большая разница, если вы зададите вопрос function_exists() по сравнению с class_exists(), поскольку обычно у вас много функций (~1.800(?) в ядре wp) по сравнению с классами (~100(?) в ядре wp). Таким образом, создание материала "подключаемого" и, следовательно, сомнение в существовании - это разница в время выполнения.
  • Классы предлагают одно большое преимущество перед наборами функций: вам гораздо проще избежать вызова его по запросу, когда он вам не нужен, а затем с помощью функций. Вам нужно выполнять только условные проверки для класса, а не для каждой функции. Поэтому, если вам это не нужно при каждой загрузке страницы и вы можете избежать вызова множества операторов if/else, функция "работает лучше".

Архитектура - Как все работает:

Набор функций: В в общем, функции выполняются в строке, которую вы называете. Поэтому каждый раз, когда вы звоните, вам приходится писать это снова, если вам приходится звонить больше одного раза.

Класс: Существуют разные подходы к классам. Класс, наиболее близкий к набору функций, - это класс "фабрика" (википедия/ google). Имо это почти то же самое, что набор функций, но инкапсулированный в класс. Но есть и другие "типы" классов. Вы могли бы, например, написать абстрактный или класс родительского класса, который вы расширяете с помощью дочернего класса. В реальном примере: Допустим, у вас есть класс, который создает некоторые статические текстовые поля. В вашей функции __construct() у вас есть набор сценариев, таких как "левый столбец", "правый столбец" и "поле нижнего колонтитула". Затем вы вызываете что-то вроде $text_field = new TextFieldClass(); для создания экземпляра класса. А позже вы просто вызываете $text_field->add( $case => 'left_column', 'case' => 'foo text' ); и $text_field->add( $case => 'footer_field', 'case' => 'bar text' );. Затем все ваши условные обозначения и все остальное уже были выполнены, когда вы создали экземпляр класса и только два класса функции должны были бы вызываться при создании текстовых полей. В этом случае вы могли бы сэкономить несколько мс времени выполнения.


Личное мнение

Если вы будете писать свои классы с умом, то у вас будет незначительное преимущество в производительности. Но у вас будет хорошо организованная структура для работы. Пока ничего впечатляющего. Но если вы рассмотрите следующие "разделенные" варианты использования классов и функций в плагине, то вы получите мой окончательный пункт: Класс является внутренним, функции являются API. Пока вы предлагаете API только через общедоступные функции (которые затем вызывают классы или функции классов), вы будете на стороне сохранения, продолжая разрабатывать свой плагин. Вы получили свободу изменять внутреннюю структуру или даже возможности вашего плагина, не затрагивая пользователей в любое время и везде.

Пример:

// construction of object
if ( ! class_exists( 'WPSE_HelloWorld' ) )
{

class WPSE_HelloWorld
{
    function __construct( $args = array( 'text', 'html', 'echo' ) )
    {
        // call your object building procedures here
        $this->hello_world( 'text', 'html', 'echo' );
    }

    function hello_world( 'text', 'html', 'echo' )
    {
        $start_el = '<{$html}>';
        $end_el = '</{$html}>';
        if ( $echo )
        {
            return print "{$start_el}{$some}{$end_el}";
        }

        return "{$start_el}{$some}{$end_el}";
    }
} // END Class 

}

// API: public functions
function the_hello_world( $args( 'echo' => true ) )
{
    $new = new WPSE_HelloWorld();
    return $new->hello_world( $args );
}

function get_hello_world( array( $args( 'echo' => false) ) )
{
    $new = new WPSE_HelloWorld();
    return $new->hello_world( $args );
}

// then you can call it like get_the_title() or the_title(), which you know from the WP API:
// 'echo' is set to false per default:
$some_var = get_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *returns* "<strong>hello reader</strong>"

// 'echo' is set to true per default:
the_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *prints/echos* "<strong>hello reader</strong>"

Примечание: Пожалуйста, также прочитайте ссылку @t310s, размещенную в комментарии к В.

 9
Author: kaiser, 2011-08-18 01:37:33

Это чисто стилистический выбор автора плагина. Нет никакой реальной разницы в скорости.

 4
Author: Otto, 2011-08-17 22:06:02

Классы обычно не дают никаких преимуществ с точки зрения производительности, но они также очень редко оказывают какое-либо негативное влияние. Их реальное преимущество заключается в том, чтобы сделать код более понятным и избежать конфликтов пространств имен.

 1
Author: Bainternet, 2011-08-17 21:56:31

В большинстве случаев, если вы используете функции, вы будете указывать имя плагина в имени каждой функции, так что эффективно вы будете дублировать это имя дюжину раз, если у плагина есть дюжина функций, что немного утомительно.

С классами у вас просто будет имя плагина в имени класса, скорее всего, один раз.

Кроме того, вы можете использовать наследование или другие конструкции oo для очень чистой реализации поведения. Вот пример:

class animalplugin{
  //plugin functions...
  function talk(){print "animalnoise";}
}
class animalplugin_with_cat_mods extends abcplugin{
  //cat functions overrides
  function talk(){print "meow";}
}
if (iscat()){
  new animalplugin_with_cat_mods();
} else {
  new animalplugin();
}
 0
Author: zeedre, 2013-02-07 14:31:05