すべてのプラグインをクラスにカプセル化する必要がありますか?


28

プラグインを開発するとき、名前空間の競合を避けるために、関数をクラスにグループ化する必要がありますか?

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

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


8
おそらく、WordPressの質問よりもPHPの質問の方が多いでしょう。このStackoverflowの質問があなたの質問に適切に対応しているかどうかを確認してください。
t31os

回答:


24

プラグインを開発するとき、名前空間の競合を避けるために、関数をクラスにグループ化する必要がありますか?

はい、しかしそれはマイナーな議論の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');

これは、1つのフックにさらに入力する必要があることを示すほんの一例です。さらに、名前空間がどのように機能するかを示します。単一のクラス名を簡単に置き換えて、すべての静的関数の名前を変更し、誤検出のためにmyplug::困難な検索と置換を行うことができますmyplug_。しかし、最終的には大きな違いはありません。

重要な点は次のとおりです。静的クラス関数Docsは、グローバル関数Docs以外の実際にはありません。

この例も示しています:Namespacingは問題ありませんが、worpdressを使用すると、フックの使用で名前空間が停止します。コールバック関数はハードエンコードされているため、クラス(base-nameの1つの場所)フック名のワードプレスでコードに介入するときに役立ちます。

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

そして、それは単なる構文糖以上のものです。

重要な点は次のとおりです。簡単に処理および保守できるコードを記述するのに役立つ何かをします。パフォーマンスを過大評価しないでください。これはよくある間違いです。さらに重要なのは、読みやすく理解しやすいコードを書くことで、必要なことだけを行うということです。たぶん、この質問と回答は、このコンテキストでの全体像に役立つでしょう:Multiple Custom Metabox Help

小さいプラグインでも私が持っている一般的なアプローチの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全体とインターフェースします。

例が示すように、プラグインのインスタンスが作成されます。これにより、Constructor Docs__constructなどの既知のコモンを使用して、実際のプラグインを初期化できます。

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

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

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

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

したがって、worpdressを使用してプログラミングするのではなく、それに反対します。worpdressは非常に柔軟であるため、プログラムに対して一般的または簡単に説明できるインターフェイスはありません。基本プラグインクラスがこの役割を引き受けることができるため、独自のコードの柔軟性が高まり、コードが簡単になり、パフォーマンスが向上します。

そのため、名前の間隔だけでなく、利点もあります。私が与えることができる最もよい提案は次のとおりです。あなたが失うことはそれほど多くなく、発見するのは新しいことだけです。

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

警告:プラグインがwordpressと直接統合されて仕事を成し遂げる場合、1つまたは2つのパブリック関数を使用する方が適している場合があります。仕事に最適なツールを選択してください。


1
静的クラス関数がグローバル関数と実際に違いがなく、あなたの目的が名前空間の競合を防ぐことである場合、クラスとしてプラグインの作成に切り替える必要性(まだ)を理解していません。また、ヘルパーブートストラップ機能に混乱しています。なぜ新しいオブジェクトを$ new_object = new MyClass();として宣言しないのですか?
AlxVallejo

@AlxVallejo:名前空間だけでは、真の必要性はありません(答えで書いたように、静的クラスメソッドはグローバル関数とほとんど同じです)。したがって、独自の名前空間を作成できます(PHP 5.3以前の名前空間)。あなたはそれが完全に正しいことに気づきました。静的なブートストラップ機能と同様:技術的には必要ありませんが、単純なreturn $myPlugin = new MyPlugin(); ものも同様です。ただし、全体像としては、単純な新しいものでは不十分な場合があります。WordPressプラグインを比較してください。「密結合」を回避するにはどうすればよいですか?
-hakre

9

クラスVS関数セット


性能

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

詳細:

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

アーキテクチャ-仕組み

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

クラス:クラスにはさまざまなアプローチがあります。関数セットに最も近いクラスは「ファクトリー」クラス(wikipedia / google)です。Imoは、一連の関数とほぼ同じですが、クラスにカプセル化されています。しかし、クラスには他の「タイプ」もあります。たとえば、抽象クラスまたは親クラスを記述して、子クラスで拡張できます。実際の例では、いくつかの静的テキストフィールドを構築するクラスがあるとしましょう。あなたでは__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つのクラス関数だけが呼び出されます。このシナリオでは、実行時間を数ミリ秒節約できました。


個人的な意見

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


好奇心が強いのですが、なぜプラグインファイルがwordpressに複数回含まれることを期待しますか?
ハクレ

@hakreどこで正確に言ったの?おかあさん、お母さんにかなり疲れた。
カイザー

1
@ kaiser、@ hakreはif( ! class_exists )あなたが最初に持っている行を指していると思いますか?
ジートン

1
@hakre @kaiserがclass_existsチェックを行うのは、それが複数回含まれる可能性があるからではなく、別のクラスとの競合を避けるためだと思いますか?
ミカルマウ

はい、class_existsについて疑問に思っていました。
-hakre

4

プラグインの作成者が純粋に文体的に選択します。速度の面で実際の違いはありません。


1

通常、クラスはパフォーマンスの面で利点を提供しませんが、いずれかのマイナス効果をもたらすことはほとんどありません。それらの本当の利点は、コードをより明確にし、名前空間の競合を回避することです。


しかし、@ hakreが言及したように、グローバル関数で接頭辞を使用する場合、名前空間の競合は実際に違いはありません。この場合、「よりクリーンな」コードと名前空間の競合の防止は同義語です。
AlxVallejo

@AlxVallejoそうだと思う:)
Bainternet

0

ほとんどの場合、関数を使用する場合は、各関数名にプラグインの名前を入力します。そのため、プラグインに1ダースの関数が数十個ある場合、その名前を何十回も複製します。 。

クラスの場合、クラス名にプラグインの名前が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();
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.