← Back to Architecture Principles
S
SOLID Principles for WordPress Development
Single Responsibility Principle in WordPress
A class should have one, and only one, reason to change
The Single Responsibility Principle is the cornerstone of maintainable WordPress development. When a component has multiple responsibilities, changes to one responsibility can impact or break the others, creating tight coupling and fragile code.
Clean Code
Modular Plugins
Scalable Themes
Core Concept
Each software module, class, or function should have one reason to change. This means it should have only one job or responsibility within the system.
When you need to modify code for a specific reason (e.g., changing how data is saved), that change should only affect one module. If changing the save logic also requires changing email notifications or report generation, you’ve violated SRP.
Practical Examples for WordPress Developers
Landing pages, Blogs, Small business sites
Bad Example
// ❌ Bad: One function doing everything
function handle_contact_form() {
if (empty($_POST['email']) || !is_email($_POST['email'])) {
wp_die('Invalid email');
}
wp_mail(get_option('admin_email'), 'New Contact', $_POST['message']);
global $wpdb;
$wpdb->insert('wp_contacts', [
'email' => $_POST['email'],
'message' => $_POST['message']
]);
wp_cache_delete('contact_count');
}
Good Example
// ✅ Good: Separated responsibilities
function handle_contact_form() {
$data = validate_contact_data($_POST);
if (is_wp_error($data)) return $data;
send_contact_notification($data);
save_contact_entry($data);
invalidate_contact_cache();
}
function validate_contact_data($input) { /* ... */ }
function send_contact_notification($data) { /* ... */ }
function save_contact_entry($data) { /* ... */ }
function invalidate_contact_cache() { /* ... */ }
Benefits
- Easy to debug — each function has clear purpose
- Simple to test independently
- Can swap email provider without touching validation
Multi-site, custom APIs, complex business logic
Bad Example
// ❌ Bad: Monolithic service class
class OrderService {
public function process($order) {
$this->validate($order);
$this->chargePayment($order);
$this->updateInventory($order);
$this->sendEmails($order);
$this->logToCrm($order);
$this->syncToWarehouse($order);
}
}
Good Example
// ✅ Good: Orchestrator + single-purpose services
class OrderOrchestrator {
public function __construct(
OrderValidator $validator,
PaymentGateway $payment,
InventoryService $inventory,
NotificationService $notify,
CrmSync $crm,
WarehouseSync $warehouse
) { /* ... */ }
public function process($order) {
$this->validator->validate($order);
$this->payment->charge($order);
$this->inventory->update($order);
$this->notify->send($order);
$this->crm->log($order);
$this->warehouse->sync($order);
}
}
Benefits
- Each service can be tested and replaced independently
- Clear boundaries for scaling and ownership
Actions and filters: one responsibility per callback
Bad Example
// ❌ Bad: One hook does everything
add_action('save_post', function($post_id) {
if (wp_is_post_revision($post_id)) return;
update_post_meta($post_id, '_seo_title', $_POST['seo_title']);
$this->generate_sitemap();
$this->purge_cdn_cache();
$this->notify_slack('Post saved');
});
Good Example
// ✅ Good: One concern per hook
add_action('save_post', 'save_seo_meta', 10, 1);
add_action('save_post', 'regenerate_sitemap', 20, 1);
add_action('save_post', 'purge_cdn_on_save', 30, 1);
add_action('save_post', 'notify_team_on_publish', 40, 1);
Benefits
- Easier to remove or reorder behavior; clear execution order
- Each callback is testable in isolation
Real-World Case Study: 4WP Bundle
Learn from real WordPress plugin architecture — comparing monolithic vs. modular approaches
SRP Violation: Monolithic Bundle
Context: While the 4WP Bundle violates SRP, it may be appropriate for other architectural patterns and use cases (see below)
The 4WP Bundle plugin demonstrates what happens when you violate SRP — it tries to handle multiple features in one codebase:
Responsibilities mixed together:
- Responsive controls for Gutenberg blocks
- FAQ management system
- Custom Gutenberg extensions
- Settings management across features
// Problems with this approach:
• Can't update FAQ without risking responsive features
• All features load even if you need just one
• Hard to maintain and test
• Code conflicts between unrelated features
Best Practice: Modular Plugins
Following SRP, each feature becomes an independent plugin with a single, clear responsibility:
// Benefits of SRP approach:
✓ Update FAQ independently from responsive features
✓ Load only plugins you need
✓ Easy to test and maintain each plugin
✓ No conflicts between separate features
Key Takeaways for WordPress Developers
Better Performance
Load only what you need, reduce bloat
Easier Maintenance
Fix bugs without touching unrelated code
User Choice
Users activate only features they need
When Bundle Approach Makes Sense
While the Bundle violates SRP, it can be appropriate for other architectural patterns and scenarios:
Facade Pattern
Provides unified interface to multiple subsystems — simplifies complex functionality behind single entry point
Starter Kit / Boilerplate
Quick start for developers who need all features initially, then can split later as project grows
Dependency Management
Ensures compatible versions of related plugins work together without conflicts
Education / Demo Projects
Shows how different features can work together in one codebase for learning purposes
Prototype / MVP Development
Faster initial development when you need to test multiple features quickly before committing to architecture
Plugin Ecosystem Management
Central control of related features with shared settings, licensing, and update mechanism
The key is knowing when to use which approach: SRP for long-term maintainability, Bundle for rapid prototyping or simplified distribution
Key Takeaways for WordPress Developers
Better Performance
Load only what you need, reduce bloat
Easier Maintenance
Fix bugs without touching unrelated code
User Choice
Users activate only features they need
When Bundle Approach Makes Sense
While the Bundle violates SRP, it can be appropriate for other architectural patterns and scenarios:
Facade Pattern
Provides unified interface to multiple subsystems — simplifies complex functionality behind single entry point
Starter Kit / Boilerplate
Quick start for developers who need all features initially, then can split later as project grows
Dependency Management
Ensures compatible versions of related plugins work together without conflicts
Education / Demo Projects
Shows how different features can work together in one codebase for learning purposes
Prototype / MVP Development
Faster initial development when you need to test multiple features quickly before committing to architecture
Plugin Ecosystem Management
Central control of related features with shared settings, licensing, and update mechanism
The key is knowing when to use which approach: SRP for long-term maintainability, Bundle for rapid prototyping or simplified distribution
When to Apply SRP in Your WordPress Projects
Writing Custom Functions
Each function should do one thing well — validate data, send emails, or update database, but not all three
“If you can’t explain what a function does in one simple sentence, it’s doing too much”
Building Plugins
Create focused plugins that solve one problem, not Swiss Army knife plugins that try to do everything
“A good plugin is like a good tool — it has one clear purpose”
Organizing Theme Code
Split your functions.php into focused files: custom-post-types.php, theme-setup.php, enqueue-scripts.php
“Organization by responsibility makes code maintainable”
Common Mistakes in WordPress Development
Avoid these frequent SRP violations that WordPress developers encounter
God Classes
Creating classes that do everything (UserManager handles DB, emails, validation, reports)
Solution:
Split into UserRepository, EmailService, UserValidator, ReportGenerator
Mixed Concerns in Functions
Functions that validate, process, and present data all in one
Solution:
Separate validation, business logic, and presentation layers
Bloated functions.php
Putting all theme functionality in one functions.php file
Solution:
Organize into /inc/ directory: post-types.php, assets.php, customizer.php
Multi-purpose Hooks
One hook callback doing many unrelated tasks
Solution:
Create separate, focused callbacks for each task
Warning Signs in Your WordPress Code
Watch for these red flags that indicate SRP violations
Class/function names with “and” or “Manager” (SaveAndEmailManager)
Difficulty naming because it does too much
Functions longer than 50 lines doing multiple things
Changes in one feature breaking unrelated features
Hard to write tests due to too many dependencies
The word “also” appears in your function description
Frequently Asked Questions
A: No, SRP is about responsibility, not file count. You can have multiple related functions in one file as long as they serve the same high-level responsibility. For example, all post validation functions can live in post-validation.php, while email functions go in email-notifications.php.
A: Instead of one callback doing everything, create multiple focused callbacks. For example, on save_post, use separate functions for validation, notification, caching, and analytics — each attached to the same hook but handling one responsibility.
A: No, modern PHP handles function calls efficiently. The real performance killer is poorly written monolithic code that does unnecessary work. Well-organized code following SRP is easier to optimize because you can identify and improve bottlenecks without touching unrelated functionality.
A: Apply the Boy Scout Rule — “leave code better than you found it.” When you need to modify existing code, refactor that section to follow SRP. Don’t attempt massive rewrites, but gradually improve code as you work with it. Focus on new features being SRP-compliant from the start.
A: WordPress hooks are perfect for SRP! Each hook callback should handle one specific task. Use do_action() to notify other parts of your code about events, allowing different responsibilities to respond independently. This creates loose coupling and high cohesion.
A: Even small sites benefit from SRP, but the implementation scale differs. For a simple blog, separating validation from email sending in your contact form is enough. You don’t need complex class hierarchies — simple, focused functions work great and make your theme easier to maintain as the site grows.