webentwicklung-frage-antwort-db.com.de

Sollten alle Plugins in einer Klasse gekapselt sein?

Sollten die Funktionen bei der Entwicklung eines Plugins zu einer Klasse zusammengefasst werden, um Namespace-Konflikte zu vermeiden?

Verursacht die Verwendung von Klassen einen Performance-Overhead für PHP?

Sollten bei einem Leistungstreffer stattdessen nur Funktionsnamen voreingestellt werden?

29
Jamie

Sollten die Funktionen bei der Entwicklung eines Plugins zu einer Klasse zusammengefasst werden, um Namespace-Konflikte zu vermeiden?

Ja, aber das ist nur eines der kleinen Argumente. Tatsächlich ist das nicht die "wahre" Natur einer Klasse in OOAD .

Verursacht die Verwendung von Klassen einen Performance-Overhead für PHP?

Nein, nicht besonders. Schlechtes Design und/oder schlecht geschriebener Code oder vorzeitige Optimierung verursachen weitaus mehr Leistungsprobleme als tatsächliche Sprachfunktionen.

Sollten bei einem Leistungstreffer stattdessen nur Funktionsnamen voreingestellt werden?

Wie geschrieben, gibt es keine Leistungseinbußen. Schlecht geschriebener Code ist eher ein Leistungseinbruch als gut geschriebener Code, der mehr Codezeilen enthält, Sie jedoch nicht zu schlechten Dingen zwingt.


Fazit:

Sie können Klassen für Plugins unterschiedlich nutzen. Sie können sie nur verwenden, um eine Art Namespace zu haben, und sie "nur" für globale Funktionen verwenden. Die direkteste Form davon sind statische Klassenfunktionen. Das folgende Codebeispiel zeigt beide, zuerst globale Funktionen, dann globale statische Klassenfunktionen:

/* 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');

Dies ist nur ein kleines Beispiel, das zeigt, dass Sie mehr für den einzelnen Haken eingeben müssen. Außerdem wird gezeigt, wie der Namespace funktioniert: Sie können den Namen einer einzelnen Klasse einfacher ersetzen, um alle statischen Funktionen umzubenennen, und dann myplug:: suchen und ersetzen, was bei myplug_ aufgrund von False-Positives schwieriger sein könnte. Aber am Ende gibt es keinen großen Unterschied.

Der Schlüsselpunkt ist: statische Klassenfunktionen Docs  sind nicht wirklich viel anderes als globale FunktionenDocs  .

Und dieses Beispiel zeigt auch: Namespacing ist in Ordnung, aber bei worpdress hört der Namespacing bei Verwendung von Hooks auf: Die Rückruffunktion ist fest codiert, daher der Vorteil des Namespacing mit der Klasse (eine Stelle für den Basisnamen, den Klassennamen) nicht Hilfe, wenn Sie Ihren Code mit WordPress für die Hook-Namen eingreifen.

Der eigentliche Vorteil beginnt mit der Verwendung von tatsächlichen Klasseninstanzen und nicht statischen Funktionen. Dies hat den Vorteil, dass Sie anfangen können, OO Prinzipien zu verwenden, und Sie können Ihren Code rationalisieren. Statische Klassenfunktionen sind eher ein Problem als eine Lösung.

Dann ist es mehr als nur syntaktischer Zucker.

Entscheidend ist: Machen Sie etwas, das Ihnen hilft, den Code zu schreiben, mit dem Sie problemlos umgehen und den Sie warten können. Überbewerten Sie die Leistung nicht, das ist ein häufiger Fehler. Wichtiger ist, dass Sie Code schreiben, der einfach zu lesen und zu verstehen ist und der genau das tut, was Sie brauchen. Vielleicht ist diese Frage und Antwort hilfreich für ein größeres Bild in diesem Zusammenhang: Multiple Custom Metabox Help .

Ein gängiger Ansatz, den ich auch bei kleineren Plugins habe, ist die Verwendung einer statischen Hilfsfunktion, um das Plugin zu instanziieren. Der Rest befindet sich dann in der Plugin-Instanz. Dies hilft, die Haupt-Plugin-Logik zu kapseln, und es profitiert vom Namensraum mit den Hooks sowie davon, dass private Mitglieder zwischen Hooks wiederverwendet werden können, was mit globalen Standardfunktionen nicht möglich ist. Das folgende Codebeispiel zeigt das Muster:

<?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;
    }
    # ...
}

Dies ist ein allgemeines Muster, das ich für die Basis-Plugin-Datei verwende. Die Plugin-Klasse repräsentiert zum einen das Plugin für WordPress und ermöglicht es zum anderen, objektorientierte Paradigmen für den eigenen Code zu verwenden, die sogar vollständig objektorientiert sein können (aber nicht müssen). Es ist eine Art Controller, der mit der gesamten WordPress-API als Anfrage (n) verbunden ist.

Wie das Beispiel zeigt, wird eine Instanz des Plugins erstellt. Auf diese Weise können Sie bekannte Commons wie einen Konstruktor verwenden Docs (__construct) um das aktuelle Plugin zu initialisieren:

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

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

Zum Zeitpunkt der Registrierung des Hooks profitiert dieses Plugin-Objekt bereits von seinem Design: Sie haben aufgehört, die eigentliche Hook-Funktion für das konkrete Plugin Klassenname fest zu codieren. Dies ist möglich, weil die Klasse für den Rückruf an die Objektinstanz gebunden ist. Klingt kompliziert, wenn man nur sagt: $thisist das Plugin. Kann in Hook-Rückrufen verwendet werden, vergleiche Klassenmethoden als Hook-Rückrufe registrieren .

Dieses Muster ermöglicht eine einfachere Schnittstelle mit WordPress: Die Injektion wird auf die Namen der Hooks und die von ihnen bereitgestellten Daten reduziert. Sie können dann beginnen, direkt in diese Plugin-Klasse zu implementieren oder Ihre Implementierung dahingehend umzugestalten, dass nur Code in die Plugin-Klasse eingefügt wird, der das absolute Minimum für die Definition der Plugin-Schnittstelle gegen WordPress darstellt. Hier beginnt der Spaß und höchstwahrscheinlich das, was jeder Plugin-Autor auf lange Sicht erreichen möchte.

Also nicht mit Wurmkleid programmieren, sondern dagegen. Da worpdress sehr flexibel ist, gibt es keine gemeinsame oder einfach zu beschreibende Programmierschnittstelle. Eine Basis-Plug-in-Klasse kann diese Rolle übernehmen und bietet Ihnen mehr Flexibilität für Ihren eigenen Code, was zu einfacherem Code und einer besseren Leistung führt.

Es gibt also mehr als nur einen Vorteil für den Namensabstand. Der beste Vorschlag, den ich machen kann, ist: Versuchen Sie es selbst. Es gibt nicht viel zu verlieren, nur Neues zu entdecken.

Sie werden höchstwahrscheinlich Unterschiede bemerken, nachdem Sie einige größere Aktualisierungen von WordPress durchgeführt haben, während Ihr Plugin kompatibel bleibt.

Einschränkung: Wenn Ihr Plugin direkt in WordPress integriert ist, um die Aufgabe zu erledigen, ist es möglicherweise besser, eine oder zwei öffentliche Funktionen zu verwenden. Nehmen Sie das richtige Werkzeug für den Job.

25
hakre

Klassen VS-Funktionssatz


Performance

Allgemein: Afaik, es gibt keinen Unterschied in der "Leistung" zwischen Klassen und Funktionssätzen.

Detail:

  • Es gibt einen großen Unterschied, wenn Sie function_exists() vs. class_exists() fragen, da Sie normalerweise viele Funktionen haben (~ 1.800 (?) Im wp-Kern) vs. Klassen (~ 100 (?) Im wp-Kern). Also Sachen "steckbar" machen und damit die Existenz in Frage stellen istein Unterschied in der Ausführungszeit.
  • Klassen bieten einen bigVorteil gegenüber Funktionssätzen: Sie können es viel einfacher vermeiden, sie bei einer Anfrage aufzurufen, wenn Sie sie nicht benötigen, als mit Funktionen. Sie müssen nur Bedingungsprüfungen für die Klasse und nicht für jede Funktion durchführen Wenn Sie es also nicht bei jedem Seitenaufruf benötigen und nicht viele if/else - Anweisungen aufrufen müssen, ist eine Funktion "leistungsfähiger".

Architektur - So funktioniert's:

Funktionsmenge: Im Allgemeinen werden Funktionen in der von Ihnen aufgerufenen Zeile ausgeführt. Jedes Mal, wenn Sie etwas anrufen, müssen Sie es erneut schreiben, wenn Sie es mehr als einmal aufrufen müssen.

Klasse: Es gibt verschiedene Herangehensweisen an Klassen. Die Klasse, die einem Funktionssatz am nächsten kommt, ist die Klasse "factory" ( wikipedia / google ). Imo es ist fast das gleiche wie eine Reihe von Funktionen, aber in einer Klasse eingekapselt. Es gibt aber auch andere "Arten" von Klassen. Sie könnten zum Beispiel eine abstractoder parent class class schreiben, die Sie mit einer child class erweitern. In einem realen Beispiel: Nehmen wir an, Sie haben eine Klasse, die einige statische Textfelder erstellt. In Ihrer __construct() -Funktion haben Sie Eine Reihe von Szenarien wie "left_column", "right_column" und "footer_field". Dann rufen Sie $text_field = new TextFieldClass(); auf, um die Klasse zu instanziieren. Später rufen Sie einfach $text_field->add( $case => 'left_column', 'case' => 'foo text' ); und $text_field->add( $case => 'footer_field', 'case' => 'bar text' ); auf. Dann wurden alle Ihre Bedingungen und andere bereits ausgeführt, als Sie instanziierten Die Klasse und nur die zwei Klassenfunktionen wären aufgerufen worden, wenn Sie die Textfelder erstellt hätten. In diesem Szenario hätten Sie einige ms Ausführungszeit sparen können.


Persönliche Meinung

Wenn Sie Ihre Klassen mit Bedacht schreiben, haben Sie einen minorVorteil in der Leistung. Aber Sie haben eine gut organisierte Struktur, an der Sie arbeiten können. Bisher nichts Spektakuläres. Aber wenn Sie die folgende "Split" -Verwendung in Betracht ziehen Fälle für Klassen und Funktionen in einem Plugin, dann bekommst du mein finalpoint: Klasse ist intern, Funktionen sind API . Solange du API nur über öffentlich nutzbare Funktionen anbietest (das dann Wenn Sie Klassen oder Klassenfunktionen aufrufen, sind Sie auf der sicheren Seite, wenn Sie Ihr Plugin weiterentwickeln. Sie haben die Freiheit erlangt, die interne Struktur oder sogar die Möglichkeiten Ihres Plugins zu ändern, ohne die Benutzer jederzeit und überall zu beeinflussen.

Beispiel:

// 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>"

Hinweis: Bitte lesen Sie auch den Link @ t310s im Kommentar zum Q.

9
kaiser

Es ist eine rein stilistische Entscheidung des Plugin-Autors. Es gibt keinen wirklichen Geschwindigkeitsunterschied.

4
Otto

Der Unterricht bietet in der Regel keine Vorteile in Bezug auf die Leistung, aber er hat auch nur sehr selten negative Auswirkungen. Ihr eigentlicher Vorteil besteht darin, den Code klarer zu gestalten und Namespace-Konflikte zu vermeiden.

1
Bainternet

Wenn Sie Funktionen verwenden, werden Sie in der Regel den Namen des Plugins in jeden Funktionsnamen einfügen, sodass Sie diesen Namen effektiv ein Dutzend Mal duplizieren werden, wenn das Plugin ein Dutzend Funktionen enthält, was ein bisschen schwierig ist .

Bei Klassen ist der Name des Plugins wahrscheinlich nur einmal im Klassennamen enthalten.

Darüber hinaus können Sie Vererbung oder andere OO-Konstrukte verwenden, um Verhalten auf sehr saubere Weise zu implementieren. Hier ist eine Ex:

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
zeedre