ปลั๊กอินทั้งหมดควรถูกห่อหุ้มในคลาสหรือไม่?


28

เมื่อมีการพัฒนาปลั๊กอินควรมีการจัดกลุ่มฟังก์ชั่นเข้าด้วยกันเป็น Class เพื่อหลีกเลี่ยงความขัดแย้งของ namespace หรือไม่?

การใช้คลาสสร้างค่าใช้จ่ายด้านประสิทธิภาพสำหรับ PHP หรือไม่

หากมีการเข้าชมประสิทธิภาพชื่อฟังก์ชันควรได้รับการแก้ไขล่วงหน้าแทนหรือไม่


8
อาจมีคำถาม PHP มากกว่า WordPress หนึ่งดูว่าคำถาม Stackoverflow นี้ตอบคำถามของคุณอย่างเหมาะสมหรือไม่
t31os

คำตอบ:


24

เมื่อมีการพัฒนาปลั๊กอินควรมีการจัดกลุ่มฟังก์ชั่นเข้าด้วยกันเป็น Class เพื่อหลีกเลี่ยงความขัดแย้งของ namespace หรือไม่?

ใช่ แต่นั่นเป็นเพียงหนึ่งในข้อโต้แย้งเล็กน้อย ในความเป็นจริงที่ไม่ธรรมชาติ "จริง" ของชั้นใน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_เนื่องจากผลบวกปลอม แต่ในท้ายที่สุดก็ไม่แตกต่างกันมาก

จุดสำคัญคือระดับคงที่ฟังก์ชั่นเอกสารไม่ได้จริงๆมากอื่นแล้วฟังก์ชั่นระดับโลกเอกสาร

และตัวอย่างนี้แสดงให้เห็นเช่นกัน: Namespacing นั้นใช้ได้ แต่ด้วย worpdress การกำหนด namespaces จะหยุดด้วยการใช้ hooks: ฟังก์ชันการโทรกลับจะถูกเข้ารหัสยากดังนั้นประโยชน์ในการกำหนดเส้นทางโดยใช้คลาส (ที่เดียวสำหรับชื่อฐาน, classname) ไม่ ช่วยเมื่อคุณแทรกแซงรหัสด้วย wordpress สำหรับชื่อเบ็ด

ประโยชน์ที่แท้จริงเริ่มต้นด้วยการใช้อินสแตนซ์ของคลาสจริงและฟังก์ชันที่ไม่คงที่ สิ่งนี้มีประโยชน์ที่คุณสามารถเริ่มใช้หลักการ OO และคุณสามารถปรับปรุงรหัสของคุณ ฟังก์ชั่นคลาสแบบสแตติกนั้นมีปัญหามากกว่าทางแก้ปัญหา

แล้วมันเป็นมากกว่าแค่น้ำตาลทราย

จุดสำคัญคือทำสิ่งที่ช่วยให้คุณเขียนรหัสที่คุณสามารถจัดการและดูแลรักษาได้ง่าย อย่าให้คะแนนมากเกินไปนั่นเป็นข้อผิดพลาดทั่วไป ที่สำคัญกว่านั้นคือคุณเขียนโค้ดที่อ่านและเข้าใจได้ง่ายนั่นเป็นสิ่งที่คุณต้องการ บางทีคำถามและคำตอบนี้อาจมีประโยชน์สำหรับรูปภาพขนาดใหญ่ในบริบทนี้: วิธีใช้ Metabox แบบกำหนดเองหลายรายการ

วิธีการทั่วไปหนึ่งที่ฉันมีแม้จะมีปลั๊กอินขนาดเล็กก็คือการใช้ฟังก์ชั่นตัวช่วยแบบคงที่เพื่อยกตัวอย่างปลั๊กอินและส่วนที่เหลืออยู่ในอินสแตนซ์ปลั๊กอินแล้ว สิ่งนี้ช่วยในการสรุปแค็ปซูลลอจิกหลักและได้รับประโยชน์จากการตั้งชื่อด้วย hooks และสมาชิกส่วนตัวสามารถนำกลับมาใช้ใหม่ได้ระหว่าง hooks ซึ่งไม่สามารถทำได้ด้วยฟังก์ชั่นมาตรฐานระดับโลก ตัวอย่างโค้ดต่อไปนี้แสดงรูปแบบ:

<?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 และในทางกลับกันจะช่วยให้เริ่มใช้กระบวนทัศน์เชิงวัตถุสำหรับรหัสของตัวเองซึ่งสามารถแม้กระทั่งวัตถุที่มุ่งเน้นอย่างสมบูรณ์ (แต่ไม่จำเป็นต้อง) มันเป็นคอนโทรลเลอร์ที่เชื่อมต่อกับ wordpress API ทั้งหมดตามที่ร้องขอ

ดังตัวอย่างที่แสดงอินสแตนซ์ของปลั๊กอินจะถูกสร้างขึ้น วิธีนี้ช่วยให้คุณสามารถใช้งานคอมมอนส์ที่รู้จักกันดีเช่นConstructor Docs ( __construct)เพื่อเริ่มต้นปลั๊กอินจริง:

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

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

ในขณะที่เบ็ดมีการลงทะเบียนวัตถุปลั๊กอินนี้แล้วผลประโยชน์จากมันออกแบบ: คุณได้หยุดที่จะยากรหัสฟังก์ชั่นที่เกิดขึ้นจริงกับเบ็ดปลั๊กอินคอนกรีตClassName เป็นไปได้เนื่องจากการเชื่อมโยงคลาสกับอินสแตนซ์วัตถุสำหรับการโทรกลับ ฟังดูซับซ้อนแค่บอกว่า: $this เป็นปลั๊กอิน สามารถนำมาใช้ในการเรียกกลับเบ็ดเปรียบเทียบวิธีการลงทะเบียนชั้นเป็นเรียกกลับเบ็ด

รูปแบบนี้ช่วยให้สามารถเชื่อมต่อกับ wordpress ได้ง่ายขึ้น: การฉีดลดลงไปยังชื่อ hooks และข้อมูลที่ให้ จากนั้นคุณสามารถเริ่มนำไปใช้โดยตรงในคลาสปลั๊กอินนี้หรือเพื่อปรับโครงสร้างการใช้งานของคุณอีกครั้งดังนั้นการใส่โค้ดลงในคลาสปลั๊กอินที่น้อยที่สุดในการกำหนดอินเทอร์เฟซปลั๊กอินของคุณกับเวิร์ดเพรส นี่คือที่ที่ความสนุกเริ่มต้นและส่วนใหญ่อาจเป็นสิ่งที่ผู้เขียนปลั๊กอินแต่ละคนต้องการที่จะประสบความสำเร็จในระยะยาว

ดังนั้นอย่าตั้งโปรแกรมด้วย worpdress แต่ขัดกับมัน เนื่องจาก worpdress นั้นค่อนข้างยืดหยุ่นจึงไม่มีคำอธิบายทั่วไปหรืออินเตอร์เฟสที่ใช้อธิบายโปรแกรมได้ง่ายนัก คลาสปลั๊กอินพื้นฐานสามารถทำหน้าที่นี้ช่วยให้คุณมีความยืดหยุ่นมากขึ้นสำหรับโค้ดของคุณเองซึ่งจะนำไปสู่โค้ดที่ง่ายขึ้นและประสิทธิภาพที่ดีขึ้น

ดังนั้นมีมากกว่าประโยชน์สำหรับการเว้นวรรคชื่อ ข้อเสนอแนะที่ดีที่สุดที่ฉันสามารถให้คือลองตัวคุณเอง มีไม่มากที่คุณจะสูญเสียเพียงสิ่งใหม่ที่จะค้นพบ

คุณอาจสังเกตเห็นความแตกต่างหลังจากที่คุณผ่านการอัปเดตที่สำคัญมากขึ้นของ wordpress ในขณะที่ทำให้ปลั๊กอินของคุณเข้ากันได้

Caveat : หากปลั๊กอินของคุณทำงานร่วมกับ wordpress โดยตรงเพื่อให้งานสำเร็จการใช้ฟังก์ชันสาธารณะหนึ่งหรือสองฟังก์ชั่นอาจเหมาะกับคุณมากกว่า ใช้เครื่องมือที่เหมาะสมสำหรับงาน


1
หากฟังก์ชั่นคลาสสแตติกไม่ได้แตกต่างจากฟังก์ชั่นทั่วโลกและวัตถุประสงค์ของคุณคือเพื่อป้องกันความขัดแย้งของการกำหนดเนมฉันไม่เข้าใจถึงความจำเป็น (ยัง) เพื่อสลับไปยังการเขียนปลั๊กอินเป็นคลาส นอกจากนี้ฉันสับสนกับฟังก์ชั่น bootstrap ผู้ช่วยของคุณ ทำไมไม่เพียงแค่ประกาศวัตถุใหม่เป็น $ new_object = new MyClass () ;?
AlxVallejo

@AlxVallejo: สำหรับ namespacing คนเดียวไม่มีความจำเป็นจริง (อย่างที่ฉันเขียนไว้ในคำตอบวิธีการเรียนแบบคงที่มีความคล้ายคลึงกับฟังก์ชั่นทั่วโลก) ดังนั้นคุณสามารถทำ namespacing ของคุณเอง (ก่อน PHP 5.3 ประเภทของ namespacing นั่นคือ) ดังนั้นคุณสังเกตเห็นว่าถูกต้องสมบูรณ์ คล้ายกันกับฟังก์ชั่นแบบคงที่บูต: ทางเทคนิคแล้วมันไม่จำเป็นที่เรียบง่ายreturn $myPlugin = new MyPlugin(); ไม่ได้เช่นกัน อย่างไรก็ตามสำหรับภาพที่ใหญ่ขึ้นอาจดูไม่ง่ายนักเปรียบเทียบปลั๊กอิน WordPress ใหม่: ฉันจะหลีกเลี่ยง“ การมีเพศสัมพันธ์อย่างแน่นหนา” ได้อย่างไร? .
hakre

9

ชุดฟังก์ชัน VS คลาส


ประสิทธิภาพ

ทั่วไป: Afaik ไม่มีความแตกต่างใน "ประสิทธิภาพ" ระหว่างคลาสและชุดฟังก์ชัน

รายละเอียด:

  • มีความแตกต่างใหญ่ถ้าคุณถามfunction_exists()กับclass_exists()ตามปกติคุณมีฟังก์ชันมากมาย (~ 1.800 (?) ใน wp core) กับคลาส (~ 100 (?) ใน wp core) ดังนั้นการทำสิ่งที่ "เสียบได้" และการตั้งคำถามจึงมีความแตกต่างในเวลาดำเนินการ
  • ชั้นเรียนมีข้อได้เปรียบที่สำคัญอย่างหนึ่งต่อชุดฟังก์ชั่น: คุณสามารถหลีกเลี่ยงได้ง่ายกว่าในการเรียกร้องตามคำขอที่คุณไม่ต้องการใช้กับฟังก์ชั่น คุณจะต้องทำการตรวจสอบตามเงื่อนไขสำหรับชั้นเรียนเท่านั้นและไม่ใช่สำหรับทุกฟังก์ชั่น ดังนั้นหากคุณไม่ต้องการใช้มันในการโหลดหน้าเว็บทุกครั้งและสามารถหลีกเลี่ยงการเรียกใช้คำสั่ง if / else จำนวนมากฟังก์ชั่น "ทำงานได้ดีขึ้น"

สถาปัตยกรรม - วิธีการทำงานของสิ่งต่าง ๆ :

ชุดฟังก์ชั่น:โดยทั่วไปฟังก์ชั่นได้รับการดำเนินการในแถวที่คุณเรียกว่า ดังนั้นทุกครั้งที่คุณโทรหาสิ่งที่คุณต้องเขียนอีกครั้งถ้าคุณต้องเรียกมันมากกว่าหนึ่งครั้ง

ชั้น:มีปัญหาต่าง ๆ ในการเรียน คลาสที่ใกล้เคียงกับชุดฟังก์ชั่นมากที่สุดคือคลาส "factory" ( 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' );. จากนั้นเงื่อนไขทั้งหมดของคุณและอื่น ๆ ได้รับการดำเนินการแล้วเมื่อคุณสร้างอินสแตนซ์ของชั้นเรียนและมีเพียงแค่สองฟังก์ชันคลาสเท่านั้นที่จะถูกเรียกใช้เมื่อคุณสร้างฟิลด์ข้อความ ใน szenario นี้คุณสามารถบันทึกมิลลิวินาทีของเวลาในการดำเนินการ


ความเห็นส่วนตัว

ถ้าคุณเขียนชั้นเรียนของคุณอย่างชาญฉลาดแล้วคุณจะมีเล็ก ๆ น้อย ๆได้เปรียบในการปฏิบัติงาน แต่คุณจะมีโครงสร้างที่ดีในการทำงาน จนถึงตอนนี้ไม่มีอะไรที่น่าตื่นเต้น แต่ถ้าคุณพิจารณาต่อไป "แยก" กรณีการใช้งานสำหรับการเรียนและการทำงานในปลั๊กอินแล้วคุณจะได้รับของฉันสุดท้ายจุด: คลาสภายในฟังก์ชั่น 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>"

หมายเหตุ: โปรดอ่านลิงค์ @ t310s ที่โพสต์ในความคิดเห็นต่อคำถาม


แค่อยากรู้ว่าทำไมคุณถึงคาดหวังว่าไฟล์ปลั๊กอินของคุณจะรวมอยู่ใน wordpress มากกว่าหนึ่งครั้ง
hakre

@hakre ฉันพูดแบบนี้ที่ไหน แม่เหนื่อยมากเลย
ไกเซอร์

1
@kaiser ฉันคิดว่า @hakre กำลังอ้างถึงif( ! class_exists )บรรทัดที่คุณมีตอนเริ่มต้นใช่ไหม
jjeaton

1
@ ฮาเครฉันคิดว่า @kaiser กำลังทำclass_existsเช็คไม่ใช่เพราะมันสามารถรวมได้มากกว่าหนึ่งครั้ง แต่เพื่อหลีกเลี่ยงความขัดแย้งกับคลาสอื่น?
Michal Mau

ใช่ฉันสงสัยเกี่ยวกับ class_exists
hakre

4

มันเป็นตัวเลือกโวหารอย่างหมดจดในส่วนของผู้เขียนปลั๊กอิน ไม่มีความแตกต่างที่แท้จริงในแง่ของความเร็ว


1

คลาสมักจะไม่ให้ประโยชน์ใด ๆ ในแง่ของประสิทธิภาพ แต่ก็ไม่ค่อยมีผลเสียเช่นกัน ประโยชน์ที่แท้จริงของพวกเขาคือการทำให้โค้ดชัดเจนขึ้นและหลีกเลี่ยงความขัดแย้งของเนมสเปซ


แต่ตามที่ @hakre กล่าวถึงความขัดแย้งของ namespace นั้นไม่แตกต่างกันมากนักเมื่อใช้ส่วนนำหน้าในฟังก์ชั่นระดับโลก โค้ด "Cleaner" และการป้องกันเนมสเปซขัดแย้งกันในกรณีนี้ใช่ไหม
AlxVallejo

@AlxVallejo ฉันเดาว่า :)
Bainternet

0

ส่วนใหญ่ถ้าคุณใช้ฟังก์ชั่นคุณจะใส่ชื่อปลั๊กอินในแต่ละชื่อฟังก์ชั่นอย่างมีประสิทธิภาพคุณจะทำซ้ำชื่อนั้นเป็นสิบครั้งถ้าปลั๊กอินมีฟังก์ชั่นโหลซึ่งเป็นการลาก .

ด้วยคลาสคุณเพียงแค่มีชื่อปลั๊กอินในชื่อคลาสที่น่าจะเป็นหนึ่งครั้ง

นอกจากนี้คุณสามารถใช้การสืบทอดหรือการสร้าง 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.