Haruskah semua plugin dienkapsulasi dalam Kelas?

28

Ketika mengembangkan sebuah plugin haruskah fungsi dikelompokkan bersama menjadi suatu Kelas untuk menghindari konflik namespace?

Apakah menggunakan kelas membuat overhead kinerja untuk PHP?

Jika ada hit kinerja, haruskah nama fungsi hanya diperbaiki sebelumnya?

Jamie
sumber
8
Mungkin lebih banyak pertanyaan PHP daripada WordPress, lihat apakah pertanyaan Stackoverflow ini sesuai dengan pertanyaan Anda.
t31os

Jawaban:

24

Ketika mengembangkan sebuah plugin haruskah fungsi dikelompokkan bersama menjadi suatu Kelas untuk menghindari konflik namespace?

Ya, tapi itu hanya salah satu argumen kecil. Sebenarnya itu bukan sifat "benar" dari kelas di OOAD .

Apakah menggunakan kelas membuat overhead kinerja untuk PHP?

Tidak, terutama. Desain yang buruk dan / atau kode tertulis yang buruk atau optimasi pra-matang menciptakan masalah kinerja yang jauh lebih banyak daripada fitur bahasa yang sebenarnya.

Jika ada hit kinerja, haruskah nama fungsi hanya diperbaiki sebelumnya?

Seperti yang ditulis, tidak ada hit kinerja. Kode tertulis yang buruk akan lebih menjadi hit kinerja daripada kode tertulis yang baik yang memiliki beberapa baris kode tetapi tidak memaksa Anda untuk melakukan hal-hal buruk.


Intinya:

Anda dapat menggunakan kelas dengan berbeda untuk plugin. Anda bisa menggunakannya untuk memiliki semacam namespace dan menggunakannya "hanya" untuk fungsi global. Bentuk paling langsung dari itu adalah fungsi kelas statis, contoh kode berikut menunjukkan keduanya, fungsi global pertama, kemudian fungsi kelas statis global:

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

Ini hanyalah sedikit contoh yang menunjukkan bahwa Anda perlu mengetik lebih banyak untuk pengait tunggal. Selain itu itu menunjukkan bagaimana ruang nama bekerja: Anda dapat lebih mudah mengganti nama kelas tunggal untuk mengubah nama semua fungsi statis dan kemudian mencari dan mengganti myplug::yang bisa lebih sulit dengan myplug_karena kesalahan positif. Namun pada akhirnya tidak ada banyak perbedaan.

Kuncinya adalah: fungsi kelas statis Documents tidak terlalu banyak selain fungsi global Documents .

Dan contoh ini juga menunjukkan: Namespacing baik-baik saja, tetapi dengan worpdress, namespacing berhenti menggunakan kait: Fungsi callback di-hardencode, karenanya manfaat dalam namespacing menggunakan kelas (satu tempat untuk nama-dasar, nama kelas) tidak membantu ketika Anda mengintervensi kode Anda dengan wordpress untuk nama hook.

Manfaat sebenarnya dimulai dengan menggunakan instance kelas aktual dan fungsi non-statis. Ini memiliki keuntungan bahwa Anda dapat mulai menggunakan prinsip-prinsip OO dan Anda dapat merampingkan kode Anda. Fungsi kelas statis lebih merupakan masalah daripada solusi infact.

Maka itu lebih dari sekedar gula sintaksis.

Poin utamanya adalah: Lakukan sesuatu yang membantu Anda menulis kode yang dapat Anda tangani dan pelihara dengan mudah. Jangan menilai terlalu tinggi, itu kesalahan umum. Yang lebih penting adalah Anda menulis kode yang mudah dibaca dan dipahami, hanya melakukan apa yang Anda butuhkan. Mungkin pertanyaan dan jawaban ini bermanfaat untuk gambaran yang lebih besar dalam konteks ini: Beberapa Bantuan Metabox Kustom .

Salah satu pendekatan umum yang saya miliki bahkan dengan plugin yang lebih kecil adalah menggunakan fungsi pembantu statis untuk instantiate plugin dan sisanya berada dalam instance plugin itu. Ini membantu untuk merangkum logika plugin utama dan manfaat dari penamaan namespace dengan kait juga bahwa anggota pribadi dapat digunakan kembali antara kait yang tidak mungkin dengan fungsi global standar. Contoh kode berikut menunjukkan polanya:

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

Ini adalah pola umum yang saya gunakan untuk file plugin dasar. Kelas plugin di satu sisi mewakili plugin untuk wordpress dan di sisi lain memungkinkan untuk mulai menggunakan paradigma berorientasi objek untuk kode sendiri yang bahkan dapat sepenuhnya berorientasi objek (tetapi tidak harus). Ini semacam pengontrol, berinteraksi dengan seluruh API wordpress sebagai permintaan.

Seperti yang ditunjukkan oleh contoh, sebuah instance dari plugin akan dibuat. Ini memungkinkan Anda untuk menggunakan milik umum yang dikenal seperti Constructor Docs ( __construct) untuk menginisialisasi plugin yang sebenarnya:

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

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

Pada saat hook terdaftar, objek plugin ini sudah mendapatkan manfaat dari desainnya: Anda telah berhenti melakukan hard-code pada fungsi hook aktual terhadap classname plugin beton . Itu mungkin karena pengikatan kelas ke objek contoh untuk panggilan balik. Kedengarannya rumit, hanya mengatakan: $this adalah plugin. Dapat digunakan dalam hookbackback, bandingkan metode Kelas Pendaftaran sebagai hookbackback .

Pola ini memungkinkan antarmuka yang lebih mudah dengan wordpress: injeksi direduksi menjadi nama kait dan data apa yang disediakannya. Anda kemudian dapat mulai mengimplementasikan langsung ke kelas plugin ini atau untuk menolak implementasi Anda terhadapnya, jadi untuk hanya memasukkan kode ke dalam kelas plugin yang merupakan batas minimum untuk mendefinisikan antarmuka plugin Anda terhadap wordpress, tetapi simpan logika umum di samping worpdress. Di sinilah kesenangan dimulai dan kemungkinan besar apa yang ingin dicapai oleh setiap pembuat plugin dalam jangka panjang.

Jadi jangan memprogram dengan worpdress tetapi menentangnya. Karena worpdress cukup fleksibel, tidak ada antarmuka yang umum atau mudah untuk dideskripsikan. Kelas plugin dasar dapat mengambil peran ini, memungkinkan Anda lebih fleksibel untuk kode Anda sendiri yang akan mengarah pada kode yang lebih mudah dan kinerja yang lebih baik.

Jadi ada lebih dari sekedar manfaat untuk penamaan nama. Saran terbaik yang bisa saya berikan adalah: Coba sendiri. Tidak banyak yang akan Anda lepas, hanya hal-hal baru yang bisa ditemukan.

Kemungkinan besar Anda akan melihat perbedaan setelah melewati beberapa pembaruan wordpress yang lebih penting sambil menjaga plugin Anda tetap kompatibel.

Peringatan : Jika plugin Anda terintegrasi langsung dengan wordpress untuk menyelesaikan pekerjaan, menggunakan satu atau dua fungsi publik mungkin lebih cocok untuk Anda. Ambil alat yang tepat untuk pekerjaan itu.

hakre
sumber
1
Jika fungsi kelas statis benar-benar tidak berbeda dengan fungsi global, dan tujuan Anda adalah untuk mencegah konflik penentuan nama, saya benar-benar belum memahami perlunya (belum) beralih ke menulis plugin sebagai kelas. Juga, saya bingung dengan fungsi bootstrap pembantu Anda. Mengapa tidak mendeklarasikan objek baru sebagai $ new_object = new MyClass () ;?
AlxVallejo
@AlxVallejo: Untuk namespacing saja, tidak ada keharusan yang sebenarnya (seperti yang saya tulis dalam jawaban, metode kelas statis hampir sama dengan fungsi global). Jadi Anda dapat melakukan namespacing Anda sendiri (pra PHP 5.3 jenis namespacing itu). Jadi Anda perhatikan itu benar sekali. Mirip dengan fungsi bootstrap statis: Secara teknis tidak perlu, sederhana return $myPlugin = new MyPlugin(); juga. Namun untuk gambar yang lebih besar, baru yang sederhana mungkin tidak cukup, bandingkan Plugin WordPress: Bagaimana cara menghindari "kopling ketat"? .
hakre
9

Kelas mengatur fungsi VS


Performa

Umum: Afaik, tidak ada perbedaan dalam "kinerja" antara kelas dan set fungsi.

Detail:

  • Ada perbedaan besar jika Anda bertanya function_exists()vs. class_exists()seperti biasanya Anda mendapat banyak fungsi (~ 1.800 (?) Di wp core) vs kelas (~ 100 (?) Di wp core). Jadi membuat barang-barang "pluggable" dan mempertanyakan keberadaannya adalah perbedaan dalam waktu eksekusi.
  • Kelas menawarkan satu keuntungan besar dibandingkan set fungsi: Anda dapat lebih mudah menghindari menyebutnya dengan permintaan di mana Anda tidak membutuhkannya, lalu dengan fungsi. Anda hanya perlu melakukan pemeriksaan bersyarat untuk kelas dan bukan untuk setiap fungsi. Jadi jika Anda tidak membutuhkannya di setiap halaman memuat dan dapat menghindari memanggil banyak pernyataan if / else, fungsi "berkinerja lebih baik".

Arsitektur - Cara kerja barang:

set fungsi: Secara umum, fungsi dijalankan di baris yang Anda sebut itu. Jadi setiap kali Anda menelepon barang, Anda harus menulisnya lagi, jika Anda harus menyebutnya lebih dari sekali.

Kelas: Ada perbedaan pendekatan dengan kelas. Kelas yang paling dekat dengan kumpulan fungsi adalah kelas "pabrik" ( wikipedia / google ). Imo itu hampir sama dengan seperangkat fungsi, tetapi dikemas dalam suatu kelas. Tetapi ada "tipe" kelas lain juga. Misalnya, Anda bisa menulis abstrak atau kelas kelas induk, yang diperluas dengan kelas anak. Dalam contoh dunia nyata: Katakanlah Anda memiliki kelas yang membangun beberapa bidang teks statis. Dalam __construct()fungsi Anda, Anda memiliki serangkaian skenario seperti "left_column", "right_column" & "footer_field". Kemudian Anda memanggil sesuatu $text_field = new TextFieldClass();untuk membuat instance kelas. Dan nanti Anda cukup menelepon $text_field->add( $case => 'left_column', 'case' => 'foo text' );dan$text_field->add( $case => 'footer_field', 'case' => 'bar text' );. Kemudian semua kondisi Anda dan yang lain telah dilakukan ketika Anda membuat instance kelas dan hanya dua fungsi kelas yang akan dipanggil ketika Anda membangun bidang teks. Dalam szenario ini Anda bisa menghemat waktu eksekusi ms.


Opini pribadi

Jika Anda menulis kelas dengan bijak, maka Anda akan memiliki sedikit keuntungan dalam kinerja. Tetapi Anda akan memiliki struktur yang terorganisir dengan baik untuk dikerjakan. Sejauh ini tidak ada yang spektakuler. Tetapi jika Anda mempertimbangkan "menggunakan" kasus penggunaan berikut untuk kelas dan fungsi dalam sebuah plugin, maka Anda akan mendapatkan poin terakhir saya : Kelas internal, fungsi adalah API . Selama Anda menawarkan API hanya melalui fungsi yang dapat digunakan untuk umum (yang kemudian memanggil kelas atau fungsi kelas), Anda akan berada di sisi yang aman mengembangkan plugin Anda lebih lanjut. Anda memperoleh kebebasan untuk mengubah struktur internal atau bahkan kemungkinan plugin Anda tanpa memengaruhi pengguna kapan saja dan di mana saja.

Contoh:

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

Catatan: Harap baca juga tautan @ t310 yang diposting dalam komentar ke Q.

kaisar
sumber
hanya ingin tahu, mengapa Anda berharap file plugin Anda dimasukkan lebih dari sekali dengan wordpress?
hakre
@ Habre Di mana tepatnya saya mengatakan ini? sry, sangat lelah pada ibu.
kaiser
1
@kaiser, saya berasumsi @hakre mengacu pada if( ! class_exists )baris yang Anda miliki di awal?
jjeaton
1
@hakre Saya berasumsi @kaiser sedang melakukan class_existspemeriksaan bukan karena itu bisa dimasukkan lebih dari sekali tetapi untuk menghindari konflik dengan kelas lain?
Michal Mau
Ya saya bertanya-tanya tentang class_exists.
hakre
4

Ini adalah pilihan gaya murni pada bagian dari pembuat plugin. Tidak ada perbedaan nyata dalam hal kecepatan.

Otto
sumber
1

Kelas biasanya tidak menawarkan manfaat dalam hal kinerja, tetapi mereka juga jarang memiliki efek negatif. Manfaat nyata mereka adalah membuat kode lebih jelas dan menghindari konflik namespace.

Bainternet
sumber
Namun, seperti yang disebutkan @hakre, konflik namespace benar-benar tidak berbeda ketika menggunakan awalan pada fungsi global. Kode "bersih" dan mencegah konflik namespace identik dalam hal ini, bukan?
AlxVallejo
@AlxVallejo kurasa begitu :)
Bainternet
0

Sebagian besar waktu, jika Anda menggunakan fungsi, Anda akan meletakkan nama plugin di setiap nama fungsi, sehingga secara efektif, Anda akan menduplikat nama itu selusin kali jika plugin memiliki selusin fungsi yang sedikit membosankan. .

Dengan kelas, Anda hanya akan memiliki nama plugin di nama kelas kemungkinan sekali.

Selain itu, Anda dapat menggunakan warisan atau konstruksi lainnya untuk menerapkan perilaku dengan cara yang sangat bersih. Berikut ini adalah mantan:

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();
}
Zeedre
sumber