web-dev-qa-db-ja.com

すべてのプラグインはクラスにカプセル化されるべきですか?

プラグインを開発するとき、名前空間の衝突を避けるために関数はクラスにまとめられるべきですか?

クラスを使用すると、PHPにパフォーマンスのオーバーヘッドが生じますか?

パフォーマンスが低下した場合は、代わりに関数名を単に固定する必要がありますか?

29
Jamie

プラグインを開発するとき、名前空間の衝突を避けるために関数はクラスにまとめられるべきですか?

はい、でもそれは小さな議論の1つにすぎません。実際、それは _ 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を指定すると、名前空間はフックを使用することで停止します。したがって、クラスを使用した名前空間の利点(基本名は1つ)あなたがフック名のためにワードプレスであなたのコードを介入するとき、助けてください。

実際の利点は、実際のクラスインスタンスと非静的関数を使用することから始まります。これには、OOの原則を利用し始めたり、コードを合理化したりできるという利点があります。静的クラス関数は、事実上の解決策よりも問題です。

それからそれは単なる構文上の砂糖以上のものです。

重要なポイントは次のとおりです。簡単に対処および保守できるコードを書くのに役立つ何かをする。パフォーマンスを過大評価しないでください。これはよくある間違いです。もっと重要なのは、読みやすく理解しやすいコードを書くことです。それはあなたが必要とすることをするだけです。たぶん、この質問と答えはこの文脈の中でより大きな絵のために役立ちます: マルチカスタムメタボックスヘルプ

私が小さいプラグインでも持っている一般的なアプローチの1つは、プラグインをインスタンス化するために静的ヘルパー関数を利用することです。そして、残りはプラグインインスタンス内にあります。これはメインのプラグインロジックをカプセル化するのを助けます、そしてそれはフックとの名前空間付けから利益を得ます、そして、プライベートなメンバーはフックの間で再使用されることができます。次のコード例は、パターンを示しています。

<?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全体とやり取りします。

例が示すように、プラグインのインスタンスが作成されます。これにより、 コンストラクタのような既知のコモンを利用することができます。 ドキュメント (__construct 実際のプラグインを初期化する:

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

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

フックが登録された時点で、このプラグインオブジェクトはすでにその設計の恩恵を受けています。具体的なプラグインclassnameに対して実際のフック関数をハードコーディングすることをやめました。これは、コールバックのためにクラスをオブジェクトインスタンスにバインドすることで可能になります。 $thisisプラグインを言っているだけで、複雑そうに聞こえます。フックコールバックで使用でき、 クラスメソッドをフックコールバックとして登録 を比較します。

このパターンはwordpressとのより簡単なインターフェースを可能にします:注入はフックの名前とそれらが提供するデータに減らされます。その後、このプラグインクラスに直接実装するか、またはそれに対して実装をリファクタリングすることで、ワードプレスに対するプラグインインターフェイスを定義するために最低限必要なコードのみをプラグインクラスに含めることができます。これが楽しみの始まりであり、おそらく各プラグインの作者が長期的に達成したいことです。

それで、worpdressでプログラムしないで、それに対して。 worpdressは非常に柔軟であるため、プログラムに対するインターフェースを記述するのが一般的でも簡単でもありません。基本的なプラグインクラスがこの役割を引き受けることができ、あなた自身のコードに対してより高い柔軟性を与えることができ、それはより簡単なコードとより良いパフォーマンスにつながります。

そのため、名前空間には単なる利点以上のものがあります。私が挙げることができる最もよい提案は、次のとおりです。自分で試してください。あなたが失うことは多くない、発見する新しいことだけがある。

プラグインの互換性を維持しながら、WordPressのメジャーアップデートをいくつか渡した後は、おそらく違いに気付くでしょう。

Caveat:仕事を終わらせるためにあなたのプラグインがワードプレスと直接統合されているなら、1つか2つのパブリック関数を使うのがあなたに向いているかもしれません。仕事に適した道具を選びましょう。

25
hakre

クラスVS関数セット


性能

一般:Afaik、クラスと関数セットの間に「パフォーマンス」の違いはありません。

詳細:

  • function_exists() vs. class_exists()に質問すると、通常多くの関数(wpコアで〜1.800(?))とクラス(wpコアで〜100(?))を取得した場合に大きな違いがあります。 。そのため、「プラグ可能」なものを作成し、その存在を疑う実行時間の違いです。
  • クラスには、関数セットに比べて1つbigの利点があります。不要な要求で関数を呼び出す場合、それを呼び出すことを簡単に回避できます。すべての関数ではなく、クラスの条件チェックのみを行う必要があります。したがって、すべてのページの読み込みでそれが必要でなく、多くのif/elseステートメントの呼び出しを回避できる場合、関数は「パフォーマンスが向上」します。

アーキテクチャ-仕組み

関数セット:一般に、関数は呼び出した行で実行されます。そのため、ものを呼び出すたびに、複数回呼び出す必要がある場合は、もう一度書く必要があります。

クラス:クラスにはさまざまなアプローチがあります。関数セットに最も近いクラスは、「factory」クラス( wikipedia /- google )です。 Imoは、一連の関数とほぼ同じですが、クラスにカプセル化されています。しかし、クラスには他の「タイプ」もあります。たとえば、abstractまたは親クラスクラスを記述して、子クラスで拡張できます。実際の例では、いくつかの静的テキストフィールドを作成するクラスがあるとしましょう。 __construct()関数には、「left_column」、「right_column」、「footer_field」などの一連のシナリオがあります。次に、$text_field = new TextFieldClass();のようなものを呼び出して、クラスをインスタンス化します。そして、後で$text_field->add( $case => 'left_column', 'case' => 'foo text' );$text_field->add( $case => 'footer_field', 'case' => 'bar text' );を呼び出すだけです。その後、クラスをインスタンス化したときにすべての条件文と他の条件がすでに実行されており、テキストフィールドを作成するときに2つのクラス関数だけが呼び出されます。このシナリオでは、実行時間を数ミリ秒節約できたはずです。


個人的な意見

クラスを賢く書くと、パフォーマンスにマイナー利点があります。しかし、あなたは取り組むためによく組織された構造を持つでしょう。これまでのところ、見事なものは何もありません。しかし、プラグインのクラスと関数の次の「分割」ユースケースを考慮すると、finalポイントが得られます:Class内部、関数は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>"

注:Qへのコメントに投稿されたリンク@ t310sもお読みください。

9
kaiser

これはプラグインの作者側の純粋にスタイル的な選択です。速度の面で実質的な違いはありません。

4
Otto

クラスは通常、パフォーマンスの面では利点がありませんが、悪影響を及ぼすことはめったにありません。それらの本当の利点はコードをより明確にしそして名前空間の衝突を避けることです。

1
Bainternet

ほとんどの場合、関数を使用する場合は、各関数名にプラグインの名前を入れます。そのため、プラグインに1ダースの関数が含まれている場合、その名前は10回複製されます。 。

クラスの場合は、クラス名にプラグインの名前が1回だけ含まれているはずです。

さらに、継承やその他の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
zeedre