Tüm eklentiler bir Sınıfta saklanmalı mı?


28

Bir eklenti geliştirirken, ad alanı çakışmalarını önlemek için işlevler bir Sınıfta gruplandırılmalı mı?

Sınıfları kullanmak PHP için genel performans giderleri yaratır mı?

Bir performans isabeti varsa, işlev isimleri bunun yerine önceden sabitlenmeli mi?


8
Muhtemelen daha fazla PHP sorusu bir WordPress sorusundan daha fazla, bu Stackoverflow sorusunun sorunuzu uygun bir şekilde ele alıp almadığını kontrol edin.
t31os

Yanıtlar:


24

Bir eklenti geliştirirken, ad alanı çakışmalarını önlemek için işlevler bir Sınıfta gruplandırılmalı mı?

Evet, ama bu sadece küçük argümanlardan biri. Aslında bu, OOAD’daki bir sınıfın “gerçek” doğası değildir .

Sınıfları kullanmak PHP için genel performans giderleri yaratır mı?

Hayır, önemli değil. Kötü tasarım ve / veya kötü yazılı kod veya önceden olgunlaştırılmış optimizasyon, gerçek dil özelliklerinden çok daha fazla performans sorunu yaratır.

Bir performans isabeti varsa, işlev isimleri bunun yerine önceden sabitlenmeli mi?

Yazıldığı gibi, hiçbir performans hedefi yoktur. Kötü yazılı kod, daha fazla kod satırı içeren, ancak sizi kötü şeyler yapmaya zorlamayan iyi yazılı koddan daha fazla performansa neden olur.


Alt çizgi:

Eklentiler için farklı sınıflar kullanabilirsiniz. Onları bir tür isim alanına sahip olmak için kullanabilir ve global fonksiyonlar için "sadece" kullanabilirsiniz. Bunun en doğrudan formu statik sınıf fonksiyonlardır, aşağıdaki kod örneği hem ilk önce genel fonksiyonları, sonra genel statik sınıf fonksiyonlarını gösterir:

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

Bu sadece tek bir kanca için daha fazla yazmanız gerektiğini gösteren küçük bir örnektir. Ek olarak, ad alanının nasıl çalıştığını gösterir: Tüm statik işlevleri yeniden adlandırmak için tek sınıf adını kolayca değiştirebilir ve ardından yanlış pozitifler nedeniyle myplug::zor olabilecek arama ve değiştirme işlemlerini yapabilirsiniz myplug_. Ancak sonunda çok fazla fark yoktur.

Temel nokta şudur: statik sınıf fonksiyonları Dokümanlar gerçekten çok fazla değil, genel fonksiyonlar Dokümanlar .

Ve bu örnekte de gösterilmektedir: İsim boşlukları gayet iyi, ancak başlıklarda isim alanı kancalarla durur: Geri arama işlevi sertleştirilmiştir, bu nedenle sınıfı kullanarak ad alanını kullanmanın yararı (taban adı için bir ad, sınıf adı) Kanca isimleri için kodunuza wordpress ile müdahale ettiğinizde yardımcı olun.

Asıl fayda, gerçek sınıf örnekleri ve statik olmayan işlevler kullanarak başlar. Bu, OO prensiplerinden yararlanmaya başlayabileceğiniz ve kodunuzu düzenleyebileceğiniz bir avantaja sahiptir. Statik sınıf fonksiyonlar, bir çözümden daha çok bir problemdir.

O zaman sözdizimsel şekerden daha fazlası.

Anahtar nokta: Kolayca ilgilenebileceğiniz ve bakımını yapabileceğiniz kodu yazmanıza yardımcı olacak bir şey yapın. Aşırı performans yapma, bu yaygın bir hata. Daha önemlisi, okumak ve anlamak kolay, sadece ihtiyacınız olanı yapan bir kod yazmanızdır. Belki bu soru ve cevap bu bağlamda daha büyük bir resim için yararlıdır : Çoklu Özel Metabox Yardım .

Daha küçük eklentilerde bile olan yaygın bir yaklaşım, eklentiyi başlatmak için statik yardımcı işlevini kullanmaktır ve geri kalanı, eklenti örneği içinde kalır. Bu, ana eklenti mantığını kapsüllemeye yardımcı olur ve kancalarla birlikte ad alanından ve ayrıca özel üyelerin standart global fonksiyonlarla mümkün olmayan kancalar arasında yeniden kullanılabileceğinden yararlanır. Aşağıdaki kod örneği deseni gösterir:

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

Bu temel eklenti dosyası için kullandığım ortak bir kalıptır. Bir yandan eklenti sınıfı, wordpress eklentisini temsil ederken, diğer yandan, tamamen nesne yönelimli olabilen (ancak olması gerekmeyen) kendi kod için nesne yönelimli paradigmalar kullanmaya başlayabiliyor. İstekler olarak tüm wordpress API ile etkileşime giren bir denetleyici.

Örnekte gösterildiği gibi, eklentinin bir örneği oluşturulacaktır. Bu , asıl eklentiyi başlatmak için Yapıcı Belgeler ( __construct) gibi bilinen ortak kullanım alanlarından faydalanmanıza izin verir :

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

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

Kanca kaydedildiğinde, bu eklenti nesnesi zaten tasarımından faydalanır: Asıl kanca işlevini beton eklenti sınıf adına karşı kodlamaktan vazgeçtin . Bu, sınıfın geri çağırma için nesne örneğine bağlanması nedeniyle mümkündür. Sesler karmaşık, sadece söyleyerek: $this bir eklenti. Kanca geri çağırmalarında kullanılabilir, Sınıf Kaydı yöntemlerini kanca geri çağırma olarak karşılaştırın .

Bu kalıp, wordpress ile daha kolay bir arayüz sağlar: enjeksiyon, kancaların isimlerine ve hangi verileri sağladıklarına indirgenir. Daha sonra doğrudan bu eklenti sınıfına uygulamaya başlayabilir veya uygulamanıza karşı yeniden canlandırmaya başlayabilirsiniz, böylece yalnızca eklenti arayüzünüzü wordpress'e karşı tanımlamak için en düşük olan eklenti sınıfına kod koymak, ancak genel mantığını solucanın bir kenara bırakmak için kullanabilirsiniz. Eğlencenin başladığı ve muhtemelen her eklenti yazarının uzun vadede başarmak istediği yer burasıdır.

Öyleyse solucan ile değil, ona karşı program yap. Solucan oldukça esnek olduğundan, programlanacak arayüzü tanımlamak için yaygın veya kolay bir işlem yoktur. Temel eklenti sınıfı bu rolü üstlenebilir ve kendi kodunuz için daha kolay kodlama ve daha iyi performansa yol açacak daha fazla esneklik sunar.

Bu yüzden isim-boşluk için sadece bir faydadan daha fazlası var. Verebileceğim en iyi öneri: Kendini dene. Kaybedeceğiniz pek bir şey yok, sadece keşfedilecek yeni şeyler var.

Eklentinizi uyumlu tutarken bazı daha önemli wordpress güncellemelerini geçtikten sonra muhtemelen farkları göreceksiniz.

Uyarma : Eklentiniz işin yapılması için doğrudan wordpress ile bütünleşirse, bir veya iki ortak işlevi kullanmak size daha uygun olabilir. İş için doğru aleti alın.


1
Statik sınıf fonksiyonlar gerçekten global fonksiyonlardan farklı değilse ve amacınız ad alanını belirleme çatışmalarını önlemekse, eklentileri sınıf olarak yazmaya geçme zorunluluğunu (henüz) anlamadım. Ayrıca, yardımcı önyükleme işlevinizle kafam karıştı. Yeni nesneyi neden $ new_object = new MyClass ();
AlxVallejo

@AlxVallejo: Yalnız adlandırma için, gerçek bir gereklilik yoktur (cevabında yazdığım gibi, statik sınıf metotları global fonksiyonlarla hemen hemen aynıdır). Böylece kendi adınızı yazabilirsiniz (PHP'nin önündeki 5.3 türünde bir isim alanı). Yani bunu doğru bir şekilde fark ettiniz. Statik önyükleme işlevine benzer: Teknik olarak gerekli değildir, basit de return $myPlugin = new MyPlugin(); yapar. Ancak daha büyük resim için, basit bir yeni yeterli olmayabilir , WordPress Eklentisini karşılaştırın : “Sıkı bağlantıdan” nasıl kaçınabilirim? .
hakre

9

Sınıflar VS fonksiyon seti


performans

Genel: Afaik, sınıflar ve fonksiyon setleri arasında "performans" olarak bir fark yoktur.

Detay:

  • Normalde olduğu gibi soru function_exists()sorarsanız büyük bir fark class_exists()var (wp çekirdeğinde ~ 1.800 (?)) Ve sınıflara (wp çekirdeğinde ~ 100 (?)). Varlığını sorgulayan bu nedenle şeyler "takılabilir" yapma ve So olan yürütme zamanında bir fark.
  • Sınıflar , fonksiyon kümelerine göre büyük bir avantaj sunar : İhtiyacınız olmayan bir istek üzerine, sonra işlevlerle çağırmaktan kaçınabilirsiniz. Her fonksiyon için sadece sınıf için şartlı kontroller yapmanız gerekir. Bu nedenle, her sayfa yüklemesinde ihtiyacınız yoksa ve çok sayıda if / else ifadesinin çağrılmasını engelleyebilirseniz, bir işlev "daha iyi sonuç verir".

Mimari - İşler nasıl çalışır:

fonksiyon seti: Genel olarak, çağırdığınız sırada fonksiyonlar yerine gelir. Bu yüzden her aradığınızda, bir kereden fazla aramak zorunda kalırsanız, tekrar yazmak zorundasınız.

Sınıf: Sınıflara farklı yaklaşımlar var. Bir işlev kümesine en yakın gelen sınıf "fabrika" sınıfıdır ( wikipedia / google ). IMO neredeyse bir dizi fonksiyonla aynıdır, ancak bir sınıfta kapsüllenir. Ancak başka sınıf türleri de var. Örneğin , bir alt sınıfa genişlettiğiniz bir özet veya üst sınıf sınıfı yazabilirsiniz . Gerçek bir dünya örneğinde: Diyelim ki bazı statik metin alanları oluşturan bir sınıfınız var. Senin içinde __construct()işlevi siz "left_column", "right_column" & "footer_field" gibi senaryoların bir dizi var. Öyleyse $text_field = new TextFieldClass();dersi başlatmak gibi bir şey diyorsun . Ve sonra sen ara $text_field->add( $case => 'left_column', 'case' => 'foo text' );ve$text_field->add( $case => 'footer_field', 'case' => 'bar text' );. Ardından, tüm koşullarınız ve diğerleri, sınıfı başlattığınızda zaten uygulandı ve metin alanlarını oluştururken yalnızca iki sınıf işlevi çağrılacaktı. Bu senaryoda, birkaç ms yürütme süresi kazanmış olabilirsiniz.


Kişisel görüş

Sınıflarınızı akıllıca yazarsanız , performans konusunda küçük bir avantaja sahip olacaksınız . Ancak üzerinde çalışılacak iyi düzenlenmiş bir yapıya sahip olacaksınız. Şimdiye kadar muhteşem bir şey. Ancak, bir eklentideki sınıflar ve işlevler için aşağıdaki "bölünmüş" kullanım durumlarını göz önünde bulundurursanız, o zaman son noktamı elde edersiniz : Sınıf iç, işlevler API . API'yi yalnızca herkese açık işlevler kullanarak (o zaman sınıfları veya sınıf işlevlerini çağıran) sunduğunuz sürece, eklentinizi daha da geliştiren tasarruf tarafında olacaksınız. Her zaman ve her yerde kullanıcıları etkilemeden iç yapısını, hatta eklentinizin olanaklarını değiştirme özgürlüğüne ulaştınız.

Örnek:

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

Not: Lütfen ayrıca yorumda yayınlanan @ t310s bağlantısını da okuyun.


merak ediyorum, neden eklenti dosyanızın wordpress ile bir defadan daha fazla eklenmesini bekliyorsunuz?
hakre,

@hakre Bunu tam olarak nerede söyledim? Ağlamak, anneme oldukça yorgunum.
kaiser

1
@kaiser, @hakre'nin if( ! class_exists )başlangıçta sahip olduğunuz çizgiden bahsettiğini varsayıyorum ?
jjeaton

1
@hakre @kaiser 'in bir class_existsdefadan fazla eklenebileceğinden değil, başka bir sınıfla çatışmadan kaçınmak için kontrolü yaptığını farz ediyorum ?
Michal Mau

Evet, class_exists hakkında merak ediyordum.
hakre

4

Eklenti yazarı adına tamamen stilistik bir seçim. Hız açısından gerçek bir fark yoktur.


1

Sınıflar genellikle performans açısından bir fayda sağlamaz, ancak nadiren de olumsuz etkileri vardır. Onların asıl yararı, kodu daha açık hale getirmek ve ad alanı çakışmalarından kaçınmaktır.


Bununla birlikte, @hakre'nin dediği gibi, küresel fonksiyonlarda önek kullanılırken ad alanı çakışması gerçekten de farklı değildir. "Temizleyici" kodu ve ad alanı çakışmalarının önlenmesi bu durumda eş anlamlı değil mi?
AlxVallejo

@AlxVallejo sanırım :)
Bainternet

0

İşlevleri kullanırsanız çoğu zaman, her işlev adına eklentinin adını koyarsınız, bu nedenle etkili bir şekilde, eklentinin bir sürükle işlevi olan bir düzine işlevi varsa, bu adı bir düzine kez çoğaltırsınız. .

Sınıflarda, muhtemelen bir kez sınıf adındaki eklentinin adını alırsınız.

Ek olarak, davranışları çok temiz bir şekilde uygulamak için miras veya diğer oo yapıları kullanabilirsiniz. İşte bir eski:

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();
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.