Software Development Principles for WordPress Plugins: LoD, SoC, SOLID, and More

Understanding and applying these principles will help you write cleaner, more maintainable WordPress plugin code. Here’s a detailed look at key software development principles with before-and-after PHP examples for WordPress developers:

1. Abstraction

Abstraction allows you to focus on what is necessary and hide underlying complexity. It’s used everywhere, like when WordPress abstracts database interactions through $wpdb.

Before:

global $wpdb;
$results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}posts WHERE post_status = 'publish'");
foreach ($results as $post) {
    echo $post->post_title;
}        

After (Abstraction Applied):

function get_published_posts() {
    global $wpdb;
    return $wpdb->get_results("SELECT * FROM {$wpdb->prefix}posts WHERE post_status = 'publish'");
}

$posts = get_published_posts();
foreach ($posts as $post) {
    echo $post->post_title;
}        

2. Encapsulate What Varies

Isolate parts of your code that may change so they can be modified without affecting other parts.

Before:

if ($baseCurrency == 'USD' && $targetCurrency == 'EUR') {
    return $amount * 0.90;
}
if ($baseCurrency == 'USD' && $targetCurrency == 'GBP') {
    return $amount * 0.80;
}        

After (Encapsulation Applied):

function convert_currency($amount, $baseCurrency, $targetCurrency) {
    $conversion_rates = [
        'USD_EUR' => 0.90,
        'USD_GBP' => 0.80,
    ];
    $key = $baseCurrency . '_' . $targetCurrency;
    return isset($conversion_rates[$key]) ? $amount * $conversion_rates[$key] : $amount;
}        

3. DRY (Don’t Repeat Yourself)

Avoid code duplication by reusing common logic through functions or classes.

Before:

$meta_value1 = get_post_meta($post_id, '_meta_key1', true);
$meta_value2 = get_post_meta($post_id, '_meta_key2', true);
$meta_value3 = get_post_meta($post_id, '_meta_key3', true);        

After (DRY Applied):

function get_custom_meta($post_id, $keys) {
    $meta_values = [];
    foreach ($keys as $key) {
        $meta_values[$key] = get_post_meta($post_id, $key, true);
    }
    return $meta_values;
}

$meta_values = get_custom_meta($post_id, ['_meta_key1', '_meta_key2', '_meta_key3']);        

4. KISS (Keep It Simple, Stupid)

Avoid complex solutions when simpler ones suffice.

Before (Complex Solution):

function check_user_access() {
    if (is_user_logged_in() && current_user_can('manage_options') && !is_admin() && wp_get_current_user()->user_login == 'admin') {
        return true;
    }
    return false;
}        

After (KISS Applied):

function check_user_access() {
    return current_user_can('manage_options');
}        

5. YAGNI (You Aren’t Gonna Need It)

Don’t add features until you actually need them.

Before:

function calculate_price($amount, $tax, $discount = 0, $future_feature = null) {
    // Future feature not needed yet
    return ($amount + $tax) - $discount;
}        

After (YAGNI Applied):

function calculate_price($amount, $tax, $discount = 0) {
    return ($amount + $tax) - $discount;
}        

6. Law of Demeter (LoD)

Minimize interactions with objects that are not directly related.

Before (Violation):

$wallet_balance = $customer->get_wallet()->get_balance();        

After (LoD Applied):

$wallet_balance = $customer->get_wallet_balance(); // Encapsulates wallet access in Customer        

7. Separation of Concerns (SoC)

Split your code into distinct sections, each with its own responsibility.

Before (Single Function):

function process_order_and_notify($order_id) {
    $order = wc_get_order($order_id);
    // Process order logic
    wp_mail($order->get_billing_email(), 'Order Update', 'Your order has been processed.');
}        

After (SoC Applied):

class OrderProcessor {
    public function process_order($order_id) {
        $order = wc_get_order($order_id);
        // Process order logic
        return $order;
    }
}

class NotificationSender {
    public function send_order_notification($email, $message) {
        wp_mail($email, 'Order Update', $message);
    }
}

$orderProcessor = new OrderProcessor();
$order = $orderProcessor->process_order($order_id);

$notificationSender = new NotificationSender();
$notificationSender->send_order_notification($order->get_billing_email(), 'Your order has been processed.');        

8. SOLID Principles for WordPress Development

  • Single Responsibility Principle (SRP):

class Logger {
    public function log($message) {
        error_log($message);
    }
}        

  • Open/Closed Principle (OCP):

interface Discount {
    public function apply($amount);
}

class FixedDiscount implements Discount {
    public function apply($amount) {
        return $amount - 10; // Fixed discount logic
    }
}

class PercentageDiscount implements Discount {
    public function apply($amount) {
        return $amount * 0.9; // 10% discount logic
    }
}        

  • Liskov Substitution Principle (LSP):

abstract class BaseWidget {
    abstract public function render();
}

class TextWidget extends BaseWidget {
    public function render() {
        echo 'Rendering Text Widget';
    }
}        

  • Interface Segregation Principle (ISP):

interface Renderable {
    public function render();
}

interface Exportable {
    public function export();
}        

  • Dependency Inversion Principle (DIP):

interface DataSource {
    public function getData();
}

class DatabaseSource implements DataSource {
    public function getData() {
        // Fetch data from DB
    }
}

class PluginService {
    private $dataSource;

    public function __construct(DataSource $dataSource) {
        $this->dataSource = $dataSource;
    }
}        

9. GRASP Patterns in WordPress

  • High Cohesion & Low Coupling:

class PostManager {
    public function create_post($title, $content) {
        return wp_insert_post(['post_title' => $title, 'post_content' => $content]);
    }
}        

  • Controller Pattern:

class AdminController {
    public function handle_save_settings() {
        // Logic to handle settings save
    }
}        

  • Indirection & Pure Fabrication:

class DataHelper {
    public function sanitize_input($input) {
        return sanitize_text_field($input);
    }
}        

Conclusion: These principles will help you write better, more maintainable, and scalable WordPress plugins. Mastering them sets you apart as a developer committed to quality and longevity in your code.

要查看或添加评论,请登录

Dev Kabir的更多文章