Tất cả các plugin có nên được gói gọn trong một Class không?


28

Khi phát triển một plugin, các chức năng có nên được nhóm lại thành một Class để tránh xung đột không gian tên?

Việc sử dụng các lớp tạo ra chi phí hiệu năng cho PHP?

Nếu có một lần nhấn hiệu năng, các tên hàm chỉ nên được sửa trước?


8
Có lẽ nhiều câu hỏi PHP hơn một câu hỏi WordPress, hãy xem câu hỏi Stackoverflow này có phù hợp với câu hỏi của bạn không.
t31os

Câu trả lời:


24

Khi phát triển một plugin, các chức năng có nên được nhóm lại thành một Class để tránh xung đột không gian tên?

Vâng, nhưng đó chỉ là một trong những tranh luận nhỏ. Thực tế đó không phải là bản chất "thực sự" của một lớp trong OOAD .

Việc sử dụng các lớp tạo ra chi phí hiệu năng cho PHP?

Không, đáng chú ý. Thiết kế xấu và / hoặc mã viết xấu hoặc tối ưu hóa trước khi trưởng thành tạo ra nhiều vấn đề về hiệu năng hơn nhiều so với các tính năng ngôn ngữ thực tế.

Nếu có một lần nhấn hiệu năng, các tên hàm chỉ nên được sửa trước?

Như đã viết, không có hiệu suất hit. Mã viết xấu sẽ ảnh hưởng nhiều đến hiệu suất hơn mã viết tốt có nhiều dòng mã hơn nhưng không bắt bạn phải làm điều xấu.


Dòng dưới cùng:

Bạn có thể sử dụng các lớp khác nhau cho các plugin. Bạn chỉ có thể sử dụng chúng để có một số loại không gian tên và sử dụng chúng "chỉ" cho các chức năng toàn cầu. Dạng trực tiếp nhất đó là các hàm lớp tĩnh, ví dụ mã sau đây cho thấy cả hai hàm toàn cầu đầu tiên, sau đó là các hàm lớp tĩnh toàn cầu:

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

Đây chỉ là một ví dụ nhỏ cho thấy rằng bạn cần gõ nhiều hơn cho hook đơn. Ngoài ra, nó còn cho thấy cách hoạt động của không gian tên: Bạn có thể dễ dàng thay thế tên lớp đơn để đổi tên tất cả các hàm tĩnh và sau đó tìm kiếm và thay thế myplug::có thể khó hơn myplug_vì dương tính giả. Nhưng cuối cùng không có nhiều khác biệt.

Điểm mấu chốt là: các hàm lớp tĩnh Tài liệu không thực sự khác nhiều so với các hàm toàn cầu Docs .

Và ví dụ này cũng cho thấy: Không gian tên là tốt, nhưng với worpdress, không gian tên dừng lại bằng cách sử dụng hook: Hàm gọi lại được mã hóa cứng, do đó, lợi ích trong việc đặt tên bằng cách sử dụng lớp (một vị trí cho tên cơ sở, tên lớp) không giúp đỡ khi bạn can thiệp mã của bạn bằng wordpress cho tên hook.

Lợi ích thực sự bắt đầu bằng việc sử dụng các thể hiện lớp thực tế và các hàm không tĩnh. Điều này có lợi ích là bạn có thể bắt đầu sử dụng các nguyên tắc OO và bạn có thể hợp lý hóa mã của mình. Các hàm lớp tĩnh là một vấn đề hơn là một giải pháp nguyên vẹn.

Sau đó, nó không chỉ là đường cú pháp.

Điểm mấu chốt là: Làm điều gì đó giúp bạn viết mã mà bạn có thể dễ dàng xử lý và duy trì. Đừng đánh giá quá cao, đó là một lỗi phổ biến. Quan trọng hơn là bạn viết mã dễ đọc và dễ hiểu, chỉ cần làm những gì bạn cần. Có thể câu hỏi và câu trả lời này hữu ích cho một bức tranh lớn hơn trong bối cảnh này: Nhiều trợ giúp về Metabox tùy chỉnh .

Một cách tiếp cận phổ biến mà tôi có ngay cả với các plugin nhỏ hơn là sử dụng hàm trợ giúp tĩnh để khởi tạo plugin và phần còn lại nằm trong phiên bản plugin sau đó. Điều này giúp đóng gói logic plugin chính và nó có lợi từ việc đặt tên với các hook cũng như các thành viên riêng có thể được sử dụng lại giữa các hook không thể thực hiện được với các hàm toàn cầu tiêu chuẩn. Ví dụ mã sau đây cho thấy mẫu:

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

Đây là một mẫu phổ biến tôi sử dụng cho tệp plugin cơ sở. Lớp plugin một mặt đại diện cho plugin cho wordpress và mặt khác, nó cho phép bắt đầu sử dụng các mô hình hướng đối tượng cho mã riêng, thậm chí có thể hoàn toàn hướng đối tượng (nhưng không cần phải). Đó là một loại bộ điều khiển, giao tiếp với toàn bộ API wordpress như (các) yêu cầu.

Như ví dụ cho thấy, một phiên bản của plugin sẽ được tạo. Điều này cho phép bạn sử dụng các dấu phẩy đã biết như Tài liệu xây dựng ( )__construct để khởi tạo plugin thực tế:

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

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

Tại thời điểm hook được đăng ký, đối tượng plugin này đã được hưởng lợi từ thiết kế của nó: Bạn đã ngừng mã hóa chức năng hook thực tế đối với tên lớp plugin cụ thể . Điều đó có thể là do sự ràng buộc của lớp với thể hiện đối tượng cho cuộc gọi lại. Nghe có vẻ phức tạp, chỉ cần nói: $this plugin. Có thể được sử dụng trong các cuộc gọi lại hook, so sánh các phương thức Đăng ký lớp như các cuộc gọi lại hook .

Mẫu này cho phép giao diện dễ dàng hơn với wordpress: tiêm được giảm xuống tên của hook và dữ liệu họ cung cấp. Sau đó, bạn có thể bắt đầu triển khai trực tiếp vào lớp plugin này hoặc để cấu trúc lại việc triển khai của mình với nó, do đó, chỉ đưa mã vào lớp plugin tối thiểu để xác định giao diện plugin của bạn chống lại wordpress, nhưng hãy bỏ logic chung sang một bên. Đây là nơi niềm vui bắt đầu và có lẽ là điều mà mỗi tác giả plugin muốn đạt được trong thời gian dài.

Vì vậy, đừng lập trình với worpdress mà chống lại nó. Vì worpdress khá linh hoạt, không có giao diện phổ biến hoặc dễ mô tả để lập trình chống lại. Một lớp plugin cơ sở có thể đảm nhận vai trò này, cho phép bạn linh hoạt hơn cho mã của riêng mình, điều này sẽ dẫn đến mã dễ dàng hơn và hiệu suất tốt hơn.

Vì vậy, có nhiều hơn chỉ là một lợi ích cho khoảng cách tên. Gợi ý tốt nhất tôi có thể đưa ra là: Hãy thử bản thân. Bạn sẽ không mất nhiều thứ, chỉ có những điều mới để khám phá.

Rất có thể bạn sẽ nhận thấy sự khác biệt sau khi bạn đã vượt qua một số cập nhật lớn hơn của wordpress trong khi vẫn giữ cho plugin của bạn tương thích.

Hãy cẩn thận : Nếu plugin của bạn tích hợp trực tiếp với wordpress để hoàn thành công việc, sử dụng một hoặc hai chức năng công cộng có thể phù hợp với bạn hơn. Lấy công cụ phù hợp cho công việc.


1
Nếu các hàm lớp tĩnh thực sự không khác biệt so với các hàm toàn cục và mục tiêu của bạn là ngăn chặn xung đột không gian tên, tôi thực sự không hiểu sự cần thiết (chưa) để chuyển sang viết plugin dưới dạng các lớp. Ngoài ra, tôi bối rối bởi chức năng bootstrap của người trợ giúp của bạn. Tại sao không chỉ khai báo đối tượng mới là $ new_object = new MyClass ();?
AlxVallejo

@AlxVallejo: Đối với không gian tên một mình, không có sự cần thiết thực sự (như tôi đã viết trong câu trả lời, các phương thức lớp tĩnh khá giống với các hàm toàn cục). Vì vậy, bạn có thể thực hiện không gian tên của riêng bạn (loại không gian tên PHP trước đó là 5.3). Vì vậy, bạn nhận thấy rằng hoàn toàn đúng. Tương tự với chức năng bootstrap tĩnh: Về mặt kỹ thuật là không cần thiết, đơn giản return $myPlugin = new MyPlugin(); cũng làm điều đó. Tuy nhiên, đối với bức tranh lớn hơn, một cái mới đơn giản có thể là không đủ, hãy so sánh Plugin WordPress: Làm thế nào để tôi tránh được việc ghép chặt chẽ chặt chẽ? .
hakre

9

Các lớp chức năng VS


Hiệu suất

Tổng quát: Afaik, không có sự khác biệt về "hiệu suất" giữa các lớp và các bộ chức năng.

Chi tiết:

  • Có một sự khác biệt lớn nếu bạn đặt câu hỏi function_exists()so với class_exists()thông thường, bạn có rất nhiều hàm (~ 1.800 (?) Trong lõi wp) so với các lớp (~ 100 (?) Trong lõi wp). Vì vậy, làm cho công cụ "có thể cắm" và do đó đặt câu hỏi về sự tồn tại một sự khác biệt trong thời gian thực hiện.
  • Các lớp học cung cấp một lợi thế lớn so với các bộ chức năng: Bạn có thể dễ dàng hơn nhiều khi gọi nó theo yêu cầu khi bạn không cần nó, sau đó với các chức năng. Bạn chỉ phải thực hiện kiểm tra có điều kiện cho lớp chứ không phải cho mọi chức năng. Vì vậy, nếu bạn không cần nó trên mỗi lần tải trang và có thể tránh gọi nhiều câu lệnh if / khác, một chức năng "hoạt động tốt hơn".

Kiến trúc - Cách thức hoạt động của công cụ:

Hàm thiết lập: Nói chung, các hàm được thực thi trong hàng bạn gọi nó. Vì vậy, mỗi khi bạn gọi công cụ, bạn phải viết lại, nếu bạn phải gọi nó nhiều lần.

Lớp: Có các aproaches khác nhau cho các lớp. Lớp, gần nhất với một tập hợp hàm là lớp "nhà máy" ( wikipedia / google ). Imo nó gần giống như một tập hợp các hàm, nhưng được gói gọn trong một lớp. Nhưng cũng có những "loại" lớp khác. Ví dụ, bạn có thể viết một lớp trừu tượng hoặc một lớp cha, mà bạn mở rộng với một lớp con. Trong một ví dụ thực tế: giả sử bạn có một lớp xây dựng một số trường văn bản tĩnh. Trong __construct()chức năng của bạn, bạn có một tập hợp các kịch bản như "left_column", "right_column" & "footer_field". Sau đó, bạn gọi một cái gì đó như $text_field = new TextFieldClass();để khởi tạo lớp học. Và sau này bạn chỉ cần gọi $text_field->add( $case => 'left_column', 'case' => 'foo text' );$text_field->add( $case => 'footer_field', 'case' => 'bar text' );. Sau đó, tất cả các điều kiện của bạn và các điều kiện khác đã được thực hiện khi bạn khởi tạo lớp và chỉ hai hàm lớp sẽ được gọi khi bạn xây dựng các trường văn bản. Trong szenario này, bạn có thể đã tiết kiệm được một vài ms thời gian thực hiện.


Ý kiến ​​cá nhân

Nếu bạn viết các lớp học của bạn một cách khôn ngoan, thì bạn sẽ có một lợi thế nhỏ trong hiệu suất. Nhưng bạn sẽ có một cấu trúc được tổ chức tốt để làm việc. Cho đến nay không có gì ngoạn mục. Nhưng nếu bạn xem xét các trường hợp sử dụng "chia" sau cho các lớp và hàm trong một plugin, thì bạn sẽ nhận được điểm cuối cùng của tôi : Lớp là nội bộ, các hàm là API . Miễn là bạn chỉ cung cấp API thông qua các chức năng có thể sử dụng công khai (sau đó gọi các lớp hoặc chức năng lớp), bạn sẽ ở bên lưu trữ phát triển plugin của mình hơn nữa. Bạn có quyền tự do thay đổi cấu trúc bên trong hoặc thậm chí các khả năng của plugin mà không ảnh hưởng đến người dùng mọi lúc và mọi nơi.

Thí dụ:

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

Lưu ý: Vui lòng đọc liên kết @ t 310s được đăng trong bình luận cho Q.


chỉ tò mò, tại sao bạn mong đợi tập tin plugin của bạn được bao gồm nhiều hơn một lần với wordpress?
hakre

@hakre Chính xác thì tôi đã nói điều này ở đâu? Sry, khá mệt mỏi các mẹ ạ.
kaiser

1
@kaiser, tôi giả sử @hakre đang đề cập đến if( ! class_exists )dòng bạn có lúc đầu?
jjeaton

1
@hakre Tôi giả sử @kaiser đang thực hiện class_existskiểm tra không phải vì nó có thể được bao gồm nhiều hơn một lần nhưng để tránh xung đột với một lớp khác?
Michal Mau

Có, tôi đã tự hỏi về class_exists.
hakre

4

Đó là một sự lựa chọn hoàn toàn theo phong cách của tác giả plugin. Không có sự khác biệt thực sự về tốc độ.


1

Các lớp học thường không cung cấp bất kỳ lợi ích nào về hiệu suất, nhưng chúng rất hiếm khi có bất kỳ tác động tiêu cực nào. Lợi ích thực sự của chúng là làm cho mã rõ ràng hơn và tránh xung đột không gian tên.


Tuy nhiên, như @hakre đã đề cập, xung đột không gian tên thực sự không khác biệt khi sử dụng tiền tố trên các hàm toàn cầu. Mã "Cleaner" và ngăn xung đột không gian tên là đồng nghĩa trong trường hợp này, phải không?
AlxVallejo

@AlxVallejo tôi đoán vậy :)
Bai Internet

0

Hầu hết thời gian, nếu bạn sử dụng các hàm, bạn sẽ đặt tên của plugin trong mỗi tên hàm, vì vậy, bạn sẽ nhân đôi tên đó hàng chục lần nếu plugin có hàng tá chức năng. .

Với các lớp, bạn chỉ cần có tên của plugin trong tên lớp có thể một lần.

Ngoài ra, bạn có thể sử dụng tính kế thừa hoặc các cấu trúc oo khác để thực hiện các hành vi một cách rất sạch sẽ. Đây là một ví dụ:

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();
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.